strata-storage 2.3.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/strata/storage/EncryptedStorage.java +84 -21
- package/android/src/main/java/com/strata/storage/SQLiteStorage.java +140 -58
- package/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +66 -5
- package/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +83 -10
- package/dist/adapters/web/MemoryAdapter.d.ts.map +1 -1
- package/dist/adapters/web/MemoryAdapter.js +7 -1
- package/dist/adapters/web/SessionStorageAdapter.d.ts.map +1 -1
- package/dist/adapters/web/SessionStorageAdapter.js +3 -2
- package/dist/android/src/main/java/com/strata/storage/EncryptedStorage.java +84 -21
- package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +140 -58
- package/dist/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +66 -5
- package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +83 -10
- package/dist/core/Strata.d.ts.map +1 -1
- package/dist/core/Strata.js +4 -6
- package/dist/firebase.d.ts.map +1 -1
- package/dist/firebase.js +75 -13
- package/dist/ios/Plugin/SQLiteStorage.swift +100 -30
- package/dist/ios/Plugin/UserDefaultsStorage.swift +13 -2
- package/dist/package.json +5 -5
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +31 -6
- package/dist/plugin/web.d.ts +5 -1
- package/dist/plugin/web.d.ts.map +1 -1
- package/dist/plugin/web.js +55 -32
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +7 -2
- package/ios/Plugin/SQLiteStorage.swift +100 -30
- package/ios/Plugin/UserDefaultsStorage.swift +13 -2
- package/package.json +17 -19
|
@@ -1,29 +1,47 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import SQLite3
|
|
3
|
+
import os.log
|
|
3
4
|
|
|
4
5
|
@objc public class SQLiteStorage: NSObject {
|
|
5
6
|
private var db: OpaquePointer?
|
|
6
7
|
private let dbName: String
|
|
7
8
|
private let tableName = "strata_storage"
|
|
9
|
+
private let logger = OSLog(subsystem: "com.strata.storage", category: "SQLiteStorage")
|
|
8
10
|
|
|
9
11
|
@objc public init(dbName: String = "strata.db") {
|
|
10
12
|
self.dbName = dbName
|
|
11
13
|
super.init()
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
do {
|
|
15
|
+
try openDatabase()
|
|
16
|
+
try createTable()
|
|
17
|
+
} catch {
|
|
18
|
+
os_log("Failed to initialize SQLite storage: %{public}@", log: logger, type: .error, error.localizedDescription)
|
|
19
|
+
}
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
deinit {
|
|
17
23
|
closeDatabase()
|
|
18
24
|
}
|
|
19
25
|
|
|
20
|
-
private func openDatabase() {
|
|
21
|
-
let fileURL = try
|
|
26
|
+
private func openDatabase() throws {
|
|
27
|
+
guard let fileURL = try? FileManager.default
|
|
22
28
|
.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
|
|
23
|
-
.appendingPathComponent(dbName)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
.appendingPathComponent(dbName) else {
|
|
30
|
+
throw NSError(
|
|
31
|
+
domain: "StrataStorage.SQLiteStorage",
|
|
32
|
+
code: 1001,
|
|
33
|
+
userInfo: [NSLocalizedDescriptionKey: "Unable to access document directory"]
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
guard sqlite3_open(fileURL.path, &db) == SQLITE_OK else {
|
|
38
|
+
let errorMessage = String(cString: sqlite3_errmsg(db))
|
|
39
|
+
sqlite3_close(db)
|
|
40
|
+
throw NSError(
|
|
41
|
+
domain: "StrataStorage.SQLiteStorage",
|
|
42
|
+
code: 1002,
|
|
43
|
+
userInfo: [NSLocalizedDescriptionKey: "Unable to open database: \(errorMessage)"]
|
|
44
|
+
)
|
|
27
45
|
}
|
|
28
46
|
}
|
|
29
47
|
|
|
@@ -31,7 +49,7 @@ import SQLite3
|
|
|
31
49
|
sqlite3_close(db)
|
|
32
50
|
}
|
|
33
51
|
|
|
34
|
-
private func createTable() {
|
|
52
|
+
private func createTable() throws {
|
|
35
53
|
let createTableString = """
|
|
36
54
|
CREATE TABLE IF NOT EXISTS \(tableName) (
|
|
37
55
|
key TEXT PRIMARY KEY NOT NULL,
|
|
@@ -43,19 +61,43 @@ import SQLite3
|
|
|
43
61
|
metadata TEXT
|
|
44
62
|
);
|
|
45
63
|
"""
|
|
46
|
-
|
|
64
|
+
|
|
47
65
|
var createTableStatement: OpaquePointer?
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
66
|
+
|
|
67
|
+
guard sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK else {
|
|
68
|
+
let errorMessage = String(cString: sqlite3_errmsg(db))
|
|
69
|
+
throw NSError(
|
|
70
|
+
domain: "StrataStorage.SQLiteStorage",
|
|
71
|
+
code: 1003,
|
|
72
|
+
userInfo: [NSLocalizedDescriptionKey: "Failed to prepare CREATE TABLE: \(errorMessage)"]
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
defer {
|
|
77
|
+
sqlite3_finalize(createTableStatement)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
guard sqlite3_step(createTableStatement) == SQLITE_DONE else {
|
|
81
|
+
let errorMessage = String(cString: sqlite3_errmsg(db))
|
|
82
|
+
throw NSError(
|
|
83
|
+
domain: "StrataStorage.SQLiteStorage",
|
|
84
|
+
code: 1004,
|
|
85
|
+
userInfo: [NSLocalizedDescriptionKey: "Failed to create table: \(errorMessage)"]
|
|
86
|
+
)
|
|
52
87
|
}
|
|
53
|
-
sqlite3_finalize(createTableStatement)
|
|
54
88
|
}
|
|
55
89
|
|
|
56
90
|
@objc public func set(key: String, value: Any, expires: Int64? = nil, tags: [String]? = nil, metadata: [String: Any]? = nil) throws -> Bool {
|
|
91
|
+
guard let db = db else {
|
|
92
|
+
throw NSError(
|
|
93
|
+
domain: "StrataStorage.SQLiteStorage",
|
|
94
|
+
code: 1000,
|
|
95
|
+
userInfo: [NSLocalizedDescriptionKey: "Database not initialized"]
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
57
99
|
let data: Data
|
|
58
|
-
|
|
100
|
+
|
|
59
101
|
if let dataValue = value as? Data {
|
|
60
102
|
data = dataValue
|
|
61
103
|
} else if let stringValue = value as? String {
|
|
@@ -96,9 +138,14 @@ import SQLite3
|
|
|
96
138
|
}
|
|
97
139
|
|
|
98
140
|
@objc public func get(key: String) -> [String: Any]? {
|
|
141
|
+
guard db != nil else {
|
|
142
|
+
os_log("Database not initialized", log: logger, type: .error)
|
|
143
|
+
return nil
|
|
144
|
+
}
|
|
145
|
+
|
|
99
146
|
let querySQL = "SELECT * FROM \(tableName) WHERE key = ? LIMIT 1"
|
|
100
147
|
var statement: OpaquePointer?
|
|
101
|
-
|
|
148
|
+
|
|
102
149
|
guard sqlite3_prepare_v2(db, querySQL, -1, &statement, nil) == SQLITE_OK,
|
|
103
150
|
sqlite3_bind_text(statement, 1, key, -1, nil) == SQLITE_OK else {
|
|
104
151
|
sqlite3_finalize(statement)
|
|
@@ -142,82 +189,105 @@ import SQLite3
|
|
|
142
189
|
}
|
|
143
190
|
|
|
144
191
|
@objc public func remove(key: String) -> Bool {
|
|
192
|
+
guard db != nil else {
|
|
193
|
+
os_log("Database not initialized", log: logger, type: .error)
|
|
194
|
+
return false
|
|
195
|
+
}
|
|
196
|
+
|
|
145
197
|
let deleteSQL = "DELETE FROM \(tableName) WHERE key = ?"
|
|
146
198
|
var statement: OpaquePointer?
|
|
147
|
-
|
|
199
|
+
|
|
148
200
|
let result = sqlite3_prepare_v2(db, deleteSQL, -1, &statement, nil) == SQLITE_OK &&
|
|
149
201
|
sqlite3_bind_text(statement, 1, key, -1, nil) == SQLITE_OK &&
|
|
150
202
|
sqlite3_step(statement) == SQLITE_DONE
|
|
151
|
-
|
|
203
|
+
|
|
152
204
|
sqlite3_finalize(statement)
|
|
153
205
|
return result
|
|
154
206
|
}
|
|
155
207
|
|
|
156
208
|
@objc public func clear(prefix: String? = nil) -> Bool {
|
|
209
|
+
guard db != nil else {
|
|
210
|
+
os_log("Database not initialized", log: logger, type: .error)
|
|
211
|
+
return false
|
|
212
|
+
}
|
|
213
|
+
|
|
157
214
|
let deleteSQL: String
|
|
158
215
|
if let prefix = prefix {
|
|
159
216
|
deleteSQL = "DELETE FROM \(tableName) WHERE key LIKE ?"
|
|
160
217
|
} else {
|
|
161
218
|
deleteSQL = "DELETE FROM \(tableName)"
|
|
162
219
|
}
|
|
163
|
-
|
|
220
|
+
|
|
164
221
|
var statement: OpaquePointer?
|
|
165
222
|
var result = sqlite3_prepare_v2(db, deleteSQL, -1, &statement, nil) == SQLITE_OK
|
|
166
|
-
|
|
223
|
+
|
|
167
224
|
if result && prefix != nil {
|
|
168
225
|
result = sqlite3_bind_text(statement, 1, "\(prefix!)%", -1, nil) == SQLITE_OK
|
|
169
226
|
}
|
|
170
|
-
|
|
227
|
+
|
|
171
228
|
if result {
|
|
172
229
|
result = sqlite3_step(statement) == SQLITE_DONE
|
|
173
230
|
}
|
|
174
|
-
|
|
231
|
+
|
|
175
232
|
sqlite3_finalize(statement)
|
|
176
233
|
return result
|
|
177
234
|
}
|
|
178
235
|
|
|
179
236
|
@objc public func keys(pattern: String? = nil) -> [String] {
|
|
237
|
+
guard db != nil else {
|
|
238
|
+
os_log("Database not initialized", log: logger, type: .error)
|
|
239
|
+
return []
|
|
240
|
+
}
|
|
241
|
+
|
|
180
242
|
let querySQL: String
|
|
181
243
|
if let pattern = pattern {
|
|
182
244
|
querySQL = "SELECT key FROM \(tableName) WHERE key LIKE ?"
|
|
183
245
|
} else {
|
|
184
246
|
querySQL = "SELECT key FROM \(tableName)"
|
|
185
247
|
}
|
|
186
|
-
|
|
248
|
+
|
|
187
249
|
var statement: OpaquePointer?
|
|
188
250
|
var keys: [String] = []
|
|
189
|
-
|
|
251
|
+
|
|
190
252
|
if sqlite3_prepare_v2(db, querySQL, -1, &statement, nil) == SQLITE_OK {
|
|
191
253
|
if let pattern = pattern {
|
|
192
254
|
// Use % wildcard for SQL LIKE pattern matching
|
|
193
255
|
sqlite3_bind_text(statement, 1, "%\(pattern)%", -1, nil)
|
|
194
256
|
}
|
|
195
|
-
|
|
257
|
+
|
|
196
258
|
while sqlite3_step(statement) == SQLITE_ROW {
|
|
197
259
|
if let key = sqlite3_column_text(statement, 0) {
|
|
198
260
|
keys.append(String(cString: key))
|
|
199
261
|
}
|
|
200
262
|
}
|
|
201
263
|
}
|
|
202
|
-
|
|
264
|
+
|
|
203
265
|
sqlite3_finalize(statement)
|
|
204
266
|
return keys
|
|
205
267
|
}
|
|
206
268
|
|
|
207
269
|
@objc public func size() throws -> (total: Int, count: Int) {
|
|
270
|
+
guard db != nil else {
|
|
271
|
+
throw NSError(
|
|
272
|
+
domain: "StrataStorage.SQLiteStorage",
|
|
273
|
+
code: 1000,
|
|
274
|
+
userInfo: [NSLocalizedDescriptionKey: "Database not initialized"]
|
|
275
|
+
)
|
|
276
|
+
}
|
|
277
|
+
|
|
208
278
|
let querySQL = "SELECT COUNT(*), SUM(LENGTH(value)) FROM \(tableName)"
|
|
209
279
|
var statement: OpaquePointer?
|
|
210
|
-
|
|
280
|
+
|
|
211
281
|
var totalSize = 0
|
|
212
282
|
var count = 0
|
|
213
|
-
|
|
283
|
+
|
|
214
284
|
if sqlite3_prepare_v2(db, querySQL, -1, &statement, nil) == SQLITE_OK {
|
|
215
285
|
if sqlite3_step(statement) == SQLITE_ROW {
|
|
216
286
|
count = Int(sqlite3_column_int(statement, 0))
|
|
217
287
|
totalSize = Int(sqlite3_column_int64(statement, 1))
|
|
218
288
|
}
|
|
219
289
|
}
|
|
220
|
-
|
|
290
|
+
|
|
221
291
|
sqlite3_finalize(statement)
|
|
222
292
|
return (total: totalSize, count: count)
|
|
223
293
|
}
|
|
@@ -6,7 +6,11 @@ import Foundation
|
|
|
6
6
|
|
|
7
7
|
@objc public init(suiteName: String? = nil) {
|
|
8
8
|
self.suiteName = suiteName
|
|
9
|
-
|
|
9
|
+
if let suiteName = suiteName, let customDefaults = UserDefaults(suiteName: suiteName) {
|
|
10
|
+
self.userDefaults = customDefaults
|
|
11
|
+
} else {
|
|
12
|
+
self.userDefaults = UserDefaults.standard
|
|
13
|
+
}
|
|
10
14
|
super.init()
|
|
11
15
|
}
|
|
12
16
|
|
|
@@ -36,7 +40,14 @@ import Foundation
|
|
|
36
40
|
if let suiteName = suiteName {
|
|
37
41
|
UserDefaults(suiteName: suiteName)?.removePersistentDomain(forName: suiteName)
|
|
38
42
|
} else {
|
|
39
|
-
let domain = Bundle.main.bundleIdentifier
|
|
43
|
+
guard let domain = Bundle.main.bundleIdentifier else {
|
|
44
|
+
// Fallback: manually clear all keys
|
|
45
|
+
let keys = Array(userDefaults.dictionaryRepresentation().keys)
|
|
46
|
+
for key in keys {
|
|
47
|
+
userDefaults.removeObject(forKey: key)
|
|
48
|
+
}
|
|
49
|
+
return userDefaults.synchronize()
|
|
50
|
+
}
|
|
40
51
|
userDefaults.removePersistentDomain(forName: domain)
|
|
41
52
|
}
|
|
42
53
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strata-storage",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "Zero-dependency universal storage plugin providing a unified API for all storage operations across web, Android, and iOS platforms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"typecheck": "tsc --noEmit",
|
|
37
37
|
"test": "vitest",
|
|
38
38
|
"test:coverage": "vitest --coverage",
|
|
39
|
-
"prepublishOnly": "
|
|
39
|
+
"prepublishOnly": "pnpm build && pnpm lint && pnpm typecheck",
|
|
40
40
|
"postinstall": "node scripts/postinstall.js || true"
|
|
41
41
|
},
|
|
42
42
|
"keywords": [
|
|
@@ -67,12 +67,11 @@
|
|
|
67
67
|
"url": "https://github.com/aoneahsan/strata-storage/issues"
|
|
68
68
|
},
|
|
69
69
|
"homepage": "https://github.com/aoneahsan/strata-storage#readme",
|
|
70
|
-
"dependencies": {},
|
|
71
70
|
"peerDependencies": {
|
|
72
|
-
"@angular/core": ">=
|
|
73
|
-
"@capacitor/core": ">=
|
|
74
|
-
"react": ">=19.
|
|
75
|
-
"vue": ">=3.
|
|
71
|
+
"@angular/core": ">=21.0.6",
|
|
72
|
+
"@capacitor/core": ">=8.0.0",
|
|
73
|
+
"react": ">=19.2.3",
|
|
74
|
+
"vue": ">=3.5.26"
|
|
76
75
|
},
|
|
77
76
|
"peerDependenciesMeta": {
|
|
78
77
|
"@capacitor/core": {
|
|
@@ -89,23 +88,22 @@
|
|
|
89
88
|
}
|
|
90
89
|
},
|
|
91
90
|
"devDependencies": {
|
|
92
|
-
"@
|
|
93
|
-
"@types/
|
|
94
|
-
"@
|
|
95
|
-
"@typescript-eslint/
|
|
96
|
-
"@
|
|
97
|
-
"
|
|
98
|
-
"eslint": "^9.37.0",
|
|
91
|
+
"@types/node": "^25.0.3",
|
|
92
|
+
"@types/react": "^19.2.7",
|
|
93
|
+
"@typescript-eslint/eslint-plugin": "^8.50.1",
|
|
94
|
+
"@typescript-eslint/parser": "^8.50.1",
|
|
95
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
96
|
+
"eslint": "^9.39.2",
|
|
99
97
|
"eslint-config-prettier": "^10.1.8",
|
|
100
98
|
"eslint-plugin-prettier": "^5.5.4",
|
|
101
|
-
"jsdom": "^27.
|
|
102
|
-
"prettier": "^3.
|
|
99
|
+
"jsdom": "^27.4.0",
|
|
100
|
+
"prettier": "^3.7.4",
|
|
103
101
|
"typescript": "^5.9.3",
|
|
104
|
-
"typescript-eslint": "^8.
|
|
105
|
-
"vitest": "^
|
|
102
|
+
"typescript-eslint": "^8.50.1",
|
|
103
|
+
"vitest": "^4.0.16"
|
|
106
104
|
},
|
|
107
105
|
"engines": {
|
|
108
|
-
"node": ">=
|
|
106
|
+
"node": ">=25.0.3"
|
|
109
107
|
},
|
|
110
108
|
"capacitor": {
|
|
111
109
|
"ios": {
|