Skip to content

Commit eeff1a2

Browse files
committed
Add Flutter multi-platform package and fix Android: increase max page size to 16kb
1 parent c481506 commit eeff1a2

File tree

12 files changed

+296
-4
lines changed

12 files changed

+296
-4
lines changed

.github/workflows/main.yml

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ jobs:
294294

295295
- name: update npm
296296
if: steps.tag.outputs.version != ''
297-
run: npm install -g npm@11.5.1
297+
run: sudo npm install -g npm@11.9.0
298298

299299
- name: build and publish npm packages
300300
if: steps.tag.outputs.version != ''
@@ -349,12 +349,54 @@ jobs:
349349
echo " Platform packages: 7"
350350
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
351351
352+
- name: assemble and publish flutter package
353+
if: steps.tag.outputs.version != ''
354+
run: |
355+
VERSION=${{ steps.tag.outputs.version }}
356+
FLUTTER_DIR=packages/flutter
357+
358+
# Android
359+
mkdir -p $FLUTTER_DIR/native_libraries/android
360+
cp artifacts/js-android-arm64-v8a/js.so $FLUTTER_DIR/native_libraries/android/js_android_arm64.so
361+
cp artifacts/js-android-x86_64/js.so $FLUTTER_DIR/native_libraries/android/js_android_x64.so
362+
363+
# iOS device
364+
mkdir -p $FLUTTER_DIR/native_libraries/ios
365+
cp artifacts/js-ios/js.dylib $FLUTTER_DIR/native_libraries/ios/js_ios_arm64.dylib
366+
367+
# iOS simulator (keep universal/fat binary as-is)
368+
mkdir -p $FLUTTER_DIR/native_libraries/ios-sim
369+
cp artifacts/js-ios-sim/js.dylib $FLUTTER_DIR/native_libraries/ios-sim/js_ios-sim.dylib
370+
371+
# macOS (separate arch-specific dylibs)
372+
mkdir -p $FLUTTER_DIR/native_libraries/mac
373+
cp artifacts/js-macos-arm64/js.dylib $FLUTTER_DIR/native_libraries/mac/js_mac_arm64.dylib
374+
cp artifacts/js-macos-x86_64/js.dylib $FLUTTER_DIR/native_libraries/mac/js_mac_x64.dylib
375+
376+
# Linux
377+
mkdir -p $FLUTTER_DIR/native_libraries/linux
378+
cp artifacts/js-linux-x86_64/js.so $FLUTTER_DIR/native_libraries/linux/js_linux_x64.so
379+
cp artifacts/js-linux-arm64/js.so $FLUTTER_DIR/native_libraries/linux/js_linux_arm64.so
380+
381+
# Windows
382+
mkdir -p $FLUTTER_DIR/native_libraries/windows
383+
cp artifacts/js-windows-x86_64/js.dll $FLUTTER_DIR/native_libraries/windows/js_windows_x64.dll
384+
385+
# Update version
386+
sed -i "s/^version: .*/version: $VERSION/" $FLUTTER_DIR/pubspec.yaml
387+
388+
# Publish to pub.dev
389+
cd $FLUTTER_DIR
390+
dart pub publish --dry-run
391+
dart pub publish --force
392+
352393
- uses: softprops/action-gh-release@v2.2.1
353394
if: steps.tag.outputs.version != ''
354395
with:
355396
body: |
356397
# Packages
357398
399+
[**Flutter/Dart**](https://pub.dev/packages/sqlite_js): `dart pub add sqlite_js`
358400
[**Node**](https://www.npmjs.com/package/@sqliteai/sqlite-js): `npm install @sqliteai/sqlite-js`
359401
[**Android**](https://central.sonatype.com/artifact/ai.sqlite/js): `ai.sqlite:js:${{ steps.tag.outputs.version }}`
360402
[**Swift**](https://github.com/sqliteai/sqlite-js#swift-package): [Installation Guide](https://github.com/sqliteai/sqlite-js#swift-package)

.gitignore

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,11 @@ packages/node/test-platform-packages/
4343

4444
# System
4545
.DS_Store
46-
Thumbs.db
46+
Thumbs.db
47+
48+
# Dart/Flutter
49+
.dart_tool/
50+
pubspec.lock
51+
.flutter-plugins
52+
.flutter-plugins-dependencies
53+
packages/flutter/native_libraries/

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ else ifeq ($(PLATFORM),android)
6767
endif
6868
CC = $(BIN)/$(ARCH)-linux-android26-clang
6969
TARGET := $(DIST_DIR)/js.so
70-
LDFLAGS := -lm -shared
70+
LDFLAGS := -lm -shared -Wl,-z,max-page-size=16384
7171
STRIP = $(BIN)/llvm-strip --strip-unneeded $@
7272
else ifeq ($(PLATFORM),ios)
7373
TARGET := $(DIST_DIR)/js.dylib

packages/flutter/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Changelog
2+
3+
## 1.1.16
4+
5+
- Initial Flutter package release
6+
- Added support for Android 16kb page size devices

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: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# sqlite_js
2+
3+
SQLite JavaScript extension for Flutter/Dart. Execute JavaScript code directly within SQLite using the QuickJS engine.
4+
5+
## Installation
6+
7+
```
8+
dart pub add sqlite_js
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_js/sqlite_js.dart';
20+
21+
void main() {
22+
// Load once at startup.
23+
sqlite3.loadSqliteJsExtension();
24+
25+
final db = sqlite3.openInMemory();
26+
27+
// Execute JavaScript code.
28+
final result = db.select("SELECT js_eval('1 + 2') AS result");
29+
print(result.first['result']); // 3
30+
31+
// Use JavaScript for more complex operations.
32+
db.execute('''
33+
SELECT js_eval('
34+
const data = JSON.parse(input);
35+
return data.map(x => x * 2);
36+
', '[1, 2, 3]') AS doubled
37+
''');
38+
39+
db.dispose();
40+
}
41+
```
42+
43+
### With `drift`
44+
45+
```dart
46+
import 'package:sqlite3/sqlite3.dart';
47+
import 'package:sqlite_js/sqlite_js.dart';
48+
import 'package:drift/native.dart';
49+
50+
Sqlite3 loadExtensions() {
51+
sqlite3.loadSqliteJsExtension();
52+
return sqlite3;
53+
}
54+
55+
// Use when creating the database:
56+
NativeDatabase.createInBackground(
57+
File(path),
58+
sqlite3: loadExtensions,
59+
);
60+
```
61+
62+
## Supported platforms
63+
64+
| Platform | Architectures |
65+
|----------|---------------|
66+
| Android | arm64, arm, x64 |
67+
| iOS | arm64 (device + simulator) |
68+
| macOS | arm64, x64 |
69+
| Linux | arm64, x64 |
70+
| Windows | x64 |
71+
72+
## API
73+
74+
See the full [sqlite-js API documentation](https://github.com/sqliteai/sqlite-js/blob/main/API.md).
75+
76+
## License
77+
78+
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: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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_js 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.assets.code.add(
38+
CodeAsset(
39+
package: input.packageName,
40+
name: 'src/native/sqlite_js_extension.dart',
41+
linkMode: DynamicLoadingBundled(),
42+
file: file.uri,
43+
),
44+
);
45+
});
46+
}
47+
48+
String? _resolveBinaryPath(OS os, Architecture arch, CodeConfig config) {
49+
if (os == OS.android) {
50+
return switch (arch) {
51+
Architecture.arm64 => 'android/js_android_arm64.so',
52+
Architecture.arm => 'android/js_android_arm.so',
53+
Architecture.x64 => 'android/js_android_x64.so',
54+
_ => null,
55+
};
56+
}
57+
58+
if (os == OS.iOS) {
59+
final sdk = config.iOS.targetSdk;
60+
if (sdk == IOSSdk.iPhoneOS) {
61+
return 'ios/js_ios_arm64.dylib';
62+
}
63+
// Simulator: fat binary (arm64 + x64)
64+
return 'ios-sim/js_ios-sim.dylib';
65+
}
66+
67+
if (os == OS.macOS) {
68+
return switch (arch) {
69+
Architecture.arm64 => 'mac/js_mac_arm64.dylib',
70+
Architecture.x64 => 'mac/js_mac_x64.dylib',
71+
_ => null,
72+
};
73+
}
74+
75+
if (os == OS.linux) {
76+
return switch (arch) {
77+
Architecture.x64 => 'linux/js_linux_x64.so',
78+
Architecture.arm64 => 'linux/js_linux_arm64.so',
79+
_ => null,
80+
};
81+
}
82+
83+
if (os == OS.windows) {
84+
return switch (arch) {
85+
Architecture.x64 => 'windows/js_windows_x64.dll',
86+
_ => null,
87+
};
88+
}
89+
90+
return null;
91+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright (c) 2025 SQLite Cloud, Inc.
2+
// Licensed under the Elastic License 2.0 (see LICENSE.md).
3+
4+
/// SQLite JavaScript extension for Flutter/Dart.
5+
library sqlite_js;
6+
7+
export 'src/sqlite_js.dart';
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (c) 2025 SQLite Cloud, Inc.
2+
// Licensed under the Elastic License 2.0 (see LICENSE.md).
3+
4+
import 'dart:ffi';
5+
6+
import 'package:sqlite3/sqlite3.dart';
7+
8+
// @Native resolves from the code asset declared in hook/build.dart.
9+
// The asset ID is 'package:sqlite_js/src/native/sqlite_js_extension.dart'.
10+
@Native<Int Function(Pointer<Void>, Pointer<Void>, Pointer<Void>)>(
11+
assetId: 'package:sqlite_js/src/native/sqlite_js_extension.dart',
12+
)
13+
external int sqlite3_js_init(
14+
Pointer<Void> db,
15+
Pointer<Void> pzErrMsg,
16+
Pointer<Void> pApi,
17+
);
18+
19+
extension SqliteJsExtension on Sqlite3 {
20+
/// Loads the sqlite-js extension.
21+
///
22+
/// Call once at app startup. All subsequently opened databases
23+
/// will have JavaScript functions available.
24+
///
25+
/// Works with both `sqlite3` package and `drift` ORM.
26+
void loadSqliteJsExtension() {
27+
ensureExtensionLoaded(
28+
SqliteExtension(
29+
Native.addressOf<
30+
NativeFunction<
31+
Int Function(Pointer<Void>, Pointer<Void>, Pointer<Void>)>>(
32+
sqlite3_js_init,
33+
).cast(),
34+
),
35+
);
36+
}
37+
}

0 commit comments

Comments
 (0)