@kafitra/lynx-storage 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +196 -0
  2. package/android/build/.transforms/57b45319aa48ed838ae9c1d47b5c9e46/results.bin +1 -0
  3. package/android/build/.transforms/57b45319aa48ed838ae9c1d47b5c9e46/transformed/debug/com/kafitra/lynxstorage/LynxStorageModule.dex +0 -0
  4. package/android/build/.transforms/57b45319aa48ed838ae9c1d47b5c9e46/transformed/debug/desugar_graph.bin +0 -0
  5. package/android/build/.transforms/8b0ebf77b1668e7a22dbb51308dd3b00/results.bin +1 -0
  6. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/AndroidManifest.xml +7 -0
  7. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/output-metadata.json +18 -0
  8. package/android/build/intermediates/aar_metadata/debug/aar-metadata.properties +5 -0
  9. package/android/build/intermediates/annotation_processor_list/debug/annotationProcessors.json +1 -0
  10. package/android/build/intermediates/compile_library_classes_jar/debug/classes.jar +0 -0
  11. package/android/build/intermediates/compile_r_class_jar/debug/R.jar +0 -0
  12. package/android/build/intermediates/compile_symbol_list/debug/R.txt +0 -0
  13. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -0
  14. package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
  15. package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
  16. package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
  17. package/android/build/intermediates/incremental/packageDebugAssets/merger.xml +2 -0
  18. package/android/build/intermediates/javac/debug/classes/com/kafitra/lynxstorage/LynxStorageModule.class +0 -0
  19. package/android/build/intermediates/local_only_symbol_list/debug/R-def.txt +2 -0
  20. package/android/build/intermediates/manifest_merge_blame_file/debug/manifest-merger-blame-debug-report.txt +7 -0
  21. package/android/build/intermediates/merged_manifest/debug/AndroidManifest.xml +7 -0
  22. package/android/build/intermediates/navigation_json/debug/navigation.json +1 -0
  23. package/android/build/intermediates/runtime_library_classes_dir/debug/com/kafitra/lynxstorage/LynxStorageModule.class +0 -0
  24. package/android/build/intermediates/runtime_library_classes_jar/debug/classes.jar +0 -0
  25. package/android/build/intermediates/symbol_list_with_package_name/debug/package-aware-r.txt +1 -0
  26. package/android/build/outputs/logs/manifest-merger-debug-report.txt +16 -0
  27. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  28. package/android/build.gradle +21 -0
  29. package/android/src/main/java/com/kafitra/lynxstorage/LynxStorageModule.java +115 -0
  30. package/dist/index.d.ts +15 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +14 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/native.d.ts +8 -0
  35. package/dist/native.d.ts.map +1 -0
  36. package/dist/native.js +10 -0
  37. package/dist/native.js.map +1 -0
  38. package/dist/types.d.ts +21 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +2 -0
  41. package/dist/types.js.map +1 -0
  42. package/ios/LynxStorageModule.h +20 -0
  43. package/ios/LynxStorageModule.m +102 -0
  44. package/lynx.module.json +7 -0
  45. package/package.json +42 -0
package/README.md ADDED
@@ -0,0 +1,196 @@
1
+ <div align="center">
2
+
3
+ # @kafitra/lynx-storage
4
+
5
+ **Persistent key-value storage native module for [Lynx](https://lynxjs.org/).**
6
+
7
+ Backed by **Android SharedPreferences** and **iOS NSUserDefaults** — data survives app restarts.
8
+
9
+ [![npm](https://img.shields.io/npm/v/@kafitra/lynx-storage?color=blue)](https://www.npmjs.com/package/@kafitra/lynx-storage)
10
+ [![Platform](https://img.shields.io/badge/Platform-Android%20%7C%20iOS-brightgreen.svg)]()
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](../../LICENSE)
12
+
13
+ </div>
14
+
15
+ ---
16
+
17
+ ## Overview
18
+
19
+ `@kafitra/lynx-storage` exposes a synchronous native key-value store to the Lynx JS runtime via `NativeModules.LynxStorage`. It is the persistence layer used by [`@kafitra/lynx-async-storage`](../lynx-async-storage) when running inside a Lynx app.
20
+
21
+ | Platform | Implementation | Storage file / suite |
22
+ | -------- | ------------------- | ------------------------- |
23
+ | Android | `SharedPreferences` | `kafitra_lynx_storage` |
24
+ | iOS | `NSUserDefaults` | `com.kafitra.lynxstorage` |
25
+
26
+ ---
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ npm install @kafitra/lynx-storage
32
+ # or
33
+ pnpm add @kafitra/lynx-storage
34
+ ```
35
+
36
+ ---
37
+
38
+ ## Android Setup
39
+
40
+ ### 1. Auto-link (recommended)
41
+
42
+ Run the Kafitra CLI linker from your app directory:
43
+
44
+ ```bash
45
+ npx @kafitra/lynx-cli link
46
+ ```
47
+
48
+ This auto-generates `LynxAutolinkRegistry.java` and injects Gradle wiring.
49
+
50
+ ### 2. Register in your Application class
51
+
52
+ ```java
53
+ // LynxApplication.java (or wherever you init LynxEnv)
54
+ import com.kafitra.demo.LynxAutolinkRegistry;
55
+
56
+ LynxEnv.inst().init(this, null, null, null);
57
+ LynxAutolinkRegistry.registerAll(); // ← registers LynxStorageModule
58
+ ```
59
+
60
+ ### 3. Manual setup (without CLI)
61
+
62
+ If you prefer not to use the CLI, add these entries manually:
63
+
64
+ **`android/settings.gradle`**
65
+
66
+ ```groovy
67
+ include ':lynx-storage'
68
+ project(':lynx-storage').projectDir = new File(rootDir, '../node_modules/@kafitra/lynx-storage/android')
69
+ ```
70
+
71
+ **`android/app/build.gradle`**
72
+
73
+ ```groovy
74
+ dependencies {
75
+ implementation project(':lynx-storage')
76
+ }
77
+ ```
78
+
79
+ **`LynxAutolinkRegistry.java`** (or your Application init)
80
+
81
+ ```java
82
+ import com.kafitra.lynxstorage.LynxStorageModule;
83
+
84
+ LynxEnv.inst().registerModule("LynxStorage", LynxStorageModule.class);
85
+ ```
86
+
87
+ ---
88
+
89
+ ## iOS Setup
90
+
91
+ ### Register in your host app
92
+
93
+ ```objc
94
+ // In your LynxInitProcessor or AppDelegate, before creating any Lynx view:
95
+ #import "LynxStorageModule.h"
96
+
97
+ [globalConfig registerModule:LynxStorageModule.class];
98
+ ```
99
+
100
+ ---
101
+
102
+ ## JavaScript API
103
+
104
+ The module is exposed on the Lynx `NativeModules` global as `NativeModules.LynxStorage`:
105
+
106
+ ```ts
107
+ declare const NativeModules: {
108
+ LynxStorage: {
109
+ getString(key: string): string | null;
110
+ setString(key: string, value: string): void;
111
+ remove(key: string): void;
112
+ clear(): void;
113
+ getAllKeys(): string; // JSON array string, e.g. '["a","b"]'
114
+ };
115
+ };
116
+ ```
117
+
118
+ ### Direct usage (TypeScript)
119
+
120
+ ```ts
121
+ import { LynxStorage } from "@kafitra/lynx-storage";
122
+
123
+ // Read
124
+ const value = LynxStorage.getString("token"); // string | null
125
+
126
+ // Write
127
+ LynxStorage.setString("token", "abc123");
128
+
129
+ // Delete
130
+ LynxStorage.remove("token");
131
+
132
+ // Clear everything
133
+ LynxStorage.clear();
134
+
135
+ // Get all keys
136
+ const keys = JSON.parse(LynxStorage.getAllKeys()); // string[]
137
+ ```
138
+
139
+ > **Tip:** All methods are **synchronous**. If you prefer a Promise-based API, use [`@kafitra/lynx-async-storage`](https://www.npmjs.com/package/@kafitra/lynx-async-storage) — it auto-detects and wraps this module.
140
+
141
+ ---
142
+
143
+ ## With @kafitra/lynx-async-storage
144
+
145
+ Install both packages in your app:
146
+
147
+ ```bash
148
+ pnpm add @kafitra/lynx-storage @kafitra/lynx-async-storage
149
+ ```
150
+
151
+ Then use `@kafitra/lynx-async-storage` in your code — it will automatically use `LynxStorage` as its backend:
152
+
153
+ ```ts
154
+ import AsyncStorage from "@kafitra/lynx-async-storage";
155
+
156
+ await AsyncStorage.setItem("session", JSON.stringify({ user: "demo" }));
157
+ const session = await AsyncStorage.getItem("session");
158
+ ```
159
+
160
+ No extra configuration needed. `@kafitra/lynx-async-storage` detects `NativeModules.LynxStorage` at runtime and uses it automatically.
161
+
162
+ ---
163
+
164
+ ## `lynx.module.json`
165
+
166
+ This file is used by `@kafitra/lynx-autolink` for auto-linking:
167
+
168
+ ```json
169
+ {
170
+ "name": "LynxStorage",
171
+ "android": {
172
+ "moduleClass": "com.kafitra.lynxstorage.LynxStorageModule",
173
+ "sourceDir": "android"
174
+ }
175
+ }
176
+ ```
177
+
178
+ ---
179
+
180
+ ## Monorepo / Workspace
181
+
182
+ If you're using this in a monorepo with `pnpm workspaces`:
183
+
184
+ ```json
185
+ {
186
+ "dependencies": {
187
+ "@kafitra/lynx-storage": "workspace:*"
188
+ }
189
+ }
190
+ ```
191
+
192
+ ---
193
+
194
+ ## License
195
+
196
+ MIT © [Kafitra Marna](https://github.com/kafitramarna)
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ package="com.kafitra.lynxstorage" >
4
+
5
+ <uses-sdk android:minSdkVersion="21" />
6
+
7
+ </manifest>
@@ -0,0 +1,18 @@
1
+ {
2
+ "version": 3,
3
+ "artifactType": {
4
+ "type": "AAPT_FRIENDLY_MERGED_MANIFESTS",
5
+ "kind": "Directory"
6
+ },
7
+ "applicationId": "com.kafitra.lynxstorage",
8
+ "variantName": "debug",
9
+ "elements": [
10
+ {
11
+ "type": "SINGLE",
12
+ "filters": [],
13
+ "attributes": [],
14
+ "outputFile": "AndroidManifest.xml"
15
+ }
16
+ ],
17
+ "elementType": "File"
18
+ }
@@ -0,0 +1,5 @@
1
+ aarFormatVersion=1.0
2
+ aarMetadataVersion=1.0
3
+ minCompileSdk=1
4
+ minCompileSdkExtension=0
5
+ minAndroidGradlePluginVersion=1.0.0
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\src\main\res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main" generated-set="main$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\src\main\res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\src\debug\res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug" generated-set="debug$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\src\debug\res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\generated\res\resValues\debug"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated" generated-set="generated$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\generated\res\resValues\debug"/></dataSet><mergedItems/></merger>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\src\main\jniLibs"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\src\debug\jniLibs"/></dataSet></merger>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\src\main\shaders"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\src\debug\shaders"/></dataSet></merger>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\src\main\assets"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\src\debug\assets"/></dataSet><dataSet config="generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\intermediates\shader_assets\debug\out"/></dataSet></merger>
@@ -0,0 +1,2 @@
1
+ R_DEF: Internal format may change without notice
2
+ local
@@ -0,0 +1,7 @@
1
+ 1<?xml version="1.0" encoding="utf-8"?>
2
+ 2<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ 3 package="com.kafitra.lynxstorage" >
4
+ 4
5
+ 5 <uses-sdk android:minSdkVersion="21" />
6
+ 6
7
+ 7</manifest>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ package="com.kafitra.lynxstorage" >
4
+
5
+ <uses-sdk android:minSdkVersion="21" />
6
+
7
+ </manifest>
@@ -0,0 +1,16 @@
1
+ -- Merging decision tree log ---
2
+ manifest
3
+ ADDED from C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\intermediates\tmp\ProcessLibraryManifest\debug\tempAndroidManifest15751414143782047258.xml:2:13-83
4
+ INJECTED from C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\intermediates\tmp\ProcessLibraryManifest\debug\tempAndroidManifest15751414143782047258.xml:2:13-83
5
+ package
6
+ INJECTED from C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\intermediates\tmp\ProcessLibraryManifest\debug\tempAndroidManifest15751414143782047258.xml
7
+ xmlns:android
8
+ ADDED from C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\intermediates\tmp\ProcessLibraryManifest\debug\tempAndroidManifest15751414143782047258.xml:2:23-81
9
+ uses-sdk
10
+ INJECTED from C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\intermediates\tmp\ProcessLibraryManifest\debug\tempAndroidManifest15751414143782047258.xml reason: use-sdk injection requested
11
+ INJECTED from C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\intermediates\tmp\ProcessLibraryManifest\debug\tempAndroidManifest15751414143782047258.xml
12
+ INJECTED from C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\intermediates\tmp\ProcessLibraryManifest\debug\tempAndroidManifest15751414143782047258.xml
13
+ android:targetSdkVersion
14
+ INJECTED from C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\intermediates\tmp\ProcessLibraryManifest\debug\tempAndroidManifest15751414143782047258.xml
15
+ android:minSdkVersion
16
+ INJECTED from C:\Users\HYPE AMD\Documents\Coding\lynx\kafitra-lynx-native\apps\demo2\node_modules\@kafitra\lynx-storage\android\build\intermediates\tmp\ProcessLibraryManifest\debug\tempAndroidManifest15751414143782047258.xml
@@ -0,0 +1,21 @@
1
+ apply plugin: 'com.android.library'
2
+
3
+ android {
4
+ namespace 'com.kafitra.lynxstorage'
5
+ compileSdkVersion 34
6
+
7
+ defaultConfig {
8
+ minSdkVersion 21
9
+ targetSdkVersion 34
10
+ }
11
+
12
+ compileOptions {
13
+ sourceCompatibility JavaVersion.VERSION_1_8
14
+ targetCompatibility JavaVersion.VERSION_1_8
15
+ }
16
+ }
17
+
18
+ dependencies {
19
+ // Provided at runtime by the host app — compileOnly to avoid duplicate classes
20
+ compileOnly "org.lynxsdk.lynx:lynx:3.6.0"
21
+ }
@@ -0,0 +1,115 @@
1
+ package com.kafitra.lynxstorage;
2
+
3
+ import android.content.Context;
4
+ import android.content.SharedPreferences;
5
+
6
+ import com.lynx.jsbridge.LynxModule;
7
+ import com.lynx.jsbridge.LynxMethod;
8
+
9
+ import org.json.JSONArray;
10
+
11
+ import java.util.Map;
12
+
13
+ /**
14
+ * LynxStorageModule — persistent key-value storage backed by SharedPreferences.
15
+ *
16
+ * Provides synchronous access to Android SharedPreferences through the
17
+ * Lynx Native Module system.
18
+ *
19
+ * <h3>Registration (in your host app):</h3>
20
+ * <pre>
21
+ * LynxEnv.inst().registerModule("LynxStorage", LynxStorageModule.class);
22
+ * </pre>
23
+ *
24
+ * <p>All values are stored as Strings under the shared preferences file
25
+ * {@code kafitra_lynx_storage}.</p>
26
+ */
27
+ public class LynxStorageModule extends LynxModule {
28
+
29
+ private static final String PREFS_NAME = "kafitra_lynx_storage";
30
+ private final Context mContext;
31
+
32
+ public LynxStorageModule(Context context) {
33
+ super(context);
34
+ this.mContext = context;
35
+ }
36
+
37
+ private SharedPreferences prefs() {
38
+ return mContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
39
+ }
40
+
41
+ /**
42
+ * Returns the string stored under {@code key}, or {@code null} when absent.
43
+ *
44
+ * @param key Storage key
45
+ * @return Stored value or null
46
+ */
47
+ @LynxMethod
48
+ public String getString(String key) {
49
+ try {
50
+ SharedPreferences sp = prefs();
51
+ if (!sp.contains(key)) return null;
52
+ return sp.getString(key, null);
53
+ } catch (Exception e) {
54
+ return null;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Stores {@code value} under {@code key}.
60
+ *
61
+ * @param key Storage key
62
+ * @param value String value to persist
63
+ */
64
+ @LynxMethod
65
+ public void setString(String key, String value) {
66
+ try {
67
+ prefs().edit().putString(key, value).apply();
68
+ } catch (Exception ignored) {
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Removes the entry for {@code key}. No-op when the key is absent.
74
+ *
75
+ * @param key Storage key to remove
76
+ */
77
+ @LynxMethod
78
+ public void remove(String key) {
79
+ try {
80
+ prefs().edit().remove(key).apply();
81
+ } catch (Exception ignored) {
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Removes all entries from the storage namespace.
87
+ */
88
+ @LynxMethod
89
+ public void clear() {
90
+ try {
91
+ prefs().edit().clear().apply();
92
+ } catch (Exception ignored) {
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Returns a JSON array string of all stored keys, e.g. {@code ["a","b","c"]}.
98
+ * Returns {@code "[]"} when storage is empty.
99
+ *
100
+ * @return JSON-encoded string array
101
+ */
102
+ @LynxMethod
103
+ public String getAllKeys() {
104
+ try {
105
+ Map<String, ?> all = prefs().getAll();
106
+ JSONArray arr = new JSONArray();
107
+ for (String key : all.keySet()) {
108
+ arr.put(key);
109
+ }
110
+ return arr.toString();
111
+ } catch (Exception e) {
112
+ return "[]";
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @kafitra/lynx-storage
3
+ *
4
+ * Public API — thin wrappers that surfaced the raw native module.
5
+ *
6
+ * Usage:
7
+ *
8
+ * import { LynxStorage } from '@kafitra/lynx-storage';
9
+ *
10
+ * LynxStorage.setString('key', 'value');
11
+ * const val = LynxStorage.getString('key'); // string | null
12
+ */
13
+ export { NativeStorage as LynxStorage } from "./native";
14
+ export type { NativeLynxStorage } from "./types";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,UAAU,CAAC;AACxD,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @kafitra/lynx-storage
3
+ *
4
+ * Public API — thin wrappers that surfaced the raw native module.
5
+ *
6
+ * Usage:
7
+ *
8
+ * import { LynxStorage } from '@kafitra/lynx-storage';
9
+ *
10
+ * LynxStorage.setString('key', 'value');
11
+ * const val = LynxStorage.getString('key'); // string | null
12
+ */
13
+ export { NativeStorage as LynxStorage } from "./native";
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @kafitra/lynx-storage
3
+ *
4
+ * Native module access layer.
5
+ */
6
+ import type { NativeLynxStorage } from "./types";
7
+ export declare const NativeStorage: NativeLynxStorage;
8
+ //# sourceMappingURL=native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAiBjD,eAAO,MAAM,aAAa,EAAE,iBAAqC,CAAC"}
package/dist/native.js ADDED
@@ -0,0 +1,10 @@
1
+ function getNativeModule() {
2
+ if (!NativeModules?.LynxStorage) {
3
+ throw new Error("[@kafitra/lynx-storage] Native module not linked. " +
4
+ "Register LynxStorageModule in your Android host:\n\n" +
5
+ ' LynxEnv.inst().registerModule("LynxStorage", LynxStorageModule.class);');
6
+ }
7
+ return NativeModules.LynxStorage;
8
+ }
9
+ export const NativeStorage = getNativeModule();
10
+ //# sourceMappingURL=native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.js","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAWA,SAAS,eAAe;IACtB,IAAI,CAAC,aAAa,EAAE,WAAW,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACb,oDAAoD;YAClD,sDAAsD;YACtD,0EAA0E,CAC7E,CAAC;IACJ,CAAC;IACD,OAAO,aAAa,CAAC,WAAW,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAsB,eAAe,EAAE,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @kafitra/lynx-storage
3
+ *
4
+ * Raw shape of the LynxStorage native module as exposed through
5
+ * NativeModules by the Lynx runtime.
6
+ *
7
+ * All methods are synchronous at the native layer.
8
+ */
9
+ export interface NativeLynxStorage {
10
+ /** Returns the stored string, or null when absent. */
11
+ getString(key: string): string | null;
12
+ /** Stores a string value. */
13
+ setString(key: string, value: string): void;
14
+ /** Removes a single entry. */
15
+ remove(key: string): void;
16
+ /** Clears the entire storage namespace. */
17
+ clear(): void;
18
+ /** Returns all stored keys as a JSON array string, e.g. '["a","b"]'. */
19
+ getAllKeys(): string;
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAEtC,6BAA6B;IAC7B,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5C,8BAA8B;IAC9B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B,2CAA2C;IAC3C,KAAK,IAAI,IAAI,CAAC;IAEd,wEAAwE;IACxE,UAAU,IAAI,MAAM,CAAC;CACtB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @kafitra/lynx-storage
3
+ *
4
+ * iOS native module — persists key-value pairs in NSUserDefaults.
5
+ *
6
+ * Registration (in your LynxInitProcessor or app delegate):
7
+ *
8
+ * #import "LynxStorageModule.h"
9
+ * [globalConfig registerModule:LynxStorageModule.class];
10
+ */
11
+
12
+ #import <Foundation/Foundation.h>
13
+ #import <Lynx/LynxModule.h>
14
+
15
+ NS_ASSUME_NONNULL_BEGIN
16
+
17
+ @interface LynxStorageModule : NSObject <LynxModule>
18
+ @end
19
+
20
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,102 @@
1
+ #import "LynxStorageModule.h"
2
+
3
+ // NSUserDefaults suite name – isolates keys from app defaults
4
+ static NSString *const kSuiteName = @"com.kafitra.lynxstorage";
5
+
6
+ @implementation LynxStorageModule
7
+
8
+ // ---------------------------------------------------------------------------
9
+ // Lynx module identity
10
+ // ---------------------------------------------------------------------------
11
+
12
+ + (NSString *)name {
13
+ return @"LynxStorage";
14
+ }
15
+
16
+ // ---------------------------------------------------------------------------
17
+ // Method lookup — maps JS method names to Objective-C selectors
18
+ // ---------------------------------------------------------------------------
19
+
20
+ + (NSDictionary<NSString *, NSString *> *)methodLookup {
21
+ return @{
22
+ @"getString": NSStringFromSelector(@selector(getString:)),
23
+ @"setString": NSStringFromSelector(@selector(setString:value:)),
24
+ @"remove": NSStringFromSelector(@selector(remove:)),
25
+ @"clear": NSStringFromSelector(@selector(clear)),
26
+ @"getAllKeys": NSStringFromSelector(@selector(getAllKeys)),
27
+ };
28
+ }
29
+
30
+ // ---------------------------------------------------------------------------
31
+ // Helpers
32
+ // ---------------------------------------------------------------------------
33
+
34
+ - (NSUserDefaults *)defaults {
35
+ NSUserDefaults *d = [[NSUserDefaults alloc] initWithSuiteName:kSuiteName];
36
+ return d ?: [NSUserDefaults standardUserDefaults];
37
+ }
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Method implementations
41
+ // ---------------------------------------------------------------------------
42
+
43
+ /**
44
+ * Returns the stored string for @p key, or nil when absent.
45
+ */
46
+ - (nullable NSString *)getString:(NSString *)key {
47
+ @try {
48
+ return [[self defaults] stringForKey:key];
49
+ } @catch (NSException *e) {
50
+ return nil;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Persists @p value under @p key.
56
+ */
57
+ - (void)setString:(NSString *)key value:(NSString *)value {
58
+ @try {
59
+ [[self defaults] setObject:value forKey:key];
60
+ [[self defaults] synchronize];
61
+ } @catch (NSException *e) { }
62
+ }
63
+
64
+ /**
65
+ * Removes the entry for @p key.
66
+ */
67
+ - (void)remove:(NSString *)key {
68
+ @try {
69
+ [[self defaults] removeObjectForKey:key];
70
+ [[self defaults] synchronize];
71
+ } @catch (NSException *e) { }
72
+ }
73
+
74
+ /**
75
+ * Clears all keys in the kafitra.lynxstorage suite.
76
+ */
77
+ - (void)clear {
78
+ @try {
79
+ NSDictionary *dict = [[self defaults] dictionaryRepresentation];
80
+ for (NSString *key in dict.allKeys) {
81
+ [[self defaults] removeObjectForKey:key];
82
+ }
83
+ [[self defaults] synchronize];
84
+ } @catch (NSException *e) { }
85
+ }
86
+
87
+ /**
88
+ * Returns a JSON-encoded array of all stored keys.
89
+ * e.g. ["session","theme","lang"]
90
+ */
91
+ - (NSString *)getAllKeys {
92
+ @try {
93
+ NSDictionary *dict = [[self defaults] dictionaryRepresentation];
94
+ NSArray *keys = dict.allKeys;
95
+ NSData *data = [NSJSONSerialization dataWithJSONObject:keys options:0 error:nil];
96
+ return data ? [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] : @"[]";
97
+ } @catch (NSException *e) {
98
+ return @"[]";
99
+ }
100
+ }
101
+
102
+ @end
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "LynxStorage",
3
+ "android": {
4
+ "moduleClass": "com.kafitra.lynxstorage.LynxStorageModule",
5
+ "sourceDir": "android"
6
+ }
7
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@kafitra/lynx-storage",
3
+ "version": "0.1.0",
4
+ "description": "Lynx Native Module for persistent key-value storage (Android SharedPreferences + iOS NSUserDefaults)",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "android",
10
+ "ios",
11
+ "lynx.module.json"
12
+ ],
13
+ "devDependencies": {
14
+ "typescript": "^5.3.0",
15
+ "rimraf": "^5.0.0"
16
+ },
17
+ "keywords": [
18
+ "lynx",
19
+ "native-module",
20
+ "storage",
21
+ "async-storage",
22
+ "android",
23
+ "ios"
24
+ ],
25
+ "author": "Kafitra",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/kafitramarna/kafitra-lynx-native.git",
30
+ "directory": "packages/lynx-storage"
31
+ },
32
+ "engines": {
33
+ "node": ">=18"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "scripts": {
39
+ "build": "tsc",
40
+ "clean": "rimraf dist"
41
+ }
42
+ }