dart_service_manager 1.4.0 copy "dart_service_manager: ^1.4.0" to clipboard
dart_service_manager: ^1.4.0 copied to clipboard

Declare services in a Dart package, compile them to native executables, and install and manage them as native operating-system services on Linux (systemd), macOS (launchd) and Windows (SCM). Ships a r [...]

1.4.0 #

  • Fix forCurrentExecutable reinstalls carrying a stale runtime script. The registry recorded the full argument vector, dart <script> <command…>, so a consumer that reinstalled from RegistryEntry.arguments fed the old script back in. The 1.3.1 guard only caught an exact match, so it missed two cases. A service installed under the Dart VM and reinstalled from an AOT build (for example a Dart 3.12 dart install app bundle) ran <binary> <old snapshot> <command…>. After an SDK upgrade renamed the pub-cache snapshot, it ran dart <new snapshot> <old snapshot> <command…>.
  • New ServiceDescriptor.scriptPath and RegistryEntry.scriptPath record the Dart script separately, and forCurrentExecutable sets it. ServiceDescriptor.commandArguments gives the command without the script.
  • Behaviour change: RegistryEntry.arguments is now the command alone. The new RegistryEntry.commandLine is the full vector passed to the binary. Reinstalling from entry.arguments now does the right thing with no change in the consumer. Registries written by earlier releases are migrated on read: a Dart VM entry's first argument becomes scriptPath.
  • resolveSelfExecutable also drops leading runtime scripts already in the arguments before adding the current one. It drops the current script, and any absolute .snapshot, .dill or .dart path. This repairs services already installed with a stale or doubled script. The function now also returns the script it applied, and recognises dart.exe paths on any host.
  • The Task Scheduler driver keeps scriptPath pointing at the staged runtime copy.
  • README: the reconfigure example rebuilt a descriptor with copyWith(arguments: …), which drops the script under the Dart VM. It now uses forCurrentExecutable, and a reinstall example was added.
  • Fix launchd reporting a stopped service as failed. launchctl stop ends the service with SIGTERM, so launchd reports LastExitStatus = 15, and every nonzero value was read as a failure. The value is a raw waitpid status, so a SIGTERM stop now reads as stopped. Real failures (a nonzero exit code, which is shifted left by 8 bits, or a crash signal) still read as failed.
  • New tests run against the host's real init system, test/integration/host_service_test.dart. They install, stop, start, reinstall and uninstall user-scoped services under systemd --user and launchd, including reinstalls across a Dart VM script change and a switch to a native binary. The os-* tags are still skipped by default; the new host preset runs them (dart test -P host), and the new CI host job runs them on Ubuntu and macOS. Before this, -t os-macos alone never lifted the skip, so these tests never ran.
  • More unit and integration coverage: lifecycle operations for 1.3.x registry entries, upgrading a 1.3.x registry file on disk, reinstalling a service the OS no longer knows, forCurrentExecutable itself, isRuntimeScript, and a real-process test for SystemProcessRunner.
  • Adopt super parameters in the exception classes; the current SDK's use_super_parameters lint was failing dart analyze --fatal-infos in CI.

1.3.1 #

  • Fix a forCurrentExecutable reinstall crash-loop under the Dart VM (JIT / pub-cache snapshot). resolveSelfExecutable prepended Platform.script to the arguments unconditionally, so re-deriving a descriptor from already-resolved arguments (as a reinstall does, replaying the registry's stored arguments) doubled the script: dart <snapshot> <snapshot> <command> …. The service then saw the extra snapshot path as an argument before its command and exited, triggering an endless Restart=always loop. The prepend is now idempotent — if the arguments already start with the script it is not added again. Affects every platform (systemd, launchd, Windows SCM and Task Scheduler), since the fix is in the shared descriptor model.

1.3.0 #

  • Add a Windows Task Scheduler backend (WindowsTaskSchedulerDriver, selected via WindowsServiceBackend.taskScheduler). Unlike the SCM driver, it runs plain console executables as background daemons without the in-process service-control dispatcher the SCM requires (which kills such programs with error 1053), and stages a private copy of the runtime so a Windows-locked pub-cache snapshot can still be refreshed. ServiceDriverFactory and DartServiceManager.forCurrentPlatform take a windowsBackend parameter (default serviceControlManager, unchanged).
  • Add DartServiceManager.describe() returning a ServiceInfo (recorded parameters + live status + the rendered native definition), and DartServiceManager.reinstall() (clean teardown-then-recreate that tolerates a missing prior install).

1.2.2 #

  • Fix a destructive bug where uninstall could delete an externally-provided executable — including the Dart VM itself (/usr/lib/dart/bin/dart) for a forCurrentExecutable / dart pub global activate install. Uninstall now only deletes binaries the manager compiled into its own managed directory; installDescriptor targets, manifest executable: paths and the Dart VM are left untouched.

1.2.1 #

  • Fix persistent user systemd on Linux when the process inherited an XDG_RUNTIME_DIR belonging to a different user (common under sudo/su or deploy scripts): the runtime directory is now derived from the detected uid (/run/user/<uid>) and an inherited value is honoured only when it matches, so systemctl --user no longer hits another user's bus and fails with Failed to connect to bus: Permission denied. That error is now recognised with an actionable hint, and a warning is emitted when a mismatched XDG_RUNTIME_DIR is overridden.

1.2.0 #

  • Persistent user-level systemd (Linux): user-scoped installs now auto-configure the per-user systemd environment so services install, enable, start, and survive logout/reboot. A new UserSystemdManager (ensurePersistentUserSystemd()) detects systemctl/loginctl, the current user/uid, lingering, the user D-Bus bus, and XDG_RUNTIME_DIR; enables lingering via sudo -n loginctl enable-linger when possible (warning with the manual command otherwise); and returns a detailed UserSystemdStatus (diagnostics + actionable warnings). The systemd driver runs it before user-scoped installs and passes a resolved XDG_RUNTIME_DIR to all systemctl --user calls, fixing Failed to connect to bus: … errors. Linux only, idempotent, never assumes root.

  • Scope/privilege warning: install now detects a mismatch between the requested scope and the current privilege level — running under sudo/root with the default user scope (user services fail as root), or a system-scoped install without elevation — and warns with the fix, then proceeds. Backed by a new injectable PrivilegeChecker (id -u / net session).

  • The CLI now shows warnings by default (info/debug still require --verbose).

  • Added --system as a shorthand for --scope system.

1.1.0 #

First-class third-party / imperative integration.

  • Imperative install: DartServiceManager.installDescriptor(descriptor, {startNow, force}) installs an already-built executable as a service — bypassing package resolution, manifest loading and compilation — with caller-supplied arguments, environment and runtime policy.
  • ServiceDescriptor.forCurrentExecutable(...): install the currently running program (Platform.resolvedExecutable) as a service, handling the JIT (dart <script>) vs AOT-binary distinction.
  • Runtime policy on ServiceDescriptor/ServiceInstallConfig and the dart_services: manifest: workingDirectory, restart (always/on-failure/never, new RestartPolicy enum), restartDelay, autoStart, stopTimeout, environmentFile. All default to the previous behaviour, so existing units/plists render unchanged.
  • Manifest executable: as an alternative to script: — install a pre-built binary without compiling.
  • Environment-file support (systemd EnvironmentFile=); drivers expose supportsEnvironmentFile and reject it where unsupported (launchd, Windows).
  • render() / --dry-run: drivers can render the native definition (systemd unit, launchd plist, sc command) without touching the system; DartServiceManager.renderDefinition(...) and install --executable --dry-run expose it.
  • reconfigure(descriptor): re-apply a changed descriptor, preserving the running state.
  • The registry now persists the full descriptor (args/env/description/policy), so lifecycle, listing and reconfigure work without a manifest. Registries written by 1.0.x still load.
  • CLI: install --executable <path>, --start-now, --dry-run, --restart, --restart-delay, --working-dir, --env-file, --no-auto-start, --force.
  • Windows services now configure SCM failure/restart actions to match the restart policy.

Potentially breaking: two new sealed exception subclasses — PermissionDeniedException and ServiceAlreadyInstalledException — are added to ServiceManagerException. Code that does an exhaustive switch over the exception hierarchy must handle the new cases.

1.0.1 #

  • Add a Shelf HTTP server example (example/shelf_server) showing a real web server declared as a service and managed end-to-end, with graceful SIGTERM/SIGINT shutdown.
  • Document package-wide operations in the README: a bare package reference (no :service) targets every service of the package — including uninstall — and uninstalling deletes each service's cached native binary.

1.0.0 #

Initial release.

  • Declare services in a package's pubspec.yaml via a dart_services: section.
  • Compile service entrypoints to native executables with dart compile exe, cached and rebuilt on change.
  • Install, uninstall, start, stop, pause, resume, restart and query services through the DartServiceManager Dart API and the dart-service CLI.
  • Platform drivers for Linux (systemd), macOS (launchd) and Windows (SCM) behind a single PlatformServiceDriver abstraction.
  • User- and system-scoped installation (ServiceScope), defaulting to user.
  • A persistent JSON service registry behind a ServiceRegistry repository abstraction, with atomic writes and per-platform storage locations.
  • Structured, injectable logging (ServiceLogger, LogLevel).
  • Sealed exception hierarchy with stable, machine-readable error codes.
1
likes
150
points
1.03k
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Declare services in a Dart package, compile them to native executables, and install and manage them as native operating-system services on Linux (systemd), macOS (launchd) and Windows (SCM). Ships a reusable library and a thin `dart-service` CLI behind a first-class Dart API.

Repository (GitHub)
View/report issues

License

Apache-2.0 (license)

Dependencies

args, meta, path, yaml

More

Packages that depend on dart_service_manager