Skip to content

Commit 97c0538

Browse files
initial JourneyApps PowerSync
1 parent 489016d commit 97c0538

19 files changed

+239
-121
lines changed

LICENSE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
Copyright 2021 Oscar Franco
1+
Copyright 2023 Oscar Franco, Journey Mobile, Inc.
22

33
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
44

55
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
66

7-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Alpha
2+
This package is currently in an alpha release. Functionality could change dramatically in future releases. Certain functions may be partially implemented or buggy.
3+
14
![screenshot](https://raw.githubusercontent.com/margelo/react-native-quick-sqlite/main/header2.png)
25

36
<div align="center">
@@ -299,7 +302,7 @@ post_install do |installer|
299302
installer.pods_project.targets.each do |target|
300303
if target.name == "react-native-quick-sqlite" then
301304
target.build_configurations.each do |config|
302-
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'SQLITE_ENABLE_FTS5=1'
305+
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', '<SQLITE_FLAGS>']
303306
end
304307
end
305308
end

android/.project

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<projectDescription>
3-
<name>android_</name>
3+
<name>journeyapps_react-native-quick-sqlite</name>
44
<comment>Project android_ created by Buildship.</comment>
55
<projects>
66
</projects>
@@ -14,4 +14,15 @@
1414
<natures>
1515
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
1616
</natures>
17+
<filteredResources>
18+
<filter>
19+
<id>1695029328310</id>
20+
<name></name>
21+
<type>30</type>
22+
<matcher>
23+
<id>org.eclipse.core.resources.regexFilterMatcher</id>
24+
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
25+
</matcher>
26+
</filter>
27+
</filteredResources>
1728
</projectDescription>

android/.settings/org.eclipse.buildship.core.prefs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
arguments=
1+
arguments=--init-script /var/folders/jx/_56srfzj0s3d98w7v3tl8kvr0000gn/T/d146c9752a26f79b52047fb6dc6ed385d064e120494f96f08ca63a317c41f94c.gradle --init-script /var/folders/jx/_56srfzj0s3d98w7v3tl8kvr0000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle
22
auto.sync=false
33
build.scans.enabled=false
4-
connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(6.0))
4+
connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(7.4.2))
55
connection.project.dir=
66
eclipse.preferences.version=1
77
gradle.user.home=
8-
java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
8+
java.home=/usr/local/Cellar/openjdk@11/11.0.14.1/libexec/openjdk.jdk/Contents/Home
99
jvm.arguments=
1010
offline.mode=false
1111
override.workspace.settings=true

android/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ find_package(ReactAndroid REQUIRED CONFIG)
4646
find_package(fbjni REQUIRED CONFIG)
4747
find_library(LOG_LIB log)
4848

49+
if(${USE_HERMES})
50+
set(JSEXECUTOR_LIB ReactAndroid::hermes_executor)
51+
else()
52+
set(JSEXECUTOR_LIB ReactAndroid::jscexecutor)
53+
endif()
54+
4955

5056
target_link_libraries(
5157
${PACKAGE_NAME}
@@ -54,5 +60,7 @@ target_link_libraries(
5460
ReactAndroid::jsi
5561
ReactAndroid::turbomodulejsijni
5662
ReactAndroid::react_nativemodule_core
63+
${JSEXECUTOR_LIB}
5764
android
65+
powersync ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libpowersync.so
5866
)

android/build.gradle

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ android {
6262
prefab true
6363
}
6464

65+
sourceSets.main {
66+
jniLibs.srcDirs = ['src/main/jniLibs']
67+
}
68+
6569
defaultConfig {
6670
minSdkVersion 21
6771
targetSdkVersion safeExtGet('targetSdkVersion', 28)
@@ -86,9 +90,7 @@ android {
8690
"META-INF/**",
8791
"**/libjsi.so",
8892
"**/libreact_nativemodule_core.so",
89-
"**/libturbomodulejsijni.so",
90-
"**/libc++_shared.so",
91-
"**/libfbjni.so"
93+
"**/libturbomodulejsijni.so"
9294
]
9395
}
9496

Binary file not shown.
Binary file not shown.
213 KB
Binary file not shown.
Binary file not shown.

cpp/bindings.cpp

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,75 @@
99
#include <string>
1010
#include "macros.h"
1111
#include <iostream>
12+
#include "sqlite3.h"
1213

1314
using namespace std;
1415
using namespace facebook;
1516

1617
namespace osp {
1718
string docPathStr;
1819
std::shared_ptr<react::CallInvoker> invoker;
20+
jsi::Runtime *runtime;
21+
22+
extern "C" {
23+
int sqlite3_powersync_init(sqlite3 *db, char **pzErrMsg,
24+
const sqlite3_api_routines *pApi);
25+
}
26+
27+
/**
28+
* This function loads the PowerSync extension into SQLite
29+
*/
30+
int init_powersync_sqlite_plugin() {
31+
int result = sqlite3_auto_extension((void (*)(void))&sqlite3_powersync_init);
32+
return result;
33+
}
1934

2035
void clearState() {
21-
sqliteCloseAll();
36+
sqliteCloseAll();
37+
}
38+
39+
/**
40+
* Callback handler for SQLite table updates
41+
*/
42+
void
43+
updateTableHandler(void *voidDBName, int opType, char const *dbName, char const *tableName, sqlite3_int64 rowId)
44+
{
45+
/**
46+
* No DB operations should occur when this callback is fired from SQLite.
47+
* This function triggers an async invocation to call watch callbacks,
48+
* avoiding holding SQLite up.
49+
*/
50+
invoker->invokeAsync([voidDBName, opType, dbName, tableName, rowId]
51+
{
52+
try {
53+
// Sqlite 3 just returns main as the db name is no other DBs are attached
54+
auto global = runtime->global();
55+
jsi::Function handlerFunction = global.getPropertyAsFunction(*runtime, "triggerUpdateHook");
56+
57+
std::string actualDBName = std::string((char *)voidDBName);
58+
auto jsiDbName = jsi::String::createFromAscii(*runtime, actualDBName);
59+
auto jsiTableName = jsi::String::createFromAscii(*runtime, tableName);
60+
auto jsiOpType = jsi::Value(opType);
61+
auto jsiRowId = jsi::String::createFromAscii(*runtime, std::to_string(rowId));
62+
handlerFunction.call(*runtime, move(jsiDbName), move(jsiTableName), move(jsiOpType), move(jsiRowId));
63+
} catch (jsi::JSINativeException e) {
64+
std::cout << e.what() << std::endl;
65+
} catch (...) {
66+
std::cout << "Unknown error" << std::endl;
67+
}
68+
});
2269
}
2370

2471
void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker, const char *docPath)
2572
{
2673
docPathStr = std::string(docPath);
2774
auto pool = std::make_shared<ThreadPool>();
2875
invoker = jsCallInvoker;
76+
runtime = &rt;
2977

3078
auto open = HOSTFN("open", 2) {
79+
init_powersync_sqlite_plugin();
80+
3181
if (count == 0)
3282
{
3383
throw jsi::JSError(rt, "[react-native-quick-sqlite][open] database name is required");
@@ -50,13 +100,17 @@ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker
50100
tempDocPath = tempDocPath + "/" + args[1].asString(rt).utf8(rt);
51101
}
52102

53-
SQLiteOPResult result = sqliteOpenDb(dbName, tempDocPath);
103+
sqlite3 *db;
104+
SQLiteOPResult result = sqliteOpenDb(dbName, tempDocPath, &db);
54105

55106
if (result.type == SQLiteError)
56107
{
57108
throw jsi::JSError(rt, result.errorMessage.c_str());
58109
}
59110

111+
// Register for update hooks
112+
sqlite3_update_hook(db, updateTableHandler, getDBName(db));
113+
60114
return {};
61115
});
62116

cpp/sqliteBridge.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
using namespace std;
2121
using namespace facebook;
2222

23+
24+
25+
2326
map<string, sqlite3 *> dbMap = map<string, sqlite3 *>();
2427

2528
bool folder_exists(const std::string &foldername)
@@ -80,26 +83,25 @@ string get_db_path(string const dbName, string const docPath)
8083
return docPath + "/" + dbName;
8184
}
8285

83-
SQLiteOPResult sqliteOpenDb(string const dbName, string const docPath)
86+
SQLiteOPResult sqliteOpenDb(string const dbName, string const docPath, sqlite3 **db)
8487
{
8588
string dbPath = get_db_path(dbName, docPath);
8689

8790
int sqlOpenFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX;
8891

89-
sqlite3 *db;
9092
int exit = 0;
91-
exit = sqlite3_open_v2(dbPath.c_str(), &db, sqlOpenFlags, nullptr);
93+
exit = sqlite3_open_v2(dbPath.c_str(), db, sqlOpenFlags, nullptr);
9294

9395
if (exit != SQLITE_OK)
9496
{
9597
return SQLiteOPResult{
9698
.type = SQLiteError,
97-
.errorMessage = sqlite3_errmsg(db)
99+
.errorMessage = sqlite3_errmsg(*db)
98100
};
99101
}
100102
else
101103
{
102-
dbMap[dbName] = db;
104+
dbMap[dbName] = *db;
103105
}
104106

105107
return SQLiteOPResult{
@@ -130,6 +132,15 @@ SQLiteOPResult sqliteCloseDb(string const dbName)
130132
};
131133
}
132134

135+
char* getDBName(sqlite3 *db) {
136+
for (auto const& x : dbMap) {
137+
if (x.second == db) {
138+
return (char*) x.first.c_str();
139+
}
140+
}
141+
return NULL;
142+
}
143+
133144
void sqliteCloseAll() {
134145
for (auto const& x : dbMap) {
135146
// In certain cases, this will return SQLITE_OK, mark the database connection as an unusable "zombie",
@@ -346,7 +357,7 @@ SQLiteOPResult sqliteExecute(string const dbName, string const &query, vector<Qu
346357
{
347358
int blob_size = sqlite3_column_bytes(statement, i);
348359
const void *blob = sqlite3_column_blob(statement, i);
349-
uint8_t *data = new uint8_t[blob_size];
360+
uint8_t *data;
350361
memcpy(data, blob, blob_size);
351362
row[column_name] = createArrayBufferQuickValue(data, blob_size);
352363
break;

cpp/sqliteBridge.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@
99

1010
#include "JSIHelper.h"
1111
#include <vector>
12+
#include <sqlite3.h>
1213

1314
using namespace std;
1415
using namespace facebook;
1516

16-
SQLiteOPResult sqliteOpenDb(string const dbName, string const docPath);
17+
SQLiteOPResult sqliteOpenDb(string const dbName, string const docPath, sqlite3 **db);
1718

1819
SQLiteOPResult sqliteCloseDb(string const dbName);
1920

@@ -27,4 +28,6 @@ SQLiteOPResult sqliteExecute(string const dbName, string const &query, vector<Qu
2728

2829
SequelLiteralUpdateResult sqliteExecuteLiteral(string const dbName, string const &query);
2930

31+
char* getDBName(sqlite3 *db);
32+
3033
void sqliteCloseAll();

example/src/Database.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { DataSource } from 'typeorm';
2-
import { typeORMDriver } from 'react-native-quick-sqlite';
32
import { Book } from './model/Book';
43
import { User } from './model/User';
54
// import { Buffer } from 'buffer';
@@ -10,7 +9,7 @@ export async function typeORMInit() {
109
type: 'react-native',
1110
database: 'typeormdb',
1211
location: '.',
13-
driver: typeORMDriver,
12+
driver: require('react-native-quick-sqlite'),
1413
entities: [Book, User],
1514
synchronize: true,
1615
});

package.json

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
{
2-
"name": "react-native-quick-sqlite",
3-
"version": "8.0.5",
2+
"name": "@journeyapps/react-native-quick-sqlite",
3+
"publishConfig": {
4+
"registry": "https://registry.npmjs.org/",
5+
"access": "public"
6+
},
7+
"version": "0.0.0",
48
"description": "Fast SQLite for react-native",
59
"main": "lib/commonjs/index",
610
"module": "lib/module/index",
@@ -13,6 +17,7 @@
1317
"android",
1418
"ios",
1519
"cpp",
20+
"meta.json",
1621
"react-native-quick-sqlite.podspec",
1722
"!lib/typescript/example",
1823
"!android/build",
@@ -23,8 +28,11 @@
2328
"!**/__mocks__"
2429
],
2530
"scripts": {
31+
"build": "bob build",
32+
"clean": "rm -rf lib tsconfig.tsbuildinfo",
2633
"typescript": "tsc --noEmit",
2734
"prepare": "bob build",
35+
"preversion": "node ./scripts/dev-package-version.js $npm_package_version",
2836
"example": "yarn --cwd example",
2937
"pods": "cd example/ios && bundle exec pod install",
3038
"bootstrap": "yarn example && yarn && yarn pods",
@@ -36,15 +44,12 @@
3644
"android"
3745
],
3846
"repository": "https://github.com/margelo/react-native-quick-sqlite",
39-
"author": "Marc Rousavy <me@mrousavy.com> (https://github.com/mrousavy)",
47+
"author": "JOURNEYAPPS",
4048
"license": "MIT",
4149
"bugs": {
4250
"url": "https://github.com/margelo/react-native-quick-sqlite/issues"
4351
},
4452
"homepage": "https://github.com/margelo/react-native-quick-sqlite#readme",
45-
"publishConfig": {
46-
"registry": "https://registry.npmjs.org/"
47-
},
4853
"devDependencies": {
4954
"react": "18.2.0",
5055
"react-native": "0.71.0",

react-native-quick-sqlite.podspec

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
require "json"
22

33
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4+
if (File.exist?(File.join(__dir__, "meta.json")))
5+
meta = JSON.parse(File.read(File.join(__dir__, "meta.json")))
6+
package["version"] = meta["version"]
7+
end
48

59
Pod::Spec.new do |s|
610
s.name = "react-native-quick-sqlite"
@@ -25,6 +29,7 @@ Pod::Spec.new do |s|
2529
s.dependency "React-callinvoker"
2630
s.dependency "React"
2731
s.dependency "React-Core"
32+
s.dependency 'powersync-sqlite-core'
2833

2934
if ENV['QUICK_SQLITE_USE_PHONE_VERSION'] == '1' then
3035
s.exclude_files = "cpp/sqlite3.c", "cpp/sqlite3.h"

scripts/dev-package-version.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Dev package version like 0.0.0-dev-hash seem to cause issues with the podspec
3+
* This script will remove the -dev-hash from the version.
4+
*/
5+
const fs = require('fs');
6+
const path = require('path');
7+
const version = process.argv[2];
8+
9+
if (version.includes('0.0.0')) {
10+
console.log(`Storing current version for dev version ${version}`);
11+
const currentPackage = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../package.json'), 'utf-8'));
12+
// Backup the current version
13+
fs.writeFileSync(
14+
path.join(__dirname, '../meta.json'),
15+
JSON.stringify({ version: currentPackage.version }, null, '\t')
16+
);
17+
}

0 commit comments

Comments
 (0)