strata-storage 1.5.0 → 2.0.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 (82) hide show
  1. package/Readme.md +66 -20
  2. package/dist/README.md +162 -0
  3. package/dist/adapters/capacitor/FilesystemAdapter.js +4 -4
  4. package/dist/adapters/capacitor/PreferencesAdapter.js +4 -4
  5. package/dist/adapters/capacitor/SecureAdapter.js +4 -4
  6. package/dist/adapters/capacitor/SqliteAdapter.js +4 -4
  7. package/dist/adapters/capacitor/index.js +4 -4
  8. package/dist/adapters/web/CacheAdapter.js +3 -3
  9. package/dist/adapters/web/CookieAdapter.js +2 -2
  10. package/dist/adapters/web/IndexedDBAdapter.js +3 -3
  11. package/dist/adapters/web/LocalStorageAdapter.js +3 -3
  12. package/dist/adapters/web/MemoryAdapter.js +3 -3
  13. package/dist/adapters/web/SessionStorageAdapter.js +1 -1
  14. package/dist/adapters/web/index.js +6 -6
  15. package/dist/android/src/main/java/com/strata/storage/EncryptedStorage.java +65 -0
  16. package/dist/android/src/main/java/com/strata/storage/SQLiteStorage.java +147 -0
  17. package/dist/android/src/main/java/com/strata/storage/SharedPreferencesStorage.java +74 -0
  18. package/dist/android/src/main/java/com/stratastorage/StrataStoragePlugin.java +256 -0
  19. package/dist/capacitor.d.ts +20 -0
  20. package/dist/capacitor.d.ts.map +1 -0
  21. package/dist/capacitor.js +48 -0
  22. package/dist/core/AdapterRegistry.js +1 -1
  23. package/dist/core/BaseAdapter.js +3 -3
  24. package/dist/core/StorageStrategy.js +1 -0
  25. package/dist/core/Strata.d.ts +28 -3
  26. package/dist/core/Strata.d.ts.map +1 -1
  27. package/dist/core/Strata.js +57 -58
  28. package/dist/features/compression/index.d.ts +2 -0
  29. package/dist/features/compression/index.d.ts.map +1 -0
  30. package/dist/features/compression/index.js +1 -0
  31. package/dist/features/compression.js +1 -1
  32. package/dist/features/encryption/index.d.ts +2 -0
  33. package/dist/features/encryption/index.d.ts.map +1 -0
  34. package/dist/features/encryption/index.js +1 -0
  35. package/dist/features/encryption.d.ts.map +1 -1
  36. package/dist/features/encryption.js +6 -5
  37. package/dist/features/observer/index.d.ts +2 -0
  38. package/dist/features/observer/index.d.ts.map +1 -0
  39. package/dist/features/observer/index.js +1 -0
  40. package/dist/features/observer.d.ts +20 -0
  41. package/dist/features/observer.d.ts.map +1 -0
  42. package/dist/features/observer.js +32 -0
  43. package/dist/features/query/index.d.ts +2 -0
  44. package/dist/features/query/index.d.ts.map +1 -0
  45. package/dist/features/query/index.js +1 -0
  46. package/dist/features/query.d.ts.map +1 -1
  47. package/dist/features/query.js +8 -1
  48. package/dist/features/sync/index.d.ts +2 -0
  49. package/dist/features/sync/index.d.ts.map +1 -0
  50. package/dist/features/sync/index.js +1 -0
  51. package/dist/features/sync.js +1 -1
  52. package/dist/features/ttl/index.d.ts +2 -0
  53. package/dist/features/ttl/index.d.ts.map +1 -0
  54. package/dist/features/ttl/index.js +1 -0
  55. package/dist/features/ttl.js +1 -1
  56. package/dist/firebase.d.ts +26 -0
  57. package/dist/firebase.d.ts.map +1 -0
  58. package/dist/firebase.js +147 -0
  59. package/dist/index.d.ts +13 -47
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +54 -58
  62. package/dist/ios/Plugin/KeychainStorage.swift +87 -0
  63. package/dist/ios/Plugin/SQLiteStorage.swift +167 -0
  64. package/dist/ios/Plugin/StrataStoragePlugin.swift +204 -0
  65. package/dist/ios/Plugin/UserDefaultsStorage.swift +44 -0
  66. package/dist/package.json +22 -4
  67. package/dist/plugin/definitions.d.ts +2 -2
  68. package/dist/plugin/definitions.d.ts.map +1 -1
  69. package/dist/plugin/index.d.ts +2 -1
  70. package/dist/plugin/index.d.ts.map +1 -1
  71. package/dist/plugin/index.js +77 -11
  72. package/dist/types/index.d.ts +190 -0
  73. package/dist/types/index.d.ts.map +1 -1
  74. package/dist/types/index.js +13 -0
  75. package/dist/utils/index.d.ts +20 -0
  76. package/dist/utils/index.d.ts.map +1 -1
  77. package/dist/utils/index.js +34 -0
  78. package/package.json +15 -24
  79. package/scripts/build.js +127 -14
  80. package/scripts/cli.js +6 -2
  81. package/scripts/configure.js +7 -3
  82. package/scripts/postinstall.js +21 -10
package/dist/index.d.ts CHANGED
@@ -1,56 +1,22 @@
1
- /**
2
- * Strata Storage - Zero-dependency universal storage plugin
3
- *
4
- * @packageDocumentation
5
- */
6
1
  export { Strata } from './core/Strata';
7
- import { Strata } from './core/Strata';
8
- export type { Platform, StorageType, StorageStrategy, StorageOptions, StorageValue, StorageChange, StorageCapabilities, StrataConfig, StorageAdapter, Transaction, ClearOptions, SizeInfo, ExportOptions, ImportOptions, QueryCondition, QueryOperators, SubscriptionCallback, UnsubscribeFunction, Migration, ExportFormat, } from './types';
9
- export { StrataError, StorageError, NotFoundError, QuotaExceededError, AdapterNotAvailableError, NotSupportedError, EncryptionError, CompressionError, SerializationError, ValidationError, TransactionError, MigrationError, SyncError, isStrataError, isQuotaError, } from './utils/errors';
10
- export { serialize, deserialize, deepClone, deepMerge, formatBytes, parseSize, EventEmitter, } from './utils';
11
2
  export { BaseAdapter } from './core/BaseAdapter';
12
3
  export { AdapterRegistry } from './core/AdapterRegistry';
13
- export { EncryptionManager } from './features/encryption';
14
- export type { EncryptionConfig, EncryptedData } from './features/encryption';
15
- export { CompressionManager } from './features/compression';
16
- export type { CompressionConfig, CompressedData } from './features/compression';
17
- export { SyncManager, createSyncManager } from './features/sync';
18
- export type { SyncConfig, SyncMessage } from './features/sync';
19
- export { QueryEngine, createQueryEngine } from './features/query';
20
- export { TTLManager, createTTLManager } from './features/ttl';
21
- export type { TTLConfig, TTLOptions, ExpiredItem } from './features/ttl';
22
- export { MigrationManager } from './features/migration';
23
- export type { Migration as MigrationDefinition } from './features/migration';
24
- export * from './plugin/definitions';
25
- export { StrataStorage } from './plugin';
26
- export { MemoryAdapter } from './adapters/web/MemoryAdapter';
27
4
  export { LocalStorageAdapter } from './adapters/web/LocalStorageAdapter';
28
5
  export { SessionStorageAdapter } from './adapters/web/SessionStorageAdapter';
29
6
  export { IndexedDBAdapter } from './adapters/web/IndexedDBAdapter';
30
7
  export { CookieAdapter } from './adapters/web/CookieAdapter';
31
8
  export { CacheAdapter } from './adapters/web/CacheAdapter';
32
- export { PreferencesAdapter } from './adapters/capacitor/PreferencesAdapter';
33
- export { SqliteAdapter } from './adapters/capacitor/SqliteAdapter';
34
- export type { SqliteConfig } from './adapters/capacitor/SqliteAdapter';
35
- export { SecureAdapter } from './adapters/capacitor/SecureAdapter';
36
- export { FilesystemAdapter } from './adapters/capacitor/FilesystemAdapter';
37
- /**
38
- * Create a new Strata instance with optional configuration
39
- *
40
- * @example
41
- * ```typescript
42
- * import { Strata } from 'strata-storage';
43
- *
44
- * const storage = new Strata({
45
- * defaultStorages: ['indexedDB', 'localStorage', 'memory'],
46
- * encryption: { enabled: true },
47
- * compression: { enabled: true }
48
- * });
49
- *
50
- * await storage.initialize();
51
- * await storage.set('key', 'value');
52
- * const value = await storage.get('key');
53
- * ```
54
- */
55
- export declare function createStrata(config?: import('./types').StrataConfig): InstanceType<typeof Strata>;
9
+ export { MemoryAdapter } from './adapters/web/MemoryAdapter';
10
+ export { EncryptionManager } from './features/encryption';
11
+ export { CompressionManager } from './features/compression';
12
+ export { TTLManager } from './features/ttl';
13
+ export { QueryEngine } from './features/query';
14
+ export { SyncManager } from './features/sync';
15
+ export { StorageObserver } from './features/observer';
16
+ export type { StorageType, StorageOptions, StorageValue, StorageAdapter, AdapterConfig, QueryOptions, SyncConfig, EncryptionConfig, CompressionConfig, ObserverCallback, StorageEvent, StorageError, StorageCapabilities, StorageMetadata, TTLConfig, } from './types';
17
+ export { isValidKey, isValidValue, serializeValue, deserializeValue, generateId, createError, retry, debounce, throttle, } from './utils';
18
+ import { Strata } from './core/Strata';
19
+ declare const storage: Strata;
20
+ export { storage };
21
+ export default storage;
56
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAGvC,YAAY,EAEV,QAAQ,EACR,WAAW,EACX,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,YAAY,EAGZ,cAAc,EACd,WAAW,EAGX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EAGd,oBAAoB,EACpB,mBAAmB,EAGnB,SAAS,EACT,YAAY,GACb,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,WAAW,EACX,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,aAAa,EACb,YAAY,GACb,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,YAAY,GACb,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACjE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,SAAS,IAAI,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG7E,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAG3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,YAAY,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAE3E;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,SAAS,EAAE,YAAY,GAAG,YAAY,CAAC,OAAO,MAAM,CAAC,CAEjG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAG7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,YAAY,EACV,WAAW,EACX,cAAc,EACd,YAAY,EACZ,cAAc,EACd,aAAa,EACb,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,SAAS,GACV,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,KAAK,EACL,QAAQ,EACR,QAAQ,GACT,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AASvC,QAAA,MAAM,OAAO,QAGX,CAAC;AAqBH,OAAO,EAAE,OAAO,EAAE,CAAC;AAGnB,eAAe,OAAO,CAAC"}
package/dist/index.js CHANGED
@@ -1,58 +1,54 @@
1
- /**
2
- * Strata Storage - Zero-dependency universal storage plugin
3
- *
4
- * @packageDocumentation
5
- */
6
- // Main export
7
- export { Strata } from './core/Strata';
8
- import { Strata } from './core/Strata';
9
- // Errors
10
- export { StrataError, StorageError, NotFoundError, QuotaExceededError, AdapterNotAvailableError, NotSupportedError, EncryptionError, CompressionError, SerializationError, ValidationError, TransactionError, MigrationError, SyncError, isStrataError, isQuotaError, } from './utils/errors';
11
- // Utilities (selected exports for advanced users)
12
- export { serialize, deserialize, deepClone, deepMerge, formatBytes, parseSize, EventEmitter, } from './utils';
13
- // Base classes for custom adapters
14
- export { BaseAdapter } from './core/BaseAdapter';
15
- export { AdapterRegistry } from './core/AdapterRegistry';
16
- // Features
17
- export { EncryptionManager } from './features/encryption';
18
- export { CompressionManager } from './features/compression';
19
- export { SyncManager, createSyncManager } from './features/sync';
20
- export { QueryEngine, createQueryEngine } from './features/query';
21
- export { TTLManager, createTTLManager } from './features/ttl';
22
- export { MigrationManager } from './features/migration';
23
- // Plugin definitions and main plugin
24
- export * from './plugin/definitions';
25
- export { StrataStorage } from './plugin';
26
- // Web Storage Adapters (for advanced users who want direct adapter access)
27
- export { MemoryAdapter } from './adapters/web/MemoryAdapter';
28
- export { LocalStorageAdapter } from './adapters/web/LocalStorageAdapter';
29
- export { SessionStorageAdapter } from './adapters/web/SessionStorageAdapter';
30
- export { IndexedDBAdapter } from './adapters/web/IndexedDBAdapter';
31
- export { CookieAdapter } from './adapters/web/CookieAdapter';
32
- export { CacheAdapter } from './adapters/web/CacheAdapter';
33
- // Capacitor Storage Adapters
34
- export { PreferencesAdapter } from './adapters/capacitor/PreferencesAdapter';
35
- export { SqliteAdapter } from './adapters/capacitor/SqliteAdapter';
36
- export { SecureAdapter } from './adapters/capacitor/SecureAdapter';
37
- export { FilesystemAdapter } from './adapters/capacitor/FilesystemAdapter';
38
- /**
39
- * Create a new Strata instance with optional configuration
40
- *
41
- * @example
42
- * ```typescript
43
- * import { Strata } from 'strata-storage';
44
- *
45
- * const storage = new Strata({
46
- * defaultStorages: ['indexedDB', 'localStorage', 'memory'],
47
- * encryption: { enabled: true },
48
- * compression: { enabled: true }
49
- * });
50
- *
51
- * await storage.initialize();
52
- * await storage.set('key', 'value');
53
- * const value = await storage.get('key');
54
- * ```
55
- */
56
- export function createStrata(config) {
57
- return new Strata(config);
58
- }
1
+ // Core exports - zero dependencies, works everywhere
2
+ export { Strata } from "./core/Strata.js";
3
+ export { BaseAdapter } from "./core/BaseAdapter.js";
4
+ export { AdapterRegistry } from "./core/AdapterRegistry.js";
5
+ // Web adapters - work in any JavaScript environment
6
+ export { LocalStorageAdapter } from "./adapters/web/LocalStorageAdapter.js";
7
+ export { SessionStorageAdapter } from "./adapters/web/SessionStorageAdapter.js";
8
+ export { IndexedDBAdapter } from "./adapters/web/IndexedDBAdapter.js";
9
+ export { CookieAdapter } from "./adapters/web/CookieAdapter.js";
10
+ export { CacheAdapter } from "./adapters/web/CacheAdapter.js";
11
+ export { MemoryAdapter } from "./adapters/web/MemoryAdapter.js";
12
+ // Core features
13
+ export { EncryptionManager } from "./features/encryption.js";
14
+ export { CompressionManager } from "./features/compression.js";
15
+ export { TTLManager } from "./features/ttl.js";
16
+ export { QueryEngine } from "./features/query.js";
17
+ export { SyncManager } from "./features/sync.js";
18
+ export { StorageObserver } from "./features/observer.js";
19
+ // Utils
20
+ export { isValidKey, isValidValue, serializeValue, deserializeValue, generateId, createError, retry, debounce, throttle, } from "./utils/index.js";
21
+ // Create and export a default storage instance that works immediately
22
+ import { Strata } from "./core/Strata.js";
23
+ import { LocalStorageAdapter } from "./adapters/web/LocalStorageAdapter.js";
24
+ import { SessionStorageAdapter } from "./adapters/web/SessionStorageAdapter.js";
25
+ import { IndexedDBAdapter } from "./adapters/web/IndexedDBAdapter.js";
26
+ import { CookieAdapter } from "./adapters/web/CookieAdapter.js";
27
+ import { CacheAdapter } from "./adapters/web/CacheAdapter.js";
28
+ import { MemoryAdapter } from "./adapters/web/MemoryAdapter.js";
29
+ // Create a singleton instance with web adapters pre-registered
30
+ const storage = new Strata({
31
+ defaultStorage: 'memory', // Always available fallback
32
+ autoInitialize: false, // We'll initialize it ourselves
33
+ });
34
+ // Register only web adapters by default
35
+ storage.registerAdapter(new MemoryAdapter());
36
+ storage.registerAdapter(new LocalStorageAdapter());
37
+ storage.registerAdapter(new SessionStorageAdapter());
38
+ storage.registerAdapter(new IndexedDBAdapter());
39
+ storage.registerAdapter(new CookieAdapter());
40
+ storage.registerAdapter(new CacheAdapter());
41
+ // Initialize the storage instance
42
+ (async () => {
43
+ try {
44
+ await storage.initialize();
45
+ }
46
+ catch (error) {
47
+ console.warn('Strata Storage initialization warning:', error);
48
+ // Continue working even if some adapters fail
49
+ }
50
+ })();
51
+ // Export the ready-to-use storage instance
52
+ export { storage };
53
+ // Default export for convenience
54
+ export default storage;
@@ -0,0 +1,87 @@
1
+ import Foundation
2
+ import Security
3
+
4
+ @objc public class KeychainStorage: NSObject {
5
+ private let service: String
6
+ private let accessGroup: String?
7
+
8
+ @objc public init(service: String? = nil, accessGroup: String? = nil) {
9
+ self.service = service ?? Bundle.main.bundleIdentifier ?? "StrataStorage"
10
+ self.accessGroup = accessGroup
11
+ super.init()
12
+ }
13
+
14
+ @objc public func set(key: String, value: Data) -> Bool {
15
+ let query = createQuery(key: key)
16
+ SecItemDelete(query as CFDictionary)
17
+
18
+ var newItem = query
19
+ newItem[kSecValueData as String] = value
20
+
21
+ let status = SecItemAdd(newItem as CFDictionary, nil)
22
+ return status == errSecSuccess
23
+ }
24
+
25
+ @objc public func get(key: String) -> Data? {
26
+ var query = createQuery(key: key)
27
+ query[kSecReturnData as String] = true
28
+ query[kSecMatchLimit as String] = kSecMatchLimitOne
29
+
30
+ var result: AnyObject?
31
+ let status = SecItemCopyMatching(query as CFDictionary, &result)
32
+
33
+ guard status == errSecSuccess else { return nil }
34
+ return result as? Data
35
+ }
36
+
37
+ @objc public func remove(key: String) -> Bool {
38
+ let query = createQuery(key: key)
39
+ let status = SecItemDelete(query as CFDictionary)
40
+ return status == errSecSuccess
41
+ }
42
+
43
+ @objc public func clear() -> Bool {
44
+ let query: [String: Any] = [
45
+ kSecClass as String: kSecClassGenericPassword,
46
+ kSecAttrService as String: service
47
+ ]
48
+ let status = SecItemDelete(query as CFDictionary)
49
+ return status == errSecSuccess || status == errSecItemNotFound
50
+ }
51
+
52
+ @objc public func keys() -> [String] {
53
+ var query: [String: Any] = [
54
+ kSecClass as String: kSecClassGenericPassword,
55
+ kSecAttrService as String: service,
56
+ kSecReturnAttributes as String: true,
57
+ kSecMatchLimit as String: kSecMatchLimitAll
58
+ ]
59
+
60
+ if let accessGroup = accessGroup {
61
+ query[kSecAttrAccessGroup as String] = accessGroup
62
+ }
63
+
64
+ var result: AnyObject?
65
+ let status = SecItemCopyMatching(query as CFDictionary, &result)
66
+
67
+ guard status == errSecSuccess,
68
+ let items = result as? [[String: Any]] else { return [] }
69
+
70
+ return items.compactMap { $0[kSecAttrAccount as String] as? String }
71
+ }
72
+
73
+ private func createQuery(key: String) -> [String: Any] {
74
+ var query: [String: Any] = [
75
+ kSecClass as String: kSecClassGenericPassword,
76
+ kSecAttrService as String: service,
77
+ kSecAttrAccount as String: key,
78
+ kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
79
+ ]
80
+
81
+ if let accessGroup = accessGroup {
82
+ query[kSecAttrAccessGroup as String] = accessGroup
83
+ }
84
+
85
+ return query
86
+ }
87
+ }
@@ -0,0 +1,167 @@
1
+ import Foundation
2
+ import SQLite3
3
+
4
+ @objc public class SQLiteStorage: NSObject {
5
+ private var db: OpaquePointer?
6
+ private let dbName: String
7
+ private let tableName = "strata_storage"
8
+
9
+ @objc public init(dbName: String = "strata.db") {
10
+ self.dbName = dbName
11
+ super.init()
12
+ openDatabase()
13
+ createTable()
14
+ }
15
+
16
+ deinit {
17
+ closeDatabase()
18
+ }
19
+
20
+ private func openDatabase() {
21
+ let fileURL = try! FileManager.default
22
+ .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
23
+ .appendingPathComponent(dbName)
24
+
25
+ if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
26
+ print("Unable to open database")
27
+ }
28
+ }
29
+
30
+ private func closeDatabase() {
31
+ sqlite3_close(db)
32
+ }
33
+
34
+ private func createTable() {
35
+ let createTableString = """
36
+ CREATE TABLE IF NOT EXISTS \(tableName) (
37
+ key TEXT PRIMARY KEY NOT NULL,
38
+ value BLOB NOT NULL,
39
+ created INTEGER NOT NULL,
40
+ updated INTEGER NOT NULL,
41
+ expires INTEGER,
42
+ tags TEXT,
43
+ metadata TEXT
44
+ );
45
+ """
46
+
47
+ var createTableStatement: OpaquePointer?
48
+ if sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK {
49
+ if sqlite3_step(createTableStatement) == SQLITE_DONE {
50
+ print("Storage table created.")
51
+ }
52
+ }
53
+ sqlite3_finalize(createTableStatement)
54
+ }
55
+
56
+ @objc public func set(key: String, value: Data, expires: Int64? = nil, tags: [String]? = nil, metadata: [String: Any]? = nil) -> Bool {
57
+ let now = Int64(Date().timeIntervalSince1970 * 1000)
58
+ let tagsJson = tags != nil ? try? JSONSerialization.data(withJSONObject: tags!, options: []) : nil
59
+ let metadataJson = metadata != nil ? try? JSONSerialization.data(withJSONObject: metadata!, options: []) : nil
60
+
61
+ let insertSQL = """
62
+ INSERT OR REPLACE INTO \(tableName)
63
+ (key, value, created, updated, expires, tags, metadata)
64
+ VALUES (?, ?, ?, ?, ?, ?, ?)
65
+ """
66
+
67
+ var statement: OpaquePointer?
68
+ let result = sqlite3_prepare_v2(db, insertSQL, -1, &statement, nil) == SQLITE_OK &&
69
+ sqlite3_bind_text(statement, 1, key, -1, nil) == SQLITE_OK &&
70
+ sqlite3_bind_blob(statement, 2, (value as NSData).bytes, Int32(value.count), nil) == SQLITE_OK &&
71
+ sqlite3_bind_int64(statement, 3, now) == SQLITE_OK &&
72
+ sqlite3_bind_int64(statement, 4, now) == SQLITE_OK &&
73
+ (expires != nil ? sqlite3_bind_int64(statement, 5, expires!) : sqlite3_bind_null(statement, 5)) == SQLITE_OK &&
74
+ (tagsJson != nil ? sqlite3_bind_blob(statement, 6, (tagsJson! as NSData).bytes, Int32(tagsJson!.count), nil) : sqlite3_bind_null(statement, 6)) == SQLITE_OK &&
75
+ (metadataJson != nil ? sqlite3_bind_blob(statement, 7, (metadataJson! as NSData).bytes, Int32(metadataJson!.count), nil) : sqlite3_bind_null(statement, 7)) == SQLITE_OK &&
76
+ sqlite3_step(statement) == SQLITE_DONE
77
+
78
+ sqlite3_finalize(statement)
79
+ return result
80
+ }
81
+
82
+ @objc public func get(key: String) -> [String: Any]? {
83
+ let querySQL = "SELECT * FROM \(tableName) WHERE key = ? LIMIT 1"
84
+ var statement: OpaquePointer?
85
+
86
+ guard sqlite3_prepare_v2(db, querySQL, -1, &statement, nil) == SQLITE_OK,
87
+ sqlite3_bind_text(statement, 1, key, -1, nil) == SQLITE_OK else {
88
+ sqlite3_finalize(statement)
89
+ return nil
90
+ }
91
+
92
+ var result: [String: Any]?
93
+ if sqlite3_step(statement) == SQLITE_ROW {
94
+ let valueData = Data(bytes: sqlite3_column_blob(statement, 1), count: Int(sqlite3_column_bytes(statement, 1)))
95
+ let created = sqlite3_column_int64(statement, 2)
96
+ let updated = sqlite3_column_int64(statement, 3)
97
+
98
+ result = [
99
+ "key": key,
100
+ "value": valueData,
101
+ "created": created,
102
+ "updated": updated
103
+ ]
104
+
105
+ if sqlite3_column_type(statement, 4) != SQLITE_NULL {
106
+ result!["expires"] = sqlite3_column_int64(statement, 4)
107
+ }
108
+
109
+ if sqlite3_column_type(statement, 5) != SQLITE_NULL {
110
+ let tagsData = Data(bytes: sqlite3_column_blob(statement, 5), count: Int(sqlite3_column_bytes(statement, 5)))
111
+ if let tags = try? JSONSerialization.jsonObject(with: tagsData, options: []) {
112
+ result!["tags"] = tags
113
+ }
114
+ }
115
+
116
+ if sqlite3_column_type(statement, 6) != SQLITE_NULL {
117
+ let metadataData = Data(bytes: sqlite3_column_blob(statement, 6), count: Int(sqlite3_column_bytes(statement, 6)))
118
+ if let metadata = try? JSONSerialization.jsonObject(with: metadataData, options: []) {
119
+ result!["metadata"] = metadata
120
+ }
121
+ }
122
+ }
123
+
124
+ sqlite3_finalize(statement)
125
+ return result
126
+ }
127
+
128
+ @objc public func remove(key: String) -> Bool {
129
+ let deleteSQL = "DELETE FROM \(tableName) WHERE key = ?"
130
+ var statement: OpaquePointer?
131
+
132
+ let result = sqlite3_prepare_v2(db, deleteSQL, -1, &statement, nil) == SQLITE_OK &&
133
+ sqlite3_bind_text(statement, 1, key, -1, nil) == SQLITE_OK &&
134
+ sqlite3_step(statement) == SQLITE_DONE
135
+
136
+ sqlite3_finalize(statement)
137
+ return result
138
+ }
139
+
140
+ @objc public func clear() -> Bool {
141
+ let deleteSQL = "DELETE FROM \(tableName)"
142
+ var statement: OpaquePointer?
143
+
144
+ let result = sqlite3_prepare_v2(db, deleteSQL, -1, &statement, nil) == SQLITE_OK &&
145
+ sqlite3_step(statement) == SQLITE_DONE
146
+
147
+ sqlite3_finalize(statement)
148
+ return result
149
+ }
150
+
151
+ @objc public func keys() -> [String] {
152
+ let querySQL = "SELECT key FROM \(tableName)"
153
+ var statement: OpaquePointer?
154
+ var keys: [String] = []
155
+
156
+ if sqlite3_prepare_v2(db, querySQL, -1, &statement, nil) == SQLITE_OK {
157
+ while sqlite3_step(statement) == SQLITE_ROW {
158
+ if let key = sqlite3_column_text(statement, 0) {
159
+ keys.append(String(cString: key))
160
+ }
161
+ }
162
+ }
163
+
164
+ sqlite3_finalize(statement)
165
+ return keys
166
+ }
167
+ }
@@ -0,0 +1,204 @@
1
+ import Foundation
2
+ import Capacitor
3
+
4
+ /**
5
+ * Main Capacitor plugin for Strata Storage
6
+ * Coordinates between different storage types on iOS
7
+ */
8
+ @objc(StrataStoragePlugin)
9
+ public class StrataStoragePlugin: CAPPlugin {
10
+ private let userDefaultsStorage = UserDefaultsStorage()
11
+ private let keychainStorage = KeychainStorage()
12
+ private let sqliteStorage = SQLiteStorage()
13
+
14
+ /**
15
+ * Check if storage is available
16
+ */
17
+ @objc func isAvailable(_ call: CAPPluginCall) {
18
+ call.resolve([
19
+ "available": true,
20
+ "platform": "ios",
21
+ "adapters": [
22
+ "preferences": true,
23
+ "secure": true,
24
+ "sqlite": true,
25
+ "filesystem": true
26
+ ]
27
+ ])
28
+ }
29
+
30
+ /**
31
+ * Get value from storage
32
+ */
33
+ @objc func get(_ call: CAPPluginCall) {
34
+ guard let key = call.getString("key") else {
35
+ call.reject("Key is required")
36
+ return
37
+ }
38
+
39
+ let storage = call.getString("storage") ?? "preferences"
40
+
41
+ do {
42
+ let value: Any?
43
+
44
+ switch storage {
45
+ case "secure":
46
+ value = try keychainStorage.get(key: key)
47
+ case "sqlite":
48
+ value = try sqliteStorage.get(key: key)
49
+ case "preferences":
50
+ fallthrough
51
+ default:
52
+ value = userDefaultsStorage.get(key: key)
53
+ }
54
+
55
+ call.resolve([
56
+ "value": value ?? NSNull()
57
+ ])
58
+ } catch {
59
+ call.reject("Failed to get value", error.localizedDescription)
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Set value in storage
65
+ */
66
+ @objc func set(_ call: CAPPluginCall) {
67
+ guard let key = call.getString("key") else {
68
+ call.reject("Key is required")
69
+ return
70
+ }
71
+
72
+ let value = call.getValue("value") ?? NSNull()
73
+ let storage = call.getString("storage") ?? "preferences"
74
+
75
+ do {
76
+ switch storage {
77
+ case "secure":
78
+ try keychainStorage.set(key: key, value: value)
79
+ case "sqlite":
80
+ try sqliteStorage.set(key: key, value: value)
81
+ case "preferences":
82
+ fallthrough
83
+ default:
84
+ userDefaultsStorage.set(key: key, value: value)
85
+ }
86
+
87
+ call.resolve()
88
+ } catch {
89
+ call.reject("Failed to set value", error.localizedDescription)
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Remove value from storage
95
+ */
96
+ @objc func remove(_ call: CAPPluginCall) {
97
+ guard let key = call.getString("key") else {
98
+ call.reject("Key is required")
99
+ return
100
+ }
101
+
102
+ let storage = call.getString("storage") ?? "preferences"
103
+
104
+ do {
105
+ switch storage {
106
+ case "secure":
107
+ try keychainStorage.remove(key: key)
108
+ case "sqlite":
109
+ try sqliteStorage.remove(key: key)
110
+ case "preferences":
111
+ fallthrough
112
+ default:
113
+ userDefaultsStorage.remove(key: key)
114
+ }
115
+
116
+ call.resolve()
117
+ } catch {
118
+ call.reject("Failed to remove value", error.localizedDescription)
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Clear storage
124
+ */
125
+ @objc func clear(_ call: CAPPluginCall) {
126
+ let storage = call.getString("storage") ?? "preferences"
127
+ let prefix = call.getString("prefix")
128
+
129
+ do {
130
+ switch storage {
131
+ case "secure":
132
+ try keychainStorage.clear(prefix: prefix)
133
+ case "sqlite":
134
+ try sqliteStorage.clear(prefix: prefix)
135
+ case "preferences":
136
+ fallthrough
137
+ default:
138
+ userDefaultsStorage.clear(prefix: prefix)
139
+ }
140
+
141
+ call.resolve()
142
+ } catch {
143
+ call.reject("Failed to clear storage", error.localizedDescription)
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Get all keys from storage
149
+ */
150
+ @objc func keys(_ call: CAPPluginCall) {
151
+ let storage = call.getString("storage") ?? "preferences"
152
+ let pattern = call.getString("pattern")
153
+
154
+ do {
155
+ let keys: [String]
156
+
157
+ switch storage {
158
+ case "secure":
159
+ keys = try keychainStorage.keys(pattern: pattern)
160
+ case "sqlite":
161
+ keys = try sqliteStorage.keys(pattern: pattern)
162
+ case "preferences":
163
+ fallthrough
164
+ default:
165
+ keys = userDefaultsStorage.keys(pattern: pattern)
166
+ }
167
+
168
+ call.resolve([
169
+ "keys": keys
170
+ ])
171
+ } catch {
172
+ call.reject("Failed to get keys", error.localizedDescription)
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Get storage size information
178
+ */
179
+ @objc func size(_ call: CAPPluginCall) {
180
+ let storage = call.getString("storage") ?? "preferences"
181
+
182
+ do {
183
+ let sizeInfo: (total: Int, count: Int)
184
+
185
+ switch storage {
186
+ case "secure":
187
+ sizeInfo = try keychainStorage.size()
188
+ case "sqlite":
189
+ sizeInfo = try sqliteStorage.size()
190
+ case "preferences":
191
+ fallthrough
192
+ default:
193
+ sizeInfo = userDefaultsStorage.size()
194
+ }
195
+
196
+ call.resolve([
197
+ "total": sizeInfo.total,
198
+ "count": sizeInfo.count
199
+ ])
200
+ } catch {
201
+ call.reject("Failed to get size", error.localizedDescription)
202
+ }
203
+ }
204
+ }