create static method
Future<LocordaGraph>
create({
- required WorkerSetup workerSetup,
- void onWorkerSpawn()?,
- required SyncEngineConfig config,
- required StorageMainHandler storage,
- String jsScript = 'worker.dart.js',
- List<
RemoteIntegration> remotes = const [], - List<
MainHandlerFactory> plugins = const [], - IriTermFactory? iriTermFactory,
- RdfCore? rdfCore,
- String? debugName,
Creates LocordaGraph with SyncEngine running in a separate worker thread.
This is the graph-based alternative to Locorda.create(), providing
direct RDF graph access without automatic object mapping.
Complete Example
1. Main thread:
import 'package:locorda_flutter_core/locorda_flutter_core.dart';
import 'package:locorda_rdf_core/core.dart';
// Initialize auth
final solidAuth = SolidAuth(...);
await solidAuth.init();
// Create LocordaGraph with worker architecture
final locordaGraph = await LocordaGraph.create(
workerSetup: setupWorkerEngine,
onWorkerSpawn: setupWorkerLogging,
// Main thread handlers
remotes: [SolidMainIntegration(solidAuth: solidAuth)],
storage: DriftMainHandler(),
// Low-level configuration with RDF IRIs
config: SyncEngineConfig(
resources: [
ResourceTypeConfig(
typeIri: IriTerm.validated('https://example.org/Note'),
crdtMapping: Uri.parse('https://example.org/mappings/note-v1.ttl'),
indices: [
IndexConfig(
name: 'notes_by_month',
type: IndexType.group,
rootResourceFetchPolicy: RootResourceFetchPolicy.prefetch,
),
],
),
],
),
);
// Work with RDF graphs directly
final noteGraph = RdfGraph.fromTriples([
Triple(
subject: IriTerm.validated('https://example.org/notes/123#it'),
predicate: IriTerm.validated('http://schema.org/name'),
object: LiteralTerm.string('My Note'),
)]);
// Save to sync system
final noteTypeIri = IriTerm.validated('https://example.org/Note');
locordaGraph.syncEngine.save(noteTypeIri, noteGraph);
// Stream graph updates
locordaGraph.syncEngine.hydrateStream(
typeIri: noteTypeIri,
).listen((batch) {
for (final (iri, graph) in batch.updates) {
// Process RdfGraph directly
print('Updated: $iri');
for (final triple in graph.triples) {
print(' $triple');
}
}
});
2. Worker thread (same as Locorda):
import 'package:locorda/worker.dart';
void main() {
workerMain(setupWorkerEngine, onWorkerSpawn: setupWorkerLogging);
}
Future<WorkerParams> setupWorkerEngine() async => WorkerParams(
remotes: [SolidWorkerHandler()],
storage: DriftWorkerHandler(...),
);
Architecture
Same worker architecture as Locorda, but without object mapping layer:
Main Thread: Worker Thread:
├─ LocordaGraph ├─ SyncEngine
│ ├─ RdfGraph operations │ ├─ CRDT merge
│ │ (manual) │ ├─ Database I/O
│ └─ ProxySyncEngine ─────────>│ ├─ HTTP requests
│ (forwards calls) │ └─ DPoP signing
└─ UI └─ (heavy work here)
Key Differences from Locorda.create()
- No
mapperInitializer: You work with raw RDF graphs - Uses
SyncEngineConfig: Direct IRI-based configuration instead ofLocordaConfig - Manual serialization: You control RDF graph creation and parsing
- Lower-level API: More control, less convenience
When to Use
- Building RDF tools or editors
- Dynamic schemas determined at runtime
- Working with non-standard RDF patterns
For most applications, prefer Locorda.create() for type-safe Dart objects.
Parameters
workerSetup: Function that configures worker-side handlersonWorkerSpawn: Optional callback for worker initializationremotes: Main thread handlers for remote backends (Solid, GDrive, etc.)storage: Main thread handler for storage backendconfig: Low-level sync engine configuration with RDF IRIsjsScript: Web worker JS filename (default: 'worker.dart.js')plugins: Additional worker plugins for custom functionalitydebugName: Optional name for debugging worker communication
Throws SyncConfigValidationException if the configuration is invalid.
Implementation
static Future<LocordaGraph> create({
required WorkerSetup workerSetup,
void onWorkerSpawn()?,
required SyncEngineConfig config,
required StorageMainHandler storage,
String jsScript = 'worker.dart.js',
List<RemoteIntegration> remotes = const [],
List<MainHandlerFactory> plugins = const [],
IriTermFactory? iriTermFactory,
RdfCore? rdfCore,
String? debugName,
}) async {
final syncEngine = await SyncEngineWithWorker.create(
jsScript: jsScript,
workerSetup: workerSetup,
remotes: remotes,
storage: storage,
plugins: plugins,
syncEngineConfig: config,
debugName: debugName,
onWorkerSpawn: onWorkerSpawn,
);
return LocordaGraph._(
syncEngine: syncEngine,
uiAdapterRegistry: UiAdapterRegistry.withRemotes(remotes),
);
}