routed_cli 0.1.0
routed_cli: ^0.1.0 copied to clipboard
Command-line tooling for the Routed framework with project scaffolding and management commands.
routed_cli #
A fast, minimalistic backend framework CLI for Dart.
This CLI is intended to complement the routed package with developer tooling similar to other modern server
frameworks. It focuses on a smooth local development experience with hot reload capability planned via hotreloader.
- Minimum Dart SDK: 3.9.2
- Planned hot reload engine: hotreloader ^4.3.0 (requires Dart >= 3.0.0)
Install #
You can run the CLI directly without installing it globally:
- From a project that depends on
routed_cli:dart run routed_cli --help- or
dart run routed --help(via theexecutablesmapping)
To install globally (useful for running from anywhere):
- From a published package (future):
dart pub global activate routed_cli
- From source (local path):
dart pub global activate --source path /path/to/packages/routed_cli
Once activated globally, invoke the routed executable:
routed --help
Usage #
A fast, minimalistic backend framework for Dart.
Usage: routed <command> [arguments]
Global options:
-h, --help Print this usage information.
--version Print the current version.
Available commands:
build Create a production build. (stub)
create Scaffold a new Routed app with healthy defaults.
dev Run a local development server. (hot reload ready - see below)
list Lists all the routes on a Routed project. (stub)
new Create a new route or middleware for Routed. (stub)
update Update the Routed CLI. (stub)
Quickstart #
- Scaffold a new project (optional but recommended):
dart run routed_cli create --name hello_world
cd hello_world
dart pub get
Prefer a different starter? Choose a template:
# API focused skeleton
dart run routed_cli create --name demo_api --template api
# HTML-first server-rendered starter
dart run routed_cli create --name demo_web --template web
# Combined API + HTML hybrid
dart run routed_cli create --name demo_fullstack --template fullstack
The api template adds sample REST routes and a test harness. The web
template renders Liquid files from the templates/ directory and ships static
assets under public/. The fullstack starter combines both.
Project Commands #
Each scaffold ships with lib/commands.dart, exposing an empty
buildProjectCommands hook. Populate it with project-specific automation and
the CLI will make those commands available automatically:
import 'dart:async';
import 'package:args/command_runner.dart';
class QueueWorkCommand extends Command<void> {
QueueWorkCommand() {
argParser.addOption('queue', defaultsTo: 'default');
}
@override
String get name => 'queue:work';
@override
String get description => 'Run the queue worker.';
@override
Future<void> run() async {
final queue = argResults?.option('queue') ?? 'default';
// TODO: enqueue work, start isolates, etc.
print('Working queue $queue');
}
}
FutureOr<List<Command<void>>> buildProjectCommands() => [QueueWorkCommand()];
Running dart run routed_cli queue:work --queue emails now boots the project
command. If a project command reuses a built-in name, the CLI exits with a
conflict so you can pick a new identifier.
Tip: add
argsto yourpubspec.yamlso project commands can extendCommand<void>directly.
The scaffold provides bin/server.dart, config files, and a starter README. Any existing project with a
bin/server.dart entrypoint works too.
- Start the dev server:
From a local dependency:
dart run routed dev --entry bin/server.dart -p 8080 -H 127.0.0.1
From a global install:
routed dev --entry bin/server.dart -p 8080 -H 127.0.0.1
Options:
--entry, -ePath to the entrypoint that starts your app (default:bin/server.dart).--port, -pPort to bind (default:8080).--host, -HHost to bind (default:127.0.0.1).--watchRepeatable; additional paths to watch (reserved for upcoming hot reload orchestration).--verbose, -vMore output.--bootstrap=falseSkip generating the hot reload bootstrap (useful for quick smoke tests).
Notes:
- The CLI currently passes
--hostand--portto your entrypoint. If your server doesn’t parse these flags, they will be ignored. See “Accepting host/port from the CLI” below.
Hot Reload #
Hot reload is a top priority feature for the dev command. The plan is to enable it using the
excellent hotreloader package.
Phase 1 (in place now):
- The
devcommand launches the target Dart program with--enable-vm-service. This is required for hot reload support in the Dart VM. - You can already integrate
hotreloaderdirectly into your app entrypoint to get hot reload behavior today (see below).
Phase 2 (planned):
- The CLI will optionally orchestrate watching (via
--watch) and perform targeted reloads via the VM service or by signaling thehotreloaderinstance. - Additional ergonomics: debouncing, filtering, and clear logging around reload successes/failures.
Enable hotreloader in your app entrypoint #
- Add as a dev dependency:
dart pub add --dev hotreloader
- Initialize the reloader in your entrypoint (e.g.,
bin/server.dart), making sure your process runs with--enable-vm-service(the CLI already does this):
import 'package:hotreloader/hotreloader.dart';
import 'package:routed/routed.dart';
Future<void> main(List<String> args) async {
// Enable hot reload for this process.
final reloader = await HotReloader.create(
debounceInterval: const Duration(seconds: 1),
onAfterReload: (ctx) {
print('Hot reload: ${ctx.result}');
},
);
final engine = Engine();
// Example routes
engine.get('/hello', (ctx) => ctx.string('Hello, World!'));
await engine.serve(host: '127.0.0.1', port: 8080);
// Cleanup on shutdown
reloader.stop();
}
- Start your app with the CLI:
routed dev --entry bin/server.dart -p 8080 -H 127.0.0.1
You can now edit files under lib/ and see changes applied live.
Accepting host/port from the CLI (optional) #
The dev command passes --host and --port to your entrypoint. If you want to honor those values, parse them in your
server’s main:
import 'package:args/args.dart';
import 'package:routed/routed.dart';
Future<void> main(List<String> args) async {
final parser = ArgParser()
..addOption('host', defaultsTo: '127.0.0.1')
..addOption('port', defaultsTo: '8080');
final result = parser.parse(args);
final host = result['host'] as String;
final port = int.parse(result['port'] as String);
final engine = Engine();
engine.get('/hello', (ctx) => ctx.string('Hello, from $host:$port!'));
await engine.serve(host: host, port: port);
}
If your app does not parse these flags, the values are simply ignored.
Commands #
-
dev:- Starts your application in development mode with the Dart VM service enabled.
- Prepares the ground for integrated hot reload.
- Flags:
--entry, -e: Entrypoint file. Default:bin/server.dart--host, -H: Host to bind. Default:127.0.0.1--port, -p: Port to bind. Default:8080--watch: Additional paths to watch for changes (planned integration)--verbose, -v: Verbose logging
-
build(stub): Create a production build. -
create(stub): Scaffold a new Routed app. -
list(stub): List all routes in a Routed project. -
new(stub): Create a new route or middleware. -
update(stub): Update the CLI.
Roadmap #
-
Hot Reload Orchestration:
- Integrate
hotreloaderwith the CLI’s--watchto trigger reloads consistently. - Log reload summaries, failures, and timing.
- Integrate
-
Developer Experience:
- Colored, structured logs.
- Friendly errors with suggested fixes (e.g., missing entry file, invalid flags).
-
Generators:
-
createandnewto scaffold apps, routes, middleware, and configs (with basic, api, web, and fullstack starters). -
Introspection:
listto enumerate routes.- Diagnostics endpoints for development.
-
Build:
buildpipeline to produce deployable artifacts.
Troubleshooting #
-
“Entry file not found”:
- Ensure your
--entrypath exists relative to your current working directory. - Example:
routed dev --entry examples/basic_router/bin/server.dart
- Ensure your
-
Hot reload doesn’t seem to apply:
- Verify your app is running with
--enable-vm-service(thedevcommand ensures this). - Ensure
hotreloaderis initialized in your entrypoint. - Make sure you’re editing files under directories watched by
hotreloader(by defaultlib/).
- Verify your app is running with
-
Port already in use:
- Choose a different port via
-p(e.g.,-p 3000).
- Choose a different port via
Contributing #
- Contributions are welcome. Focus areas include:
- Hot reload orchestration and file watching.
- Route listing, app scaffolding, and DX improvements.
- Documentation and examples.
License #
Apache-2.0