Skip to content

Commit

Permalink
Finalizing 1.0.0-rc.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Hexagon committed Apr 1, 2024
1 parent 29e5d63 commit 60fe2d6
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 12 deletions.
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@cross/fs": "jsr:@cross/fs@^0.0.8",
"@cross/runtime": "jsr:@cross/runtime@^1.0.0",
"@cross/test": "jsr:@cross/test@^0.0.9",
"@cross/utils": "jsr:@cross/utils@^0.9.1",
"@cross/utils": "jsr:@cross/utils@^0.9.2",
"@std/assert": "jsr:@std/assert@^0.221.0",
"@std/path": "jsr:@std/path@^0.221.0"
},
Expand Down
7 changes: 7 additions & 0 deletions lib/cli/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ function checkArguments(args: ArgsParser): ArgsParser {
throw new Error("Service name must be specified.");
}

// Check characters of name
const validServiceNameCharsRegex = /^[a-zA-Z0-9_-]+$/;
const serviceName = args.get("name")!; // Assuming you fetch the name here
if (!validServiceNameCharsRegex.test(serviceName)) {
throw new Error("Service name contains invalid characters. Only letters, numbers, underscores, and hyphens are allowed.");
}

return args;
}

Expand Down
20 changes: 15 additions & 5 deletions lib/cli/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { printFlags, printUsage } from "./output.ts";
import { checkArguments, parseArguments } from "./args.ts";
import { installService, uninstallService } from "../service.ts";
import { exit } from "@cross/utils";
import { Colors, exit } from "@cross/utils";

/**
* Define the main entry point of the CLI application
Expand Down Expand Up @@ -69,8 +69,13 @@ async function main(inputArgs: string[]) {
console.log(result.serviceFileContent);
} else {
if (result.manualSteps && result.manualSteps.length) {
console.log("To complete the installation, carry out these manual steps:");
console.log(result.manualSteps);
console.log(Colors.bold("To complete the installation, carry out these manual steps:"));
result.manualSteps.forEach((step, index) => {
console.log(Colors.cyan(`${index + 1}. ${step.text}`));
if (step.command) {
console.log(" " + Colors.yellow("Command: ") + step.command);
}
});
} else {
console.log(`Service ´${name}' successfully installed at '${result.servicePath}'.`);
}
Expand All @@ -87,8 +92,13 @@ async function main(inputArgs: string[]) {
try {
const result = await uninstallService({ system, name, home });
if (result.manualSteps && result.manualSteps.length) {
console.log(`Carry out these manual steps to complete the unistallation of '${name}'`);
console.log(result.manualSteps);
console.log(Colors.bold("To complete the uninstallation, carry out these manual steps:"));
result.manualSteps.forEach((step, index) => {
console.log(Colors.cyan(`${index + 1}. ${step.text}`));
if (step.command) {
console.log(" " + Colors.yellow("Command: ") + step.command);
}
});
} else {
console.log(`Service '${name}' at '${result.servicePath}' is now uninstalled.`);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/managers/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ class InitService {
async generateConfig(config: InstallServiceOptions): Promise<string> {
const runtimePath = await resolvedExecPath();
const runtimeDir = dirname(runtimePath);
const command = config.cmd;
const servicePath = config.path?.length ? `${config.path?.join(":")}:${runtimeDir}` : runtimeDir;
const command = config.cmd;
let initScriptContent = initScriptTemplate.replace(/{{name}}/g, config.name);
initScriptContent = initScriptContent.replace("{{command}}", command);
initScriptContent = initScriptContent.replace("{{path}}", servicePath);
Expand Down
30 changes: 26 additions & 4 deletions lib/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { WindowsService } from "./managers/windows.ts";
import { CurrentOS, OperatingSystem } from "@cross/runtime";
import { getEnv } from "@cross/env";
import { cwd, spawn } from "@cross/utils";
import type { SpawnResult } from "@cross/utils";
import { stat } from "@cross/fs";
import type { ServiceInstallResult, ServiceUninstallResult } from "./result.ts";
/**
Expand Down Expand Up @@ -126,13 +127,23 @@ serviceManager.register("upstart", new UpstartService());
serviceManager.register("launchd", new LaunchdService());
serviceManager.register("windows", new WindowsService());

async function installService(options: InstallServiceOptions, onlyGenerate: boolean, forceInitSystem?: string): Promise<ServiceInstallResult> {
if (forceInitSystem && !onlyGenerate) {
/**
* Installs a command as a system service on the detected operating system.
* Throws an error on unsupported init systems.
*
* @async
* @param options - Configuration options for the service installation. See {@link InstallServiceOptions}
* @param dryRun - If true, only generates the service configuration and paths without installing it.
* @param forceInitSystem - Optionally override auto-detection of the init system (for testing purposes).
* @returns - A promise resolving to a {@link ServiceInstallResult} object, indicating the success/failure of the installation.
*/
async function installService(options: InstallServiceOptions, dryRun: boolean, forceInitSystem?: string): Promise<ServiceInstallResult> {
if (forceInitSystem) {
throw new Error("Manually selecting an init system is not possible while installing.");
}
const config = prepareConfig(options);
const initSystem = forceInitSystem || await detectInitSystem();
return await serviceManager.installService(initSystem, config, onlyGenerate);
return await serviceManager.installService(initSystem, config, dryRun);
}

/**
Expand Down Expand Up @@ -163,15 +174,26 @@ async function generateConfig(options: InstallServiceOptions, forceInitSystem?:
}

async function detectInitSystem(): Promise<string> {
// Assume launcd on macOS
if (CurrentOS === OperatingSystem.macOS) {
return "launchd";
}

// Assume windows service manager on windows
if (CurrentOS === OperatingSystem.Windows) {
return "windows";
}

const process = await spawn(["ps", "-p", "1", "-o", "comm="]);
let process: SpawnResult | undefined;
try {
process = await spawn(["ps", "-p", "1", "-o", "comm="]);
} catch (e) {
throw new Error(`Unexpected error while determining init system: ${e.message}`);
}

if (process.code !== 0) {
throw new Error(`Unexpected error while determining init system: ${process.stderr || process.stdout}`);
}

if (process.stdout.includes("systemd")) {
return "systemd";
Expand Down
2 changes: 1 addition & 1 deletion mod.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { installService, uninstallService } from "./lib/service.ts";
export { generateConfig, installService, uninstallService } from "./lib/service.ts";
export type { InstallServiceOptions, UninstallServiceOptions } from "./lib/service.ts";

0 comments on commit 60fe2d6

Please sign in to comment.