Skip to content

Commit

Permalink
Merge pull request #230 from powersync-ja/feat/web-encryption
Browse files Browse the repository at this point in the history
Web support for `powersync_sqlcipher`
  • Loading branch information
simolus3 authored Jan 29, 2025
2 parents 51a6061 + 31fc274 commit 98ef589
Show file tree
Hide file tree
Showing 37 changed files with 453 additions and 228 deletions.
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,40 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## 2025-01-28

### Changes

---

Packages with breaking changes:

- There are no breaking changes in this release.

Packages with other changes:

- [`powersync_core` - `v1.1.2`](#powersync_core---v112)
- [`powersync_attachments_helper` - `v0.6.18`](#powersync_attachments_helper---v0618)
- [`powersync_sqlcipher` - `v0.1.4`](#powersync_sqlcipher---v014)
- [`powersync` - `v1.11.2`](#powersync---v1112)

Packages with dependency updates only:

> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `powersync_attachments_helper` - `v0.6.18`
- `powersync_sqlcipher` - `v0.1.4`
- `powersync` - `v1.11.2`

---

#### `powersync_core` - `v1.1.2`

- Web: Support running in contexts where web workers are unavailable.
- Web: Fix sync worker logs not being disabled.
- `powersync_sqlcipher`: Web support.


## 2025-01-16

### Changes
Expand Down
2 changes: 1 addition & 1 deletion demos/benchmarks/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ environment:
dependencies:
flutter:
sdk: flutter
powersync: ^1.11.1
powersync: ^1.11.2
path_provider: ^2.1.1
path: ^1.8.3
logging: ^1.2.0
Expand Down
2 changes: 1 addition & 1 deletion demos/django-todolist/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ environment:
dependencies:
flutter:
sdk: flutter
powersync: ^1.11.1
powersync: ^1.11.2
path_provider: ^2.1.1
path: ^1.8.3
logging: ^1.2.0
Expand Down
2 changes: 1 addition & 1 deletion demos/firebase-nodejs-todolist/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies:
flutter:
sdk: flutter

powersync: ^1.11.1
powersync: ^1.11.2
path_provider: ^2.1.1
supabase_flutter: ^2.0.1
path: ^1.8.3
Expand Down
2 changes: 1 addition & 1 deletion demos/supabase-anonymous-auth/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies:
flutter:
sdk: flutter

powersync: ^1.11.1
powersync: ^1.11.2
path_provider: ^2.1.1
supabase_flutter: ^2.0.2
path: ^1.8.3
Expand Down
2 changes: 1 addition & 1 deletion demos/supabase-edge-function-auth/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies:
flutter:
sdk: flutter

powersync: ^1.11.1
powersync: ^1.11.2
path_provider: ^2.1.1
supabase_flutter: ^2.0.2
path: ^1.8.3
Expand Down
2 changes: 1 addition & 1 deletion demos/supabase-simple-chat/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ dependencies:

supabase_flutter: ^2.0.2
timeago: ^3.6.0
powersync: ^1.11.1
powersync: ^1.11.2
path_provider: ^2.1.1
path: ^1.8.3
logging: ^1.2.0
Expand Down
4 changes: 2 additions & 2 deletions demos/supabase-todolist-drift/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ environment:
dependencies:
flutter:
sdk: flutter
powersync_attachments_helper: ^0.6.17
powersync: ^1.11.1
powersync_attachments_helper: ^0.6.17+1
powersync: ^1.11.2
path_provider: ^2.1.1
supabase_flutter: ^2.0.1
path: ^1.8.3
Expand Down
2 changes: 1 addition & 1 deletion demos/supabase-todolist-optional-sync/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ environment:
dependencies:
flutter:
sdk: flutter
powersync: ^1.11.1
powersync: ^1.11.2
path_provider: ^2.1.1
supabase_flutter: ^2.0.1
path: ^1.8.3
Expand Down
2 changes: 2 additions & 0 deletions demos/supabase-todolist/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/

# IntelliJ related
Expand Down
20 changes: 10 additions & 10 deletions demos/supabase-todolist/macos/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ PODS:
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- powersync-sqlite-core (0.3.4)
- powersync-sqlite-core (0.3.9)
- powersync_flutter_libs (0.0.1):
- FlutterMacOS
- powersync-sqlite-core (~> 0.3.4)
- powersync-sqlite-core (~> 0.3.8)
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
Expand Down Expand Up @@ -64,16 +64,16 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos

SPEC CHECKSUMS:
app_links: 10e0a0ab602ffaf34d142cd4862f29d34b303b2a
app_links: 9028728e32c83a0831d9db8cf91c526d16cc5468
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
powersync-sqlite-core: d029aa444d33acbb05b47f9f9757b2650578e2d3
powersync_flutter_libs: 44829eda70d4f87c9271e963a54126ce19408d7c
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
powersync-sqlite-core: 7515d321eb8e3c08b5259cdadb9d19b1876fe13a
powersync_flutter_libs: 330d8309223a121ec15a7334d9edc105053e5f82
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb
sqlite3_flutter_libs: 5ca46c1a04eddfbeeb5b16566164aa7ad1616e7b
url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399
sqlite3_flutter_libs: 03311aede9d32fb2d24e32bebb8cd01c3b2e6239
url_launcher_macos: de10e46d8d8b9e3a7b8a133e8de92b104379f05e

PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367

COCOAPODS: 1.15.2
COCOAPODS: 1.16.2
6 changes: 5 additions & 1 deletion demos/supabase-todolist/macos/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import Cocoa
import FlutterMacOS

@NSApplicationMain
@main
class AppDelegate: FlutterAppDelegate {
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}

override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
return true
}
}
4 changes: 2 additions & 2 deletions demos/supabase-todolist/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ environment:
dependencies:
flutter:
sdk: flutter
powersync_attachments_helper: ^0.6.17
powersync: ^1.11.1
powersync_attachments_helper: ^0.6.17+1
powersync: ^1.11.2
path_provider: ^2.1.1
supabase_flutter: ^2.0.1
path: ^1.8.3
Expand Down
6 changes: 6 additions & 0 deletions packages/powersync/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 1.11.2

- Web: Support running in contexts where web workers are unavailable.
- Web: Fix sync worker logs not being disabled.
- `powersync_sqlcipher`: Web support.

## 1.11.1

- Fix `statusStream` emitting the same sync status multiple times.
Expand Down
178 changes: 3 additions & 175 deletions packages/powersync/bin/setup_web.dart
Original file line number Diff line number Diff line change
@@ -1,176 +1,4 @@
import 'dart:convert';
import 'dart:io';
import 'package:collection/collection.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:pubspec_parse/pubspec_parse.dart';
import 'package:args/args.dart';
// ignore: implementation_imports
import 'package:powersync_core/src/setup_web.dart';

void main(List<String> arguments) async {
var parser = ArgParser();
// Add a flag to enable/disable the download of worker (defaults to true)
// Pass the --no-worker argument to disable the download of the worker
// dart run powersync:setup_web --no-worker
parser.addFlag('worker', defaultsTo: true);
// Add a option to specify the output directory (defaults to web)
// Pass the --output-dir argument to specify the output directory
// dart run powersync:setup_web --output-dir assets
parser.addOption('output-dir', abbr: 'o', defaultsTo: 'web');
var results = parser.parse(arguments);
bool downloadWorker = results.flag('worker');
String outputDir = results.option('output-dir')!;

final root = Directory.current.uri;
print('Project root: ${root.toFilePath()}');

final wasmPath = '${root.toFilePath()}$outputDir/sqlite3.wasm';

final workerPath = '${root.toFilePath()}$outputDir/powersync_db.worker.js';
final syncWorkerPath =
'${root.toFilePath()}$outputDir/powersync_sync.worker.js';

final packageConfigFile = File.fromUri(
root.resolve('.dart_tool/package_config.json'),
);
dynamic packageConfig;
try {
packageConfig = json.decode(await packageConfigFile.readAsString());
} on FileSystemException {
print('Missing .dart_tool/package_config.json');
print('Run `flutter pub get` first.');
exit(1);
} on FormatException {
print('Invalid .dart_tool/package_config.json');
print('Run `flutter pub get` first.');
exit(1);
}

try {
final httpClient = HttpClient();

final powersyncPackageName = 'powersync';

if (downloadWorker) {
final powersyncPkg =
getPackageFromConfig(packageConfig, powersyncPackageName);

final powersyncVersion = getPubspecVersion(
packageConfigFile, powersyncPkg, powersyncPackageName);

final workerUrl =
'https://github.com/powersync-ja/powersync.dart/releases/download/powersync-v$powersyncVersion/powersync_db.worker.js';

final syncWorkerUrl =
'https://github.com/powersync-ja/powersync.dart/releases/download/powersync-v$powersyncVersion/powersync_sync.worker.js';

await downloadFile(httpClient, workerUrl, workerPath);
await downloadFile(httpClient, syncWorkerUrl, syncWorkerPath);
}

final sqlitePackageName = 'sqlite3';

final sqlite3Pkg = getPackageFromConfig(packageConfig, sqlitePackageName);

String sqlite3Version =
"v${getPubspecVersion(packageConfigFile, sqlite3Pkg, sqlitePackageName)}";

List<String> tags = await getLatestTagsFromRelease(httpClient);
String? matchTag = tags.firstWhereOrNull((element) =>
element.contains(sqlite3Version) && coreVersionIsInRange(element));
if (matchTag != null) {
sqlite3Version = matchTag;
} else {
throw Exception(
"""No compatible powersync core version found for sqlite3 version $sqlite3Version
Latest supported sqlite3 versions: ${tags.take(3).map((tag) => tag.split('-')[0]).join(', ')}.
You can view the full list of releases at https://github.com/powersync-ja/sqlite3.dart/releases""");
}

final sqliteUrl =
'https://github.com/powersync-ja/sqlite3.dart/releases/download/$sqlite3Version/sqlite3.wasm';

await downloadFile(httpClient, sqliteUrl, wasmPath);
} catch (e) {
print(e);
exit(1);
}
}

bool coreVersionIsInRange(String tag) {
// Sets the range of powersync core version that is compatible with the sqlite3 version
// We're a little more selective in the versions chosen here than the range
// we're compatible with.
VersionConstraint constraint = VersionConstraint.parse('>=0.3.0 <0.4.0');
List<String> parts = tag.split('-');
String powersyncPart = parts[1];

List<String> versionParts = powersyncPart.split('.');
String extractedVersion =
versionParts.sublist(versionParts.length - 3).join('.');
final coreVersion = Version.parse(extractedVersion);
if (constraint.allows(coreVersion)) {
return true;
}
return false;
}

dynamic getPackageFromConfig(dynamic packageConfig, String packageName) {
final pkg = (packageConfig['packages'] ?? []).firstWhere(
(e) => e['name'] == packageName,
orElse: () => null,
);
if (pkg == null) {
throw Exception('Dependency on package:$packageName is required');
}
return pkg;
}

String getPubspecVersion(
File packageConfigFile, dynamic package, String packageName) {
final rootUri = packageConfigFile.uri.resolve(package['rootUri'] ?? '');
print('Using package:$packageName from ${rootUri.toFilePath()}');

String pubspec =
File('${rootUri.toFilePath()}/pubspec.yaml').readAsStringSync();
Pubspec parsed = Pubspec.parse(pubspec);
final version = parsed.version?.toString();
if (version == null) {
throw Exception(
"${capitalize(packageName)} version not found. Run `flutter pub get` first.");
}
return version;
}

String capitalize(String s) => s[0].toUpperCase() + s.substring(1);

Future<List<String>> getLatestTagsFromRelease(HttpClient httpClient) async {
var request = await httpClient.getUrl(Uri.parse(
"https://api.github.com/repos/powersync-ja/sqlite3.dart/releases"));
var response = await request.close();
if (response.statusCode == HttpStatus.ok) {
var res = await response.transform(utf8.decoder).join();
List<dynamic> jsonObj = json.decode(res);
List<String> tags = [];
for (dynamic obj in jsonObj) {
final tagName = obj['tag_name'] as String;
if (!tagName.contains("-powersync")) continue;
tags.add(tagName);
}
return tags;
} else {
throw Exception("Failed to fetch GitHub releases and tags");
}
}

Future<void> downloadFile(
HttpClient httpClient, String url, String savePath) async {
print('Downloading: $url');
var request = await httpClient.getUrl(Uri.parse(url));
var response = await request.close();
if (response.statusCode == HttpStatus.ok) {
var file = File(savePath);
await response.pipe(file.openWrite());
} else {
throw Exception(
'Failed to download file: ${response.statusCode} ${response.reasonPhrase}');
}
}
void main(List<String> args) => downloadWebAssets(args);
Loading

0 comments on commit 98ef589

Please sign in to comment.