Skip to content

Commit f6f8e4f

Browse files
committed
Sync main sqlite-sync repo
2 parents 09faefd + 14df2d9 commit f6f8e4f

File tree

14 files changed

+408
-9
lines changed

14 files changed

+408
-9
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: publish flutter package
2+
on:
3+
push:
4+
tags:
5+
- '*.*.*'
6+
7+
permissions:
8+
contents: read
9+
id-token: write
10+
11+
jobs:
12+
publish:
13+
runs-on: ubuntu-22.04
14+
name: publish to pub.dev
15+
16+
steps:
17+
18+
- uses: actions/checkout@v4.2.2
19+
20+
- name: download release assets
21+
run: |
22+
VERSION=${GITHUB_REF#refs/tags/}
23+
echo "VERSION=$VERSION" >> $GITHUB_ENV
24+
25+
mkdir -p artifacts
26+
cd artifacts
27+
28+
# Download all platform binaries from the GitHub release
29+
gh release download "$VERSION" --pattern "cloudsync-*.tar.gz"
30+
31+
# Extract all archives
32+
for archive in cloudsync-*.tar.gz; do
33+
name=$(basename "$archive" "-$VERSION.tar.gz")
34+
mkdir -p "$name"
35+
tar -xzf "$archive" -C "$name"
36+
rm "$archive"
37+
done
38+
39+
ls -la
40+
env:
41+
GH_TOKEN: ${{ github.token }}
42+
43+
- uses: dart-lang/setup-dart@v1.7.1
44+
45+
- name: assemble and publish flutter package
46+
run: |
47+
FLUTTER_DIR=packages/flutter
48+
49+
# Android
50+
mkdir -p $FLUTTER_DIR/native_libraries/android
51+
cp artifacts/cloudsync-android-arm64-v8a/cloudsync.so $FLUTTER_DIR/native_libraries/android/cloudsync_android_arm64.so
52+
cp artifacts/cloudsync-android-armeabi-v7a/cloudsync.so $FLUTTER_DIR/native_libraries/android/cloudsync_android_arm.so
53+
cp artifacts/cloudsync-android-x86_64/cloudsync.so $FLUTTER_DIR/native_libraries/android/cloudsync_android_x64.so
54+
55+
# iOS device
56+
mkdir -p $FLUTTER_DIR/native_libraries/ios
57+
cp artifacts/cloudsync-ios/cloudsync.dylib $FLUTTER_DIR/native_libraries/ios/cloudsync_ios_arm64.dylib
58+
59+
# iOS simulator (keep universal/fat binary as-is)
60+
mkdir -p $FLUTTER_DIR/native_libraries/ios-sim
61+
cp artifacts/cloudsync-ios-sim/cloudsync.dylib $FLUTTER_DIR/native_libraries/ios-sim/cloudsync_ios-sim.dylib
62+
63+
# macOS (separate arch-specific dylibs)
64+
mkdir -p $FLUTTER_DIR/native_libraries/mac
65+
cp artifacts/cloudsync-macos-arm64/cloudsync.dylib $FLUTTER_DIR/native_libraries/mac/cloudsync_mac_arm64.dylib
66+
cp artifacts/cloudsync-macos-x86_64/cloudsync.dylib $FLUTTER_DIR/native_libraries/mac/cloudsync_mac_x64.dylib
67+
68+
# Linux
69+
mkdir -p $FLUTTER_DIR/native_libraries/linux
70+
cp artifacts/cloudsync-linux-x86_64/cloudsync.so $FLUTTER_DIR/native_libraries/linux/cloudsync_linux_x64.so
71+
cp artifacts/cloudsync-linux-arm64/cloudsync.so $FLUTTER_DIR/native_libraries/linux/cloudsync_linux_arm64.so
72+
73+
# Windows
74+
mkdir -p $FLUTTER_DIR/native_libraries/windows
75+
cp artifacts/cloudsync-windows-x86_64/cloudsync.dll $FLUTTER_DIR/native_libraries/windows/cloudsync_windows_x64.dll
76+
77+
# Update version
78+
sed -i "s/^version: .*/version: $VERSION/" $FLUTTER_DIR/pubspec.yaml
79+
80+
# Publish to pub.dev
81+
cd $FLUTTER_DIR
82+
dart pub get
83+
dart pub publish --force

.github/workflows/main.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
name: build, test and release sqlite-sync
22
on:
33
push:
4+
branches:
5+
- '**'
6+
tags-ignore:
7+
- '**'
48
workflow_dispatch:
59

610
permissions:
@@ -433,13 +437,9 @@ jobs:
433437
- uses: actions/setup-node@v4
434438
if: steps.tag.outputs.version != ''
435439
with:
436-
node-version: '20'
440+
node-version: '24'
437441
registry-url: 'https://registry.npmjs.org'
438442

439-
- name: update npm
440-
if: steps.tag.outputs.version != ''
441-
run: npm install -g npm@11.5.1
442-
443443
- name: build and publish npm packages
444444
if: steps.tag.outputs.version != ''
445445
run: |
@@ -512,6 +512,7 @@ jobs:
512512
body: |
513513
# Packages
514514
515+
[**Flutter/Dart**](https://pub.dev/packages/sqlite_sync): `flutter pub add sqlite_sync:${{ steps.tag.outputs.version }}` or `dart pub add sqlite_sync:${{ steps.tag.outputs.version }}`
515516
[**Node**](https://www.npmjs.com/package/@sqliteai/sqlite-sync-dev): `npm install @sqliteai/sqlite-sync-dev`
516517
[**WASM**](https://www.npmjs.com/package/@sqliteai/sqlite-wasm): `npm install @sqliteai/sqlite-wasm@dev`
517518
[**React Native**](https://www.npmjs.com/package/@sqliteai/sqlite-sync-react-native): `npm install @sqliteai/sqlite-sync-react-native`

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,10 @@ jniLibs/
5050
.DS_Store
5151
Thumbs.db
5252
CLAUDE.md
53-
*.o
53+
54+
# Dart/Flutter
55+
.dart_tool/
56+
pubspec.lock
57+
.flutter-plugins
58+
.flutter-plugins-dependencies
59+
packages/flutter/native_libraries/

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ else ifeq ($(PLATFORM),android)
132132
CURL_CONFIG = --host $(ARCH)-linux-$(ANDROID_ABI) --with-openssl=$(CURDIR)/$(OPENSSL_INSTALL_DIR) LDFLAGS="-L$(CURDIR)/$(OPENSSL_INSTALL_DIR)/lib" LIBS="-lssl -lcrypto" AR=$(BIN)/llvm-ar AS=$(BIN)/llvm-as CC=$(CC) CXX=$(BIN)/$(ARCH)-linux-$(ANDROID_ABI)-clang++ LD=$(BIN)/ld RANLIB=$(BIN)/llvm-ranlib STRIP=$(BIN)/llvm-strip
133133
TARGET := $(DIST_DIR)/cloudsync.so
134134
CFLAGS += -fPIC -I$(OPENSSL_INSTALL_DIR)/include
135-
LDFLAGS += -shared -fPIC -L$(OPENSSL_INSTALL_DIR)/lib -lssl -lcrypto -lm
135+
LDFLAGS += -shared -fPIC -L$(OPENSSL_INSTALL_DIR)/lib -lssl -lcrypto -lm -Wl,-z,max-page-size=16384
136136
STRIP = $(BIN)/llvm-strip --strip-unneeded $@
137137
else ifeq ($(PLATFORM),ios)
138138
TARGET := $(DIST_DIR)/cloudsync.dylib

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,27 @@ npm install @sqliteai/sqlite-sync-react-native
263263

264264
Then follow the instructions from the [README](https://www.npmjs.com/package/@sqliteai/sqlite-sync-react-native)
265265

266+
### Flutter Package
267+
268+
Add the [sqlite_sync](https://pub.dev/packages/sqlite_sync) package to your project:
269+
270+
```bash
271+
flutter pub add sqlite_sync # Flutter projects
272+
dart pub add sqlite_sync # Dart projects
273+
```
274+
275+
Usage with `sqlite3` package:
276+
```dart
277+
import 'package:sqlite3/sqlite3.dart';
278+
import 'package:sqlite_sync/sqlite_sync.dart';
279+
280+
sqlite3.loadSqliteSyncExtension();
281+
final db = sqlite3.openInMemory();
282+
print(db.select('SELECT cloudsync_version()'));
283+
```
284+
285+
For a complete example, see the [Flutter example](https://github.com/sqliteai/sqlite-extensions-guide/blob/main/examples/flutter/README.md).
286+
266287
## Getting Started
267288

268289
Here's a quick example to get started with SQLite Sync:

packages/flutter/.pubignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Only ignore development files, NOT native_libraries
2+
.dart_tool/
3+
pubspec.lock
4+
5+
# Explicitly include native_libraries (override any parent .gitignore)
6+
!native_libraries/
7+
!native_libraries/**

packages/flutter/LICENSE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../LICENSE.md

packages/flutter/README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# sqlite_sync
2+
3+
SQLite Sync is a multi-platform extension that brings a true local-first experience to your applications with minimal effort. It extends standard SQLite tables with built-in support for offline work and automatic synchronization, allowing multiple devices to operate independently—even without a network connection—and seamlessly stay in sync.
4+
5+
## Installation
6+
7+
```
8+
dart pub add sqlite_sync
9+
```
10+
11+
Requires Dart 3.10+ / Flutter 3.38+.
12+
13+
## Usage
14+
15+
### With `sqlite3`
16+
17+
```dart
18+
import 'package:sqlite3/sqlite3.dart';
19+
import 'package:sqlite_sync/sqlite_sync.dart';
20+
21+
void main() {
22+
// Load once at startup.
23+
sqlite3.loadSqliteSyncExtension();
24+
25+
final db = sqlite3.openInMemory();
26+
27+
// Check version.
28+
final result = db.select('SELECT cloudsync_version() AS version');
29+
print(result.first['version']);
30+
31+
db.dispose();
32+
}
33+
```
34+
35+
### With `drift`
36+
37+
```dart
38+
import 'package:sqlite3/sqlite3.dart';
39+
import 'package:sqlite_sync/sqlite_sync.dart';
40+
import 'package:drift/native.dart';
41+
42+
Sqlite3 loadExtensions() {
43+
sqlite3.loadSqliteSyncExtension();
44+
return sqlite3;
45+
}
46+
47+
// Use when creating the database:
48+
NativeDatabase.createInBackground(
49+
File(path),
50+
sqlite3: loadExtensions,
51+
);
52+
```
53+
54+
## Supported platforms
55+
56+
| Platform | Architectures |
57+
|----------|---------------|
58+
| Android | arm64, arm, x64 |
59+
| iOS | arm64 (device + simulator) |
60+
| macOS | arm64, x64 |
61+
| Linux | arm64, x64 |
62+
| Windows | x64 |
63+
64+
## API
65+
66+
See the full [sqlite-sync API documentation](https://github.com/sqliteai/sqlite-sync/blob/main/API.md).
67+
68+
## License
69+
70+
See [LICENSE](LICENSE).
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include: package:lints/recommended.yaml

packages/flutter/hook/build.dart

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// Copyright (c) 2025 SQLite Cloud, Inc.
2+
// Licensed under the Elastic License 2.0 (see LICENSE.md).
3+
4+
import 'dart:io';
5+
6+
import 'package:code_assets/code_assets.dart';
7+
import 'package:hooks/hooks.dart';
8+
import 'package:path/path.dart' as p;
9+
10+
void main(List<String> args) async {
11+
await build(args, (input, output) async {
12+
if (!input.config.buildCodeAssets) return;
13+
14+
final codeConfig = input.config.code;
15+
final os = codeConfig.targetOS;
16+
final arch = codeConfig.targetArchitecture;
17+
18+
final binaryPath = _resolveBinaryPath(os, arch, codeConfig);
19+
if (binaryPath == null) {
20+
throw UnsupportedError(
21+
'sqlite_sync does not support $os $arch.',
22+
);
23+
}
24+
25+
final nativeLibDir = p.join(
26+
input.packageRoot.toFilePath(),
27+
'native_libraries',
28+
);
29+
final file = File(p.join(nativeLibDir, binaryPath));
30+
if (!file.existsSync()) {
31+
throw StateError(
32+
'Pre-built binary not found: ${file.path}. '
33+
'Run the CI pipeline to populate native_libraries/.',
34+
);
35+
}
36+
37+
output.dependencies.add(file.uri);
38+
39+
final assetFile = await _prepareAssetFile(
40+
input: input,
41+
os: os,
42+
arch: arch,
43+
config: codeConfig,
44+
file: file,
45+
);
46+
47+
output.assets.code.add(
48+
CodeAsset(
49+
package: input.packageName,
50+
name: 'src/native/sqlite_sync_extension.dart',
51+
linkMode: DynamicLoadingBundled(),
52+
file: assetFile.uri,
53+
),
54+
);
55+
});
56+
}
57+
58+
Future<File> _prepareAssetFile({
59+
required BuildInput input,
60+
required OS os,
61+
required Architecture arch,
62+
required CodeConfig config,
63+
required File file,
64+
}) async {
65+
if (os != OS.iOS || config.iOS.targetSdk == IOSSdk.iPhoneOS) {
66+
return file;
67+
}
68+
69+
final thinArch = switch (arch) {
70+
Architecture.arm64 => 'arm64',
71+
Architecture.x64 => 'x86_64',
72+
_ => null,
73+
};
74+
if (thinArch == null) {
75+
return file;
76+
}
77+
78+
final outputName = 'cloudsync_ios_sim_$thinArch.dylib';
79+
final outputFile = File.fromUri(input.outputDirectory.resolve(outputName));
80+
await outputFile.parent.create(recursive: true);
81+
82+
final result = await Process.run('/usr/bin/lipo', [
83+
file.path,
84+
'-thin',
85+
thinArch,
86+
'-output',
87+
outputFile.path,
88+
]);
89+
if (result.exitCode != 0) {
90+
throw StateError(
91+
'Failed to thin sqlite_sync iOS simulator binary for $thinArch: '
92+
'${result.stderr}',
93+
);
94+
}
95+
96+
return outputFile;
97+
}
98+
99+
String? _resolveBinaryPath(OS os, Architecture arch, CodeConfig config) {
100+
if (os == OS.android) {
101+
return switch (arch) {
102+
Architecture.arm64 => 'android/cloudsync_android_arm64.so',
103+
Architecture.arm => 'android/cloudsync_android_arm.so',
104+
Architecture.x64 => 'android/cloudsync_android_x64.so',
105+
_ => null,
106+
};
107+
}
108+
109+
if (os == OS.iOS) {
110+
final sdk = config.iOS.targetSdk;
111+
if (sdk == IOSSdk.iPhoneOS) {
112+
return 'ios/cloudsync_ios_arm64.dylib';
113+
}
114+
// Simulator: fat binary (arm64 + x64)
115+
return 'ios-sim/cloudsync_ios-sim.dylib';
116+
}
117+
118+
if (os == OS.macOS) {
119+
return switch (arch) {
120+
Architecture.arm64 => 'mac/cloudsync_mac_arm64.dylib',
121+
Architecture.x64 => 'mac/cloudsync_mac_x64.dylib',
122+
_ => null,
123+
};
124+
}
125+
126+
if (os == OS.linux) {
127+
return switch (arch) {
128+
Architecture.x64 => 'linux/cloudsync_linux_x64.so',
129+
Architecture.arm64 => 'linux/cloudsync_linux_arm64.so',
130+
_ => null,
131+
};
132+
}
133+
134+
if (os == OS.windows) {
135+
return switch (arch) {
136+
Architecture.x64 => 'windows/cloudsync_windows_x64.dll',
137+
_ => null,
138+
};
139+
}
140+
141+
return null;
142+
}

0 commit comments

Comments
 (0)