Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internal support for Node and Bun #56

Merged
merged 21 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deno.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
deno-version: [1.42.0, "v1.x"]
deno-version: [1.43.3, "v1.x"]

steps:
- name: Git Checkout
Expand Down
10 changes: 7 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,15 @@ coverage
# Lumocs generated site
_site

# Node files
.npmrc
# Node/npm files
package-lock.json
package.json
node_modules
.npmrc
package.json
*.tgz

# Bun files
.bun.lockb

# VSCode files
.vscode
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![PUP](https://cdn.jsdelivr.net/gh/hexagon/pup@master/docs/src/resources/pup_dark.png)

Pup is a powerful universal process manager developed with Deno, designed to keep your scripts, applications and services alive.
Pup is a powerful universal process manager developed with JavaScript, designed to keep your scripts, applications and services alive.

_For detailed documentation, visit [pup.56k.guru](https://pup.56k.guru)._

Expand All @@ -25,10 +25,12 @@ _For detailed documentation, visit [pup.56k.guru](https://pup.56k.guru)._

### Installation

To install Pup, make sure you run the latest version of Deno (`deno upgrade`), then open your terminal and execute the following command:
To install Pup, make sure you run the latest version of your runtime environment, then open your terminal and execute the following command:

**Deno**:

```bash
deno run -Ar jsr:@pup/pup@1.0.0-rc.39 setup --channel prerelease
deno run -Ar jsr:@pup/pup@1.0.0-rc.40 setup --channel prerelease
```

This command downloads the latest version of Pup and installs it on your system. The `--channel prerelease` option is included as there is no stable version of Pup yet. Read more abour release
Expand Down
5 changes: 3 additions & 2 deletions application.meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@

const Application = {
name: "pup",
version: "1.0.0-rc.39",
version: "1.0.0-rc.40",
url: "jsr:@pup/pup@$VERSION",
description: "Powerful universal process manager, designed to keep your scripts, applications and services alive.",
canary_url: "https://raw.githubusercontent.com/Hexagon/pup/main/pup.ts",
deno: null, /* Minimum stable version of Deno required to run Pup (without --unstable-* flags) */
deno: "1.43.0", /* Minimum stable version of Deno required to run Pup (without --unstable-* flags) */
deno_unstable: "1.43.0", /* Minimum version of Deno required to run Pup (with --unstable-* flags) */
repository: "https://github.com/hexagon/pup",
changelog: "https://hexagon.github.io/pup/changelog.html",
Expand Down
65 changes: 32 additions & 33 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
{
"name": "@pup/pup",
"version": "1.0.0-rc.39",
"version": "1.0.0-rc.40",

"exports": {
".": "./pup.ts",
"./lib": "./mod.ts"
},

"unstable": [
"kv"
],

"fmt": {
"lineWidth": 200,
"semiColons": false,
Expand All @@ -29,40 +25,43 @@
},

"tasks": {
"update-deps": "deno run --allow-read=. --allow-net=jsr.io,registry.npmjs.org jsr:@check/deps",
"check": "deno fmt --check && deno lint && deno check --unstable-kv pup.ts && deno test --allow-read --allow-write --allow-env --allow-net --allow-sys --allow-run --unstable-kv --coverage=cov_profile && echo \"Generating coverage\" && deno coverage cov_profile --exclude=pup/test --lcov --output=cov_profile.lcov",
"check-deps": "deno run -r --allow-read=. --allow-net=jsr.io,registry.npmjs.org jsr:@check/deps",
"check": "deno fmt --check && deno lint && deno check pup.ts && deno test --trace-leaks --allow-read --allow-write --allow-env --allow-net --allow-sys --allow-run --coverage=cov_profile && echo \"Generating coverage\" && deno coverage cov_profile --exclude=pup/test --lcov --output=cov_profile.lcov",
"check-coverage": "deno task check && genhtml cov_profile.lcov --output-directory cov_profile/html && lcov --list cov_profile.lcov && deno run --allow-net --allow-read https://deno.land/std/http/file_server.ts cov_profile/html",
"build-schema": "deno run --allow-write --allow-read --allow-env=XDG_DATA_HOME,HOME tools/build-schema.ts && deno fmt",
"build-versions": "deno run --allow-read --allow-write --allow-env tools/release.ts && deno fmt",
"build": "deno task check && deno task build-schema && deno task build-versions"
"generate-package-json": "deno run -A tools/generate-package-json.ts",
"build": "deno task check && deno task build-schema && deno task build-versions && deno task build-package-json && npm pack",
"publish-npm": "deno task build && npm publish"
},

"imports": {
"@cross/deepmerge": "jsr:@cross/deepmerge@^1.0.0",
"@cross/env": "jsr:@cross/env@^1.0.2",
"@cross/fs": "jsr:@cross/fs@^0.1.11",
"@cross/jwt": "jsr:@cross/jwt@^0.4.7",
"@cross/runtime": "jsr:@cross/runtime@^1.0.0",
"@cross/service": "jsr:@cross/service@^1.0.3",
"@cross/test": "jsr:@cross/test@^0.0.9",
"@cross/utils": "jsr:@cross/utils@^0.12.0",
"@cross/deepmerge": "jsr:@cross/deepmerge@~1.0.0",
"@cross/env": "jsr:@cross/env@~1.0.2",
"@cross/fs": "jsr:@cross/fs@~0.1.11",
"@cross/jwt": "jsr:@cross/jwt@~0.4.7",
"@cross/kv": "jsr:@cross/kv@^0.16.3",
"@cross/runtime": "jsr:@cross/runtime@~1.0.0",
"@cross/service": "jsr:@cross/service@~1.0.3",
"@cross/test": "jsr:@cross/test@~0.0.9",
"@cross/utils": "jsr:@cross/utils@~0.13.0",
"@hexagon/croner": "jsr:@hexagon/croner@^8.0.2",
"@oak/oak": "jsr:@oak/oak@^15.0.0",
"@pup/api-client": "jsr:@pup/api-client@^1.0.6",
"@pup/api-definitions": "jsr:@pup/api-definitions@^1.0.2",
"@pup/common": "jsr:@pup/common@^1.0.3",
"@pup/plugin": "jsr:@pup/plugin@^1.0.1",
"@std/assert": "jsr:@std/assert@^0.224.0",
"@std/async": "jsr:@std/async@^0.224.0",
"@std/encoding": "jsr:@std/encoding@^0.224.0",
"@std/io": "jsr:@std/io@^0.224.0",
"@std/path": "jsr:@std/path@^0.224.0",
"@std/semver": "jsr:@std/semver@^0.224.0",
"dax-sh": "npm:dax-sh@^0.41.0",
"filesize": "npm:filesize@^10.1.1",
"json5": "npm:json5@^2.2.3",
"timeago.js": "npm:timeago.js@^4.0.2",
"zod": "npm:zod@^3.23.6",
"zod-to-json-schema": "npm:zod-to-json-schema@^3.23.0"
"@oak/oak": "jsr:@oak/oak@^16.1.0",
"@pup/api-client": "jsr:@pup/api-client@~2.0.0",
"@pup/api-definitions": "jsr:@pup/api-definitions@~2.0.0",
"@pup/common": "jsr:@pup/common@~1.0.3",
"@pup/plugin": "jsr:@pup/plugin@~1.0.1",
"@std/assert": "jsr:@std/assert@^0.226.0",
"@std/async": "jsr:@std/async@~0.224.0",
"@std/encoding": "jsr:@std/encoding@^1.0.0",
"@std/io": "jsr:@std/io@~0.224.0",
"@std/path": "jsr:@std/path@^0.225.1",
"@std/semver": "jsr:@std/semver@~0.224.0",
"dax-sh": "npm:dax-sh@~0.41.0",
"filesize": "npm:filesize@~10.1.1",
"json5": "npm:json5@~2.2.3",
"timeago.js": "npm:timeago.js@~4.0.2",
"zod": "npm:zod@~3.23.6",
"zod-to-json-schema": "npm:zod-to-json-schema@~3.23.0"
}
}
2 changes: 1 addition & 1 deletion docs/src/_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"description": "Universal Process Manager"
},
"substitute": {
"$PUP_VERSION": "1.0.0-rc.39"
"$PUP_VERSION": "1.0.0-rc.40"
},
"top_links": [
{
Expand Down
6 changes: 6 additions & 0 deletions docs/src/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ nav_order: 13

All notable changes to this project will be documented in this section.

## [1.0.0-rc.40] - Unreleased

- fix(core): Replace `Deno.Kv` with `@cross/kv` for cross-runtime compatibility, more compact logs and avoiding `--unstable`
- fix(core): Internal changes to support Node and Bun
- fix(core): Removes the `sysinfo.ts`-module in favor of `@cross/utils/sysinfo`

## [1.0.0-rc.39] - 2024-05-04

- fix(core): Clustered processes were duplicated in API and `pup status`
Expand Down
3 changes: 1 addition & 2 deletions docs/src/contributing/packaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ If you have experience with software packaging, your contribution can greatly en

- Pup can be compiled into an executable prior to packaging using `deno compile`. The procedure is described at
[https://deno.com/manual@v1.34.3/tools/compiler](https://deno.com/manual@v1.34.3/tools/compiler). The command should be similar to
`deno compile --allow-all --reload --unstable-kv --output pup pup.ts --external-installer`. The `--unstable-kv` flag should be included if the version you are packaging (mostly pre-releases)
requires unstable features according to `versions.json`.
`deno compile --allow-all --reload --output pup pup.ts --external-installer`.

- The `--external-installer` argument to the Pup script disables the built-in installer, hiding `setup` and `upgrade` options from `--help`.

Expand Down
40 changes: 20 additions & 20 deletions lib/cli/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,21 +429,19 @@ async function main() {
* Base argument: logs
*/
if (baseArgument === "logs") {
const logStore = `${await toPersistentPath(configFile as string)}/.main.log`
const logStore = `${await toPersistentPath(configFile as string)}/.main.db`
const logger = new Logger(configuration!.logger || {}, logStore)
await logger.init()
const startTimestamp = checkedArgs.get("start") ? new Date(Date.parse(checkedArgs.get("start")!)).getTime() : undefined
const endTimestamp = checkedArgs.get("end") ? new Date(Date.parse(checkedArgs.get("end")!)).getTime() : undefined
const numberOfRows = checkedArgs.get("n") ? parseInt(checkedArgs.get("n")!, 10) : undefined
let logs = await logger.getLogContents(checkedArgs.get("id"), startTimestamp, endTimestamp)
logs = logs.filter((log) => {
const { processId, severity } = log
const severityFilter = !checkedArgs.get("severity") || checkedArgs.get("severity") === "" || checkedArgs.get("severity")!.toLowerCase() === severity.toLowerCase()
const processFilter = !checkedArgs.get("id") || checkedArgs.get("id") === "" || checkedArgs.get("id")!.toLowerCase() === processId.toLowerCase()
return severityFilter && processFilter
})
if (numberOfRows) {
logs = logs.slice(-numberOfRows)
}
const logs = await logger.getLogContents(
(!checkedArgs.get("id") || checkedArgs.get("id") === "") ? undefined : checkedArgs.get("id")!.toLowerCase(),
startTimestamp,
endTimestamp,
(!checkedArgs.get("severity") || checkedArgs.get("severity") === "") ? undefined : checkedArgs.get("severity")!.toLowerCase(),
numberOfRows,
)
if (logs && logs.length > 0) {
const logWithColors = configuration!.logger?.colors ?? true
for (const log of logs) {
Expand Down Expand Up @@ -496,7 +494,7 @@ async function main() {
exit(1)
}
} catch (_e) {
console.error("Action failed: Could not contact the Pup instance.")
console.error("Action failed: Could not contact the Pup instance.", _e)
exit(1)
}
}
Expand Down Expand Up @@ -587,14 +585,16 @@ async function main() {
pup.init()

// Register for running pup.terminate() if not already run on clean exit
let hasRunShutdownCode = false
globalThis.addEventListener("beforeunload", (evt) => {
if (!hasRunShutdownCode) {
evt.preventDefault()
hasRunShutdownCode = true
;(async () => await pup.terminate(30000))()
}
})
if (globalThis.addEventListener) {
let hasRunShutdownCode = false
globalThis.addEventListener("beforeunload", (evt) => {
if (!hasRunShutdownCode) {
evt.preventDefault()
hasRunShutdownCode = true
;(async () => await pup.terminate(30000))()
}
})
}

if (CurrentRuntime === Runtime.Deno) {
// This is needed to trigger termination in Deno
Expand Down
6 changes: 3 additions & 3 deletions lib/cli/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { filesize } from "filesize"
import { blockedFormatter, codeFormatter, naFormatter, restartsFormatter, statusFormatter } from "./formatters/strings.ts"
import { timeagoFormatter } from "./formatters/times.ts"
import { Configuration, DEFAULT_REST_API_HOSTNAME } from "../core/configuration.ts"
import { resolve } from "@std/path"
import { ApiApplicationState } from "@pup/api-definitions"
import { toResolvedAbsolutePath } from "@pup/common/path"

/**
* Helper which print the status of all running processes,
Expand All @@ -29,8 +29,8 @@ import { ApiApplicationState } from "@pup/api-definitions"
export function printStatus(configFile: string, configuration: Configuration, cwd: string | undefined, status: ApiApplicationState) {
// Print configuration
console.log("")
console.log(Colors.bold("Configuration:") + "\t" + resolve(configFile))
console.log(Colors.bold("Working dir:") + "\t" + cwd || "Not set (default: pup)")
console.log(Colors.bold("Configuration:") + "\t" + toResolvedAbsolutePath(configFile))
console.log(Colors.bold("Working dir:") + "\t" + (cwd ? toResolvedAbsolutePath(cwd as string) : "Not set (default: pup)"))
console.log(Colors.bold("Instance name:") + "\t" + (configuration.name || "Not set"))
console.log(Colors.bold("Rest API URL:") + "\thttp://" + (configuration.api?.hostname || DEFAULT_REST_API_HOSTNAME) + ":" + status.port)

Expand Down
3 changes: 0 additions & 3 deletions lib/cli/upgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,6 @@ export async function upgrade(
if (ignoreCertificateErrorsString && ignoreCertificateErrorsString !== "") {
installCmd.push(ignoreCertificateErrorsString)
}
if (unstableInstall) {
installCmd.push("--unstable-kv")
}
installCmd.push("-n", "pup") // Installed command name = pup
installCmd.push(canaryInstall ? versions.canary_url : (requestedVersion as Version).url)

Expand Down
2 changes: 1 addition & 1 deletion lib/core/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,6 @@ export class PupApi {
this._pup.logger[severity](`api-${consumer}`, message)
}
public async getLogs(processId?: string, startTimeStamp?: number, endTimeStamp?: number, nRows?: number): Promise<LogEventData[]> {
return await this._pup.logger.getLogContents(processId, startTimeStamp, endTimeStamp, nRows)
return await this._pup.logger.getLogContents(processId, startTimeStamp, endTimeStamp, undefined, nRows)
}
}
12 changes: 6 additions & 6 deletions lib/core/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Cluster extends Process {
this.setInstances(this.config.cluster?.instances || 1)
}

public override start = async (reason?: string, restart?: boolean) => {
public override start = async (reason?: string, restart?: boolean): Promise<void> => {
await Promise.all(
this.processes.map((process) => process.start(reason, restart)),
)
Expand All @@ -35,7 +35,7 @@ class Cluster extends Process {
return true
}

public setInstances = (nInstances: number) => {
public setInstances = (nInstances: number): void => {
const backends = []

// ToDo: If there already are processes, reuse, stop or add
Expand Down Expand Up @@ -125,15 +125,15 @@ class Cluster extends Process {
return Promise.allSettled(results).then((results) => results.every((result) => result))
}

public override restart = (reason: string) => {
public override restart = (reason: string): void => {
this.processes.forEach((process) => process.restart(reason))
}

public override block = (reason: string) => {
public override block = (reason: string): void => {
this.processes.forEach((process) => process.block(reason))
}

public override unblock = (reason: string) => {
public override unblock = (reason: string): void => {
this.processes.forEach((process) => process.unblock(reason))
}

Expand Down Expand Up @@ -175,7 +175,7 @@ class Cluster extends Process {
return clusterStatus
}

public cleanup = () => {
public cleanup = (): void => {
this.loadBalancerWorker?.terminate()
this.loadBalancerWorker = null
}
Expand Down
2 changes: 1 addition & 1 deletion lib/core/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PluginConfiguration } from "@pup/plugin"

// Logger constants
export const DEFAULT_INTERNAL_LOG_HOURS = 48
export const KV_SIZE_LIMIT_BYTES = 65_536
export const KV_LIMIT_STRING_LENGTH_BYTES = 65_536

// Core constants
export const MAINTENANCE_INTERVAL_MS = 900_000
Expand Down
9 changes: 8 additions & 1 deletion lib/core/loadbalancer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* @license MIT
*/

import { CurrentRuntime, Runtime } from "@cross/runtime"
import { LOAD_BALANCER_DEFAULT_VALIDATION_INTERVAL_S } from "./configuration.ts"

export enum BalancingStrategy {
Expand Down Expand Up @@ -77,7 +78,13 @@ export class LoadBalancer {
private setupValidationTimer(): number {
const timer = setInterval(() => this.validateBackends(), this.validationInterval * 1000)
// Make the timer non-blocking
Deno.unrefTimer(timer)
if (CurrentRuntime === Runtime.Deno) {
Deno.unrefTimer(timer)
// @ts-ignore unref exists in node and bun
} else if (timer.unref) {
// @ts-ignore unref exists in node and bun
timer.unref()
}
return timer
}

Expand Down
Loading