Skip to content

Commit 86d2ca2

Browse files
committed
initial check-in
1 parent e938a03 commit 86d2ca2

File tree

24 files changed

+3134
-132
lines changed

24 files changed

+3134
-132
lines changed

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,11 @@ Carthage/Build
3434
# `pod install` in .travis.yml
3535
#
3636
# Pods/
37+
Example/Pods/CouchbaseLite-Enterprise
38+
Example/Pods/CouchbaseLite-Swift-Enterprise
39+
Example/Pods/Nimble
40+
Example/Pods/Quick
41+
Example/Pods/Manifest.lock
42+
Example/Podfile.lock
43+
Example/Pods/Local Podspecs
44+
Example/Pods/Target Support Files

CbliteSwiftJsLib.podspec

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#
2-
# Be sure to run `pod lib lint CbliteSwiftJsLib.podspec' to ensure this is a
3-
# valid spec before submitting.
2+
# Be sure to run `pod lib lint CbliteSwiftJsLib.podspec' before submitting for review.
43
#
54
# Any lines starting with a # are optional, but their use is encouraged
65
# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
@@ -9,7 +8,7 @@
98
Pod::Spec.new do |s|
109
s.name = 'CbliteSwiftJsLib'
1110
s.version = '0.1.0'
12-
s.summary = 'A short description of CbliteSwiftJsLib.'
11+
s.summary = 'Couchbase Lite Swift libary for cblite.js (Javascript) Library'
1312

1413
# This description is used to generate tags and improve search results.
1514
# * Think: What does it do? Why did you write it? What is the focus?
@@ -18,25 +17,23 @@ Pod::Spec.new do |s|
1817
# * Finally, don't worry about the indent, CocoaPods strips it!
1918

2019
s.description = <<-DESC
21-
TODO: Add long description of the pod here.
20+
Couchbase Lite Swift libary for cblite.js (Javascript) Library. This is a set of shared code used by the Ionic and React Native plugins for Couchbase Lite.
2221
DESC
2322

24-
s.homepage = 'https://github.com/Aaron LaBeau/CbliteSwiftJsLib'
23+
s.homepage = 'https://github.com/couchbaselabs/CbliteSwiftJsLib'
2524
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
26-
s.license = { :type => 'MIT', :file => 'LICENSE' }
27-
s.author = { 'Aaron LaBeau' => 'alabeau@gmail.com' }
28-
s.source = { :git => 'https://github.com/Aaron LaBeau/CbliteSwiftJsLib.git', :tag => s.version.to_s }
29-
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
25+
s.license = { :type => 'Apache License, Version 2.0', :file => 'LICENSE' }
26+
s.author = 'Couchbase'
27+
s.source = { :git => 'https://github.com/couchbaselabs/CbliteSwiftJsLib.git', :tag => s.version.to_s }
28+
s.social_media_url = 'https://twitter.com/couchbase'
3029

31-
s.ios.deployment_target = '10.0'
30+
s.ios.deployment_target = '13.0'
31+
s.swift_version = '5.5'
3232

3333
s.source_files = 'CbliteSwiftJsLib/Classes/**/*'
34-
35-
# s.resource_bundles = {
36-
# 'CbliteSwiftJsLib' => ['CbliteSwiftJsLib/Assets/*.png']
37-
# }
3834

3935
# s.public_header_files = 'Pod/Classes/**/*.h'
40-
# s.frameworks = 'UIKit', 'MapKit'
41-
# s.dependency 'AFNetworking', '~> 2.3'
36+
37+
s.dependency 'CouchbaseLite-Swift-Enterprise', '~> 3.1'
38+
s.dependency 'CouchbaseLite-Enterprise', '~> 3.1'
4239
end

CbliteSwiftJsLib/Assets/.gitkeep

Whitespace-only changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//
2+
// CustomQuery.h
3+
// CbliteSwiftJsLib
4+
//
5+
// Created by Aaron LaBeau on 07/04/24.
6+
//
7+
8+
#import <CouchbaseLite/CouchbaseLite.h>
9+
10+
@interface CustomQuery : CBLQuery {
11+
}
12+
@end
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// CustomQuery.m
3+
// CbliteSwiftJsLib
4+
//
5+
// Created by Aaron LaBeau on 07/04/24.
6+
//
7+
8+
#import <objc/runtime.h>
9+
#import <Foundation/Foundation.h>
10+
11+
#import "CustomQuery.h"
12+
13+
@implementation CustomQuery
14+
15+
-(instancetype) initWithJson:(NSData *)jsonData database:(CBLDatabase*)database {
16+
SEL sel = NSSelectorFromString(@"initWithDatabase:JSONRepresentation:");
17+
id queryInstance = [CBLQuery alloc];
18+
19+
Ivar ivar = class_getInstanceVariable(CBLQuery.self, "_from");
20+
object_setIvar(queryInstance, ivar, [CBLQueryDataSource database:database]);
21+
22+
id (*method)(id, SEL, id, id) = (void *)[queryInstance methodForSelector:sel];
23+
return method(queryInstance, sel, database, jsonData);
24+
}
25+
26+
@end
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
//
2+
// DatabaseManager.swift
3+
// Created by Aaron LaBeau on 07/04/24.
4+
//
5+
6+
import Foundation
7+
import CouchbaseLiteSwift
8+
9+
enum DatabaseError: Error {
10+
case invalidDatabaseName(databaseName: String)
11+
case unableToOpenDatabase(databaseName: String)
12+
case unableToCloseDatabase(databaseName: String)
13+
case unableToDeleteDatabase(message: String, databaseName: String)
14+
case databaseLocked(databaseName: String)
15+
case copyError(message: String)
16+
case maintenanceError(message: String)
17+
}
18+
19+
public class DatabaseManager {
20+
21+
// MARK: - Private for management of state
22+
var openDatabases = [String: Database]()
23+
var queryResultSets = [String: ResultSet]()
24+
25+
/* change listeners */
26+
var databaseChangeListeners = [String: Any]()
27+
var documentChangeListeners = [String: Any]()
28+
var queryChangeListeners = [String: Any]()
29+
30+
/* replicators tracking */
31+
var replicators = [String: Replicator]()
32+
var replicatorChangeListeners = [String: Any]()
33+
var replicatorDocumentListeners = [String: Any]()
34+
35+
var queryCount: Int = 0
36+
var replicatorCount: Int = 0
37+
var allResultsChunkSize: Int = 0
38+
39+
/* collections */
40+
private var defaultCollectionName:String = "_default"
41+
private var defaultScopeName:String = "_default"
42+
43+
// MARK: - Singleton
44+
static let shared = DatabaseManager()
45+
46+
// MARK: - Private initializer to prevent external instantiation
47+
private init() {
48+
// Initialization code here
49+
}
50+
51+
// MARK: - Helper methods
52+
53+
public func getDatabase(_ name: String) -> Database? {
54+
objc_sync_enter(openDatabases)
55+
defer {
56+
objc_sync_exit(openDatabases)
57+
}
58+
59+
return openDatabases[name]
60+
}
61+
62+
public func buildDatabaseConfig(_ config: [AnyHashable: Any]?) -> DatabaseConfiguration {
63+
var databaseConfiguration = DatabaseConfiguration()
64+
if let encKey = config?["encryptionKey"] as? String {
65+
let key = EncryptionKey.password(encKey)
66+
databaseConfiguration.encryptionKey = key
67+
}
68+
if let directory = config?["directory"] as? String {
69+
// Used to auto set the database to be in the documents folder,
70+
// otherwise the directory won't work because we need a full path
71+
databaseConfiguration.directory = directory
72+
}
73+
return databaseConfiguration
74+
}
75+
76+
// MARK: Database Methods
77+
78+
public func open(_ databaseName: String, databaseConfig: [AnyHashable: Any]?) throws {
79+
do {
80+
let config = self.buildDatabaseConfig(databaseConfig)
81+
let database = try Database(name: databaseName, config: config)
82+
83+
if self.openDatabases[databaseName] != nil {
84+
self.openDatabases.removeValue(forKey: databaseName)
85+
}
86+
self.openDatabases[databaseName] = database
87+
} catch {
88+
throw DatabaseError.unableToOpenDatabase(databaseName: databaseName)
89+
}
90+
}
91+
92+
public func close(_ databaseName: String) throws {
93+
guard let database = self.getDatabase(databaseName) else {
94+
throw DatabaseError.invalidDatabaseName(databaseName: databaseName)
95+
}
96+
do {
97+
try database.close()
98+
} catch {
99+
throw DatabaseError.unableToCloseDatabase(databaseName: databaseName)
100+
}
101+
}
102+
103+
func delete(_ databaseName: String) throws {
104+
guard let database = self.getDatabase(databaseName) else {
105+
throw DatabaseError.invalidDatabaseName(databaseName: databaseName)
106+
}
107+
do {
108+
try database.delete()
109+
openDatabases.removeValue(forKey: databaseName)
110+
} catch {
111+
if let nsError = error as NSError?, nsError.code == 19 {
112+
// SQLite error code 19 (SQLITE_CONSTRAINT) indicates that the database is locked.
113+
throw DatabaseError.databaseLocked(databaseName: databaseName)
114+
} else {
115+
throw DatabaseError.unableToDeleteDatabase(message: "Error deleting database: \(error.localizedDescription)", databaseName: databaseName)
116+
}
117+
}
118+
}
119+
120+
public func exists(_ databaseName: String, directoryPath: String) -> Bool {
121+
return Database.exists(withName: databaseName, inDirectory: directoryPath)
122+
}
123+
124+
public func getPath(_ databaseName: String) throws -> String? {
125+
guard let database = self.getDatabase(databaseName) else {
126+
throw DatabaseError.invalidDatabaseName(databaseName: databaseName)
127+
}
128+
return database.path
129+
}
130+
131+
public func copy(_ path: String, newName: String, databaseConfig: [AnyHashable: Any]?) throws {
132+
let config = self.buildDatabaseConfig(databaseConfig)
133+
do {
134+
try Database.copy(fromPath: path, toDatabase: newName, withConfig: config)
135+
} catch {
136+
throw DatabaseError.copyError(message: "\(error.localizedDescription)")
137+
}
138+
}
139+
140+
// MARK: Database Maintenance methods
141+
142+
func performMaintenance(_ databaseName: String, maintenanceType: MaintenanceType) throws {
143+
guard let database = self.getDatabase(databaseName) else {
144+
throw DatabaseError.invalidDatabaseName(databaseName: databaseName)
145+
}
146+
147+
do {
148+
try database.performMaintenance(type: maintenanceType)
149+
} catch {
150+
if let nsError = error as NSError? {
151+
let errorMessage: String
152+
if let reason = nsError.userInfo[NSLocalizedFailureReasonErrorKey] as? String {
153+
throw DatabaseError.maintenanceError(message: "Unknown error: \(reason)")
154+
}
155+
}
156+
throw DatabaseError.maintenanceError(message: "Unknown error trying to perform maintenance \(error)")
157+
}
158+
}
159+
160+
// MARK: Index Methods
161+
162+
func createIndex(_ indexName: String,
163+
indexType: String,
164+
items: [[Any]],
165+
databaseName: String) throws {
166+
do {
167+
try CollectionManager.shared.createIndex(indexName, indexType: indexType,
168+
items: items,
169+
collectionName: defaultCollectionName,
170+
scopeName: defaultScopeName,
171+
databaseName: databaseName)
172+
}
173+
catch {
174+
throw error
175+
}
176+
}
177+
178+
func deleteIndex(_ indexName: String,
179+
indexType: String,
180+
items: [[Any]],
181+
databaseName: String) throws {
182+
do {
183+
try CollectionManager.shared.deleteIndex(indexName,
184+
collectionName: defaultCollectionName,
185+
scopeName: defaultScopeName,
186+
databaseName: databaseName)
187+
}
188+
catch {
189+
throw error
190+
}
191+
}
192+
193+
func getIndexes(databaseName: String) throws -> [String] {
194+
do {
195+
let indexes = try CollectionManager.shared.indexes(
196+
defaultCollectionName,
197+
scopeName: defaultScopeName,
198+
databaseName: databaseName)
199+
return indexes
200+
} catch {
201+
throw error
202+
}
203+
}
204+
205+
// MARK: Document methods
206+
207+
func getDocumentsCount(_ databaseName: String)
208+
throws -> UInt64 {
209+
210+
do {
211+
return try CollectionManager.shared.documentsCount(
212+
defaultCollectionName,
213+
scopeName: defaultScopeName,
214+
databaseName: databaseName)
215+
} catch {
216+
throw error
217+
}
218+
}
219+
220+
func saveDocument(_ documentId: String,
221+
document: [String: Any],
222+
concurrencyControl: ConcurrencyControl?,
223+
collectionName: String?,
224+
scopeName: String?,
225+
databaseName: String) throws -> String {
226+
do {
227+
return try CollectionManager.shared.saveDocument(documentId, document: document, concurrencyControl: concurrencyControl, collectionName: defaultCollectionName, scopeName: defaultScopeName, databaseName: databaseName)
228+
} catch {
229+
throw error
230+
}
231+
}
232+
233+
func getDocument(_ documentId: String,
234+
databaseName: String) throws -> Document? {
235+
do {
236+
return try CollectionManager.shared.document(
237+
documentId,
238+
collectionName: defaultCollectionName,
239+
scopeName: defaultScopeName,
240+
databaseName: databaseName)
241+
}
242+
catch {
243+
throw error
244+
}
245+
}
246+
247+
func deleteDocument(_ documentId: String,
248+
databaseName: String) throws {
249+
do {
250+
try CollectionManager.shared.deleteDocument(
251+
documentId,
252+
collectionName: defaultCollectionName,
253+
scopeName: defaultScopeName,
254+
databaseName: databaseName)
255+
} catch {
256+
throw error
257+
}
258+
}
259+
260+
func deleteDocument(_ documentId: String,
261+
concurrencyControl: ConcurrencyControl,
262+
databaseName: String) throws -> String {
263+
do {
264+
return try CollectionManager.shared.deleteDocument(
265+
documentId,
266+
concurrencyControl: concurrencyControl,
267+
collectionName: defaultCollectionName,
268+
scopeName: defaultScopeName,
269+
databaseName: databaseName)
270+
} catch {
271+
throw error
272+
}
273+
}
274+
275+
func purgeDocument(_ documentId: String,
276+
databaseName: String) throws {
277+
do {
278+
try CollectionManager.shared.purgeDocument(
279+
documentId,
280+
collectionName: defaultCollectionName,
281+
scopeName: defaultScopeName,
282+
databaseName: databaseName)
283+
} catch {
284+
throw error
285+
}
286+
}
287+
288+
289+
290+
}

0 commit comments

Comments
 (0)