run method
Runs this command.
The return value is wrapped in a Future if necessary and returned by
CommandRunner.runCommand.
Implementation
@override
Future<int> run() async {
final dataDir =
globals.option('data') ?? environment['OMNYSTORE_DATA'] ?? '.omnystore';
final verbose = globals.flag('verbose');
final quiet = globals.flag('quiet');
final logger = CliContext.loggerFor(verbose: verbose || !quiet);
final port = int.tryParse(argResults!.option('port') ?? '8080');
if (port == null || port < 0 || port > 65535) {
throw CliException(
'Invalid --port "${argResults!.option('port')}".',
exitCode: 64,
);
}
final providerId = argResults!.option('provider-id') ?? 'hub-local';
final local = await CliContext.openLocalStore(
dataDir,
logger: logger,
providerId: providerId,
);
// Always a hub, even with no nodes: it costs one indirection and means
// attaching a node later needs no restart into a different mode.
final hub = OmnyStoreHub(logger: logger)
..addProvider(
LocalStoreProvider(
local,
descriptor: ProviderDescriptor(
id: providerId,
kind: ProviderKind.hub,
// A catch-all, so the server works with no configuration and a
// node added later takes over its own organizations without the
// hub being reconfigured.
servesAll: true,
dataPlane: DataPlaneMode.relay,
agentVersion: omnyStoreVersion,
priority: -100,
),
),
);
final publishToken =
argResults!.option('publish-token') ??
environment['OMNYSTORE_PUBLISH_TOKEN'];
final nodeToken =
argResults!.option('node-token') ?? environment['OMNYSTORE_NODE_TOKEN'];
final corsOption = argResults!.option('cors');
final server = OmnyStoreServer(
store: hub,
logger: logger,
allowAnyOrigin: corsOption == '*',
allowedOrigins: corsOption == null || corsOption == '*'
? const []
: corsOption
.split(',')
.map((o) => o.trim())
.where((o) => o.isNotEmpty),
requireAuthForWrites: publishToken != null,
writeAuthenticator: publishToken == null
? null
: BearerTokenAuthenticator({
publishToken: Principal(
id: 'publisher',
roles: const {'publisher'},
),
}),
enableNodes: argResults!.flag('nodes'),
nodeMount: argResults!.option('node-mount') ?? '/_node',
nodeAuthenticator: nodeToken == null
? null
: BearerTokenAuthenticator({
nodeToken: Principal(id: 'node', roles: const {'node'}),
}),
);
final tls = _tlsFrom(argResults!);
await server.start(
port: port,
address: argResults!.option('address') ?? '0.0.0.0',
tls: tls,
);
final scheme = tls == null ? 'http' : 'https';
if (!quiet) {
out.writeln('OmnyStore $omnyStoreVersion');
out.writeln(' data: $dataDir');
out.writeln(' API: $scheme://localhost:${server.port}/api/v1');
out.writeln(' health: $scheme://localhost:${server.port}/health');
if (server.nodes != null) {
final wsScheme = tls == null ? 'ws' : 'wss';
out.writeln(
' nodes: $wsScheme://localhost:${server.port}'
'${argResults!.option('node-mount') ?? '/_node'}',
);
}
if (publishToken == null) {
out.writeln(
' writes: OPEN — anyone who can reach this server can publish. '
'Pass --publish-token to require authentication.',
);
}
out.writeln('Press Ctrl-C to stop.');
}
await _awaitInterrupt();
if (!quiet) out.writeln('\nShutting down…');
await server.stop();
await local.close();
return 0;
}