Skip to main content

Built and signed on GitHub Actions

Run any command as a service in Windows, Linux or macOS

This package works with DenoIt is unknown whether this package works with Cloudflare Workers, Node.js, Bun, Browsers
It is unknown whether this package works with Cloudflare Workers
It is unknown whether this package works with Node.js
This package works with Deno
It is unknown whether this package works with Bun
It is unknown whether this package works with Browsers
JSR Score
94%
Published
5 months ago (1.0.7)

@cross/service

Service is a JavaScript/TypeScript module for managing system services. It offers a convenient way to install, uninstall, and generate service configurations for various service managers. It can be used as either a command line tool, or a typescript library for direct integration in other Node/Deno/Bun programs.

Part of the @cross suite - check out our growing collection of cross-runtime tools at github.com/cross-org.

Features

  • Easy-to-use CLI for managing services
  • Library usage for custom integrations
  • Install, uninstall, and generate service configurations
  • Compatible with systemd, sysvinit, docker-init, upstart (Linux), launchd (macOS) and SCM (Windows) service managers
  • Installs any script as service on any system.
  • Cross-Runtime and Cross-Platform.

Installation

To use Service as a CLI program, you can install or upgrade it using Deno:

deno install -frA --global --name cross-service jsr:@cross/service/install

For library usage in Node, Deno or Bun - install according to the instructions at jsr.io/@cross/service and simply import the installService() function from the:

import { installService } from "@cross/service";

CLI Usage

To use the service library from the command line, follow these steps:

Install a command as a service:

# Using deno

cross-service install --name my-service --cmd "deno run --allow-net /full/path/to/server.ts"

# ... or a generic executable (with arguments and extra paths)

cross-service install --name my-service --cmd "/full/path/to/executable --optional-arg /full/path/to/config.ext" --path "/add/this/to/path:/and/this"

Uninstall a service:

cross-service uninstall --name my-service

Generate a service configuration file without installing it:

cross-service generate --name my-service --cmd "deno run --allow-net /full/path/to/server.ts --arg /full/path/to/config.ext"

Note:

  • The deno install path (e.g. $HOME/.deno/bin) will automatically be added to path. Additional paths can be supplied by passing a colon separated list to--path.
  • If you have any problems, always use full paths when registering a service. Services do not have the PATH that your shell have.
  • Use generate before install, that way you can visually inspect the generated configuration before installing it.
  • Steps requiring elevated access (like installing a system wide service) will not be performed automatically, you will insted get step by step instruction to make the required steps using sudo or the tool of your choice.
  • You can force service to generate configuration for a manager that is not installed, using systemd as an example: generate --force systemd

Programmatic Usage

To use the service library programmatically, you can import and use the installService, generateConfig and uninstallService functions.

Install for your runtime according to the instructions at [https://jsr.io/@cross/service].

InstallServiceOptions

This is the interface for the options used by the installService function:

interface InstallServiceOptions {
  system: boolean;
  name: string;
  cmd: string;
  user?: string;
  home?: string;
  cwd?: string;
  path?: string[];
  env?: string[];
}

The interface for the uninstallService function is very similar:

interface UninstallServiceOptions {
  system: boolean;
  name: string;
  home?: string;
}

installService

The installService function installs a command as a service, using the current service manager:

import { installService } from "@cross/service";

await installService({
  system: false, // Use user mode if available (default) or force system mode
  name: "my-service",
  cmd: "deno run --allow-net server.ts",
  user: "username", // Optional, defaults to current user
  home: "/home/username", // Optional, defaults to current user's home
  cwd: "/path/to/working/directory", // Optional, defaults to current working directory
  path: ["/extra/path", "/extra/path/2"], // Optional
  env: ["KEY=VALUE", "KEY2=VALUE2"], // Optional
});

uninstallService

The uninstallService function uninstalls a command from a service, using the currently installed service manager:

import { uninstallService } from "@cross/service";

await uninstallService({
  system: false, // Use user mode if available (default) or force system mode
  name: "my-service",
  home: "/home/username", // Optional, defaults to current user's home, used in case of user services
});

generateConfig

The generateConfig function generates a service configuration string for the specified service:

import { generateConfig } from "@cross/service";

const config = await generateConfig({
  system: false, // Use user mode if available (default) or force system mode
  name: "my-service",
  cmd: "deno run --allow-net server.ts",
  user: "username", // Optional, defaults to current user
  home: "/home/username", // Optional, defaults to current user's home
  cwd: "/path/to/working/directory", // Optional, defaults to current working directory,
  path: ["/extra/path", "/extra/path/2"], // Optional
  env: ["KEY=VALUE", "KEY2=VALUE2"], // Optional
});

console.log(config);

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

Before submitting a pull request, please ensure your code follows the project's coding style and passes all tests.

Template for a new service manager implementation

/**
 * @file lib/managers/name_of_manager.ts
 *
 * This module provides a template for implementing new manager classes
 * for various init systems. The template contains the structure and descriptions
 * of the required methods for a manager class. Replace 'ManagerTemplate' with the
 * name of the new manager class and implement the necessary methods according
 * to the target init system.
 *
 * When done, add this new implementation to lib/service.ts
 */

import { InstallServiceOptions, UninstallServiceOptions } from "../service.ts";

class ManagerTemplate {
  /**
   * Generates the configuration file content based on the given options.
   * @param config - The configuration options for the service.
   * @returns The generated configuration file content.
   */
  generateConfig(config: InstallServiceOptions): string {
    // TODO: Implement this method for the target init system.
    throw new Error("Not implemented");
  }

  /**
   * Installs the service based on the given options.
   * @param config - The configuration options for the service.
   * @param onlyGenerate - A flag indicating whether to only generate the configuration or
   * also install the service. The difference between install with onlyGenerate and the
   * generateConfig function, is that install with onlyGenerate should console.log additional
   * steps needed to finish the installation, such as `sudo systemctl daemon-reload`.
   * generateConfig do only output the base configuration file.
   */
  async install(config: InstallServiceOptions, onlyGenerate: boolean): Promise<InstallServiceOptions> {
    /*
     * ToDo: Implement this method for the target init system.
     *
    return {
      servicePath,
      serviceFileContent,
      manualSteps: null,
    }; */
    throw new Error("Not implemented");
  }

  /**
   * Uninstalls the service based on the given options.
   * @param config - The configuration options for uninstalling the service.
   */
  async uninstall(config: UninstallServiceOptions): Promise<UninstallServiceOptions> {
    /*
     * TODO: Implement this method for the target init system.
     *
    return {
      pathToServiceFile,
      manualSteps: null,
    };
    */
    throw new Error("Not implemented");
  }
}

export { ManagerTemplate };
Built and signed on
GitHub Actions
View transparency log

New Ticket: Report package

Please provide a reason for reporting this package. We will review your report and take appropriate action.

Please review the JSR usage policy before submitting a report.

Add Package

deno add jsr:@cross/service

Import symbol

import * as service from "@cross/service";
or

Import directly with a jsr specifier

import * as service from "jsr:@cross/service";

Add Package

pnpm i jsr:@cross/service
or (using pnpm 10.8 or older)
pnpm dlx jsr add @cross/service

Import symbol

import * as service from "@cross/service";

Add Package

yarn add jsr:@cross/service
or (using Yarn 4.8 or older)
yarn dlx jsr add @cross/service

Import symbol

import * as service from "@cross/service";

Add Package

npx jsr add @cross/service

Import symbol

import * as service from "@cross/service";

Add Package

bunx jsr add @cross/service

Import symbol

import * as service from "@cross/service";