Halkyon's shared packages
A pub workspace of the Dart packages Halkyon's apps share: halkyon_ui, Halkyon's look (the theme, fonts, layout and shared widgets, with texts in English and German), halkyon_core's low-level primitives and halkyon_interop's cross-app contracts. Dart 3.13 with LeanCode's lints, configured once at the root; apps take a package by git, pinned to a signed commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
commit
80fa7b9628
105 changed files with 6762 additions and 0 deletions
31
packages/halkyon_core/.gitignore
vendored
Normal file
31
packages/halkyon_core/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins-dependencies
|
||||
/build/
|
||||
/coverage/
|
||||
10
packages/halkyon_core/.metadata
Normal file
10
packages/halkyon_core/.metadata
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "cc0734ac716fbb8b90f3f9db8020958b1553afa7"
|
||||
channel: "stable"
|
||||
|
||||
project_type: package
|
||||
3
packages/halkyon_core/CHANGELOG.md
Normal file
3
packages/halkyon_core/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
## 0.0.1
|
||||
|
||||
* TODO: Describe initial release.
|
||||
1
packages/halkyon_core/LICENSE
Normal file
1
packages/halkyon_core/LICENSE
Normal file
|
|
@ -0,0 +1 @@
|
|||
TODO: Add your license here.
|
||||
39
packages/halkyon_core/README.md
Normal file
39
packages/halkyon_core/README.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<!--
|
||||
This README describes the package. If you publish this package to pub.dev,
|
||||
this README's contents appear on the landing page for your package.
|
||||
|
||||
For information about how to write a good package README, see the guide for
|
||||
[writing package pages](https://dart.dev/tools/pub/writing-package-pages).
|
||||
|
||||
For general information about developing packages, see the Dart guide for
|
||||
[creating packages](https://dart.dev/guides/libraries/create-packages)
|
||||
and the Flutter guide for
|
||||
[developing packages and plugins](https://flutter.dev/to/develop-packages).
|
||||
-->
|
||||
|
||||
TODO: Put a short description of the package here that helps potential users
|
||||
know whether this package might be useful for them.
|
||||
|
||||
## Features
|
||||
|
||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
||||
|
||||
## Getting started
|
||||
|
||||
TODO: List prerequisites and provide or point to information on how to
|
||||
start using the package.
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Include short and useful examples for package users. Add longer examples
|
||||
to `/example` folder.
|
||||
|
||||
```dart
|
||||
const like = 'sample';
|
||||
```
|
||||
|
||||
## Additional information
|
||||
|
||||
TODO: Tell users more about the package: where to find more information, how to
|
||||
contribute to the package, how to file issues, what response they can expect
|
||||
from the package authors, and more.
|
||||
2
packages/halkyon_core/analysis_options.yaml
Normal file
2
packages/halkyon_core/analysis_options.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# The workspace's lint rules (see ../../analysis_options.yaml).
|
||||
include: ../../analysis_options.yaml
|
||||
17
packages/halkyon_core/lib/halkyon_core.dart
Normal file
17
packages/halkyon_core/lib/halkyon_core.dart
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/// Low-level primitives shared across Halkyon apps.
|
||||
///
|
||||
/// This package is pure Dart and has no Flutter dependency. It provides:
|
||||
/// - A re-export of `package:clock`'s `Clock` for testable time access.
|
||||
/// - A thin `generateUuid` wrapper for v4 UUID generation.
|
||||
/// - A `Logger` interface and basic `ConsoleLogger` implementation.
|
||||
/// - The optional `HalkyonException` marker interface.
|
||||
library;
|
||||
|
||||
// Re-export the clock package directly. Halkyon apps depend on `Clock` for
|
||||
// testable time access; re-exporting here means they get it via halkyon_core
|
||||
// without needing a separate `clock` dependency.
|
||||
export 'package:clock/clock.dart' show Clock, clock;
|
||||
|
||||
export 'src/exceptions.dart';
|
||||
export 'src/logger.dart';
|
||||
export 'src/uuid.dart';
|
||||
11
packages/halkyon_core/lib/src/exceptions.dart
Normal file
11
packages/halkyon_core/lib/src/exceptions.dart
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/// Marker interface for exceptions originating in Halkyon code.
|
||||
///
|
||||
/// Implementing this is optional. It exists so callers can distinguish
|
||||
/// "this came from Halkyon" from "this came from a library we use" using
|
||||
/// `on HalkyonException catch (e)` if they want that granularity.
|
||||
///
|
||||
/// Most Halkyon exceptions should also extend a more specific type
|
||||
/// (e.g., `AuthException`, `SyncException`) defined in the relevant feature.
|
||||
abstract class HalkyonException() implements Exception {
|
||||
String get message;
|
||||
}
|
||||
54
packages/halkyon_core/lib/src/logger.dart
Normal file
54
packages/halkyon_core/lib/src/logger.dart
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/// Severity levels for log messages.
|
||||
enum LogLevel() {
|
||||
debug,
|
||||
info,
|
||||
warning,
|
||||
error,
|
||||
}
|
||||
|
||||
/// A minimal logging interface.
|
||||
///
|
||||
/// Implementations are injected via the app's `Dependencies` composition root
|
||||
/// rather than imported globally, so tests can swap in fakes.
|
||||
abstract interface class Logger() {
|
||||
void log(
|
||||
LogLevel level,
|
||||
String message, {
|
||||
Object? error,
|
||||
StackTrace? stackTrace,
|
||||
});
|
||||
}
|
||||
|
||||
/// A logger that writes to stdout. Suitable for development and tests.
|
||||
///
|
||||
/// Production apps should use a logger that forwards to Sentry or similar,
|
||||
/// configured at the composition root.
|
||||
class const ConsoleLogger() implements Logger {
|
||||
@override
|
||||
void log(
|
||||
LogLevel level,
|
||||
String message, {
|
||||
Object? error,
|
||||
StackTrace? stackTrace,
|
||||
}) {
|
||||
final prefix = switch (level) {
|
||||
LogLevel.debug => '[DEBUG]',
|
||||
LogLevel.info => '[INFO]',
|
||||
LogLevel.warning => '[WARN]',
|
||||
LogLevel.error => '[ERROR]',
|
||||
};
|
||||
// Writing to stdout is this logger's whole purpose.
|
||||
// ignore: avoid_print
|
||||
print('$prefix $message');
|
||||
if (error != null) {
|
||||
// As above: stdout is where this logger writes.
|
||||
// ignore: avoid_print
|
||||
print(' error: $error');
|
||||
}
|
||||
if (stackTrace != null) {
|
||||
// As above: stdout is where this logger writes.
|
||||
// ignore: avoid_print
|
||||
print(' stack: $stackTrace');
|
||||
}
|
||||
}
|
||||
}
|
||||
10
packages/halkyon_core/lib/src/uuid.dart
Normal file
10
packages/halkyon_core/lib/src/uuid.dart
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import 'package:uuid/uuid.dart';
|
||||
|
||||
const _uuid = Uuid();
|
||||
|
||||
/// Generates a v4 (random) UUID as a lowercase hyphenated string.
|
||||
///
|
||||
/// Thin wrapper over `package:uuid` so Halkyon code doesn't need to import
|
||||
/// it directly. If we ever need to swap the UUID library, this is the only
|
||||
/// site that changes.
|
||||
String generateUuid() => _uuid.v4();
|
||||
15
packages/halkyon_core/pubspec.yaml
Normal file
15
packages/halkyon_core/pubspec.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
name: halkyon_core
|
||||
description: "Low-level primitives shared across Halkyon apps. Pure Dart, no Flutter."
|
||||
version: 0.0.1
|
||||
publish_to: none
|
||||
resolution: workspace
|
||||
|
||||
environment:
|
||||
sdk: ^3.13.0
|
||||
|
||||
dependencies:
|
||||
clock: ^1.1.1
|
||||
uuid: ^4.5.0
|
||||
|
||||
dev_dependencies:
|
||||
test: ^1.25.0
|
||||
52
packages/halkyon_core/test/halkyon_core_test.dart
Normal file
52
packages/halkyon_core/test/halkyon_core_test.dart
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import 'package:halkyon_core/halkyon_core.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('generateUuid', () {
|
||||
test('produces a non-empty string', () {
|
||||
expect(generateUuid(), isNotEmpty);
|
||||
});
|
||||
|
||||
test('produces a valid v4 UUID format', () {
|
||||
// v4 UUID: 8-4-4-4-12 hex characters, with version 4 in the third group.
|
||||
final uuid = generateUuid();
|
||||
expect(
|
||||
uuid,
|
||||
matches(
|
||||
RegExp(
|
||||
r'^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$',
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('produces different values on successive calls', () {
|
||||
final a = generateUuid();
|
||||
final b = generateUuid();
|
||||
expect(a, isNot(equals(b)));
|
||||
});
|
||||
});
|
||||
|
||||
group('ConsoleLogger', () {
|
||||
test('can be instantiated as const', () {
|
||||
const logger = ConsoleLogger();
|
||||
expect(logger, isA<Logger>());
|
||||
});
|
||||
|
||||
// Note: we don't test that ConsoleLogger actually prints, because
|
||||
// capturing stdout in tests is fragile and the implementation is trivial.
|
||||
// If we add structured logging later, we'll test that more carefully.
|
||||
});
|
||||
|
||||
group('HalkyonException', () {
|
||||
test('is implementable', () {
|
||||
final ex = _TestException('boom');
|
||||
expect(ex, isA<HalkyonException>());
|
||||
expect(ex, isA<Exception>());
|
||||
expect(ex.message, equals('boom'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class _TestException(@override final String message)
|
||||
implements HalkyonException;
|
||||
31
packages/halkyon_interop/.gitignore
vendored
Normal file
31
packages/halkyon_interop/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins-dependencies
|
||||
/build/
|
||||
/coverage/
|
||||
10
packages/halkyon_interop/.metadata
Normal file
10
packages/halkyon_interop/.metadata
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "cc0734ac716fbb8b90f3f9db8020958b1553afa7"
|
||||
channel: "stable"
|
||||
|
||||
project_type: package
|
||||
3
packages/halkyon_interop/CHANGELOG.md
Normal file
3
packages/halkyon_interop/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
## 0.0.1
|
||||
|
||||
* TODO: Describe initial release.
|
||||
1
packages/halkyon_interop/LICENSE
Normal file
1
packages/halkyon_interop/LICENSE
Normal file
|
|
@ -0,0 +1 @@
|
|||
TODO: Add your license here.
|
||||
39
packages/halkyon_interop/README.md
Normal file
39
packages/halkyon_interop/README.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<!--
|
||||
This README describes the package. If you publish this package to pub.dev,
|
||||
this README's contents appear on the landing page for your package.
|
||||
|
||||
For information about how to write a good package README, see the guide for
|
||||
[writing package pages](https://dart.dev/tools/pub/writing-package-pages).
|
||||
|
||||
For general information about developing packages, see the Dart guide for
|
||||
[creating packages](https://dart.dev/guides/libraries/create-packages)
|
||||
and the Flutter guide for
|
||||
[developing packages and plugins](https://flutter.dev/to/develop-packages).
|
||||
-->
|
||||
|
||||
TODO: Put a short description of the package here that helps potential users
|
||||
know whether this package might be useful for them.
|
||||
|
||||
## Features
|
||||
|
||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
||||
|
||||
## Getting started
|
||||
|
||||
TODO: List prerequisites and provide or point to information on how to
|
||||
start using the package.
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Include short and useful examples for package users. Add longer examples
|
||||
to `/example` folder.
|
||||
|
||||
```dart
|
||||
const like = 'sample';
|
||||
```
|
||||
|
||||
## Additional information
|
||||
|
||||
TODO: Tell users more about the package: where to find more information, how to
|
||||
contribute to the package, how to file issues, what response they can expect
|
||||
from the package authors, and more.
|
||||
2
packages/halkyon_interop/analysis_options.yaml
Normal file
2
packages/halkyon_interop/analysis_options.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# The workspace's lint rules (see ../../analysis_options.yaml).
|
||||
include: ../../analysis_options.yaml
|
||||
13
packages/halkyon_interop/lib/halkyon_interop.dart
Normal file
13
packages/halkyon_interop/lib/halkyon_interop.dart
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/// Cross-app interoperability contracts for the Halkyon ecosystem.
|
||||
///
|
||||
/// This package is pure Dart and defines:
|
||||
/// - `TaskShape`: a minimal type for representing tasks across apps
|
||||
/// (e.g., a Halkyon Learn review session surfaced in Halkyon ToDo).
|
||||
/// - `HalkyonEvent`: a sealed class hierarchy for cross-app events.
|
||||
/// - `EventPublisher`: an interface for emitting events to other apps,
|
||||
/// with `DormantPublisher` as a no-op default for apps running standalone.
|
||||
library;
|
||||
|
||||
export 'src/event_publisher.dart';
|
||||
export 'src/events.dart';
|
||||
export 'src/task_shape.dart';
|
||||
24
packages/halkyon_interop/lib/src/event_publisher.dart
Normal file
24
packages/halkyon_interop/lib/src/event_publisher.dart
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import 'package:halkyon_interop/src/events.dart';
|
||||
|
||||
/// Publishes [HalkyonEvent]s to other Halkyon apps installed alongside this one.
|
||||
///
|
||||
/// The actual transport (platform channels, intents, App Group containers,
|
||||
/// etc.) is implementation-specific and lives in the app's composition root,
|
||||
/// not in this package.
|
||||
abstract interface class EventPublisher() {
|
||||
/// Publish an event. Implementations should be non-blocking and best-effort:
|
||||
/// failing to deliver to peer apps must not fail the originating action.
|
||||
Future<void> publish(HalkyonEvent event);
|
||||
}
|
||||
|
||||
/// A no-op [EventPublisher] for apps running in isolation.
|
||||
///
|
||||
/// When a Halkyon app starts and detects no peer apps to broadcast to (or
|
||||
/// when the user has disabled cross-app communication), inject this. All
|
||||
/// `publish` calls are silently dropped.
|
||||
class const DormantPublisher() implements EventPublisher {
|
||||
@override
|
||||
Future<void> publish(HalkyonEvent event) async {
|
||||
// Intentionally empty. Events are dropped when there are no peers.
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue