spooder 2.0.7 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,33 +8,63 @@
8
8
 
9
9
  > **Warning** - This project is developed for [Bun](https://bun.sh/), which at the time of writing is still experimental. It is not recommended to use this project in production environments unless you understand the risks.
10
10
 
11
- ## Structure
11
+ ## Installation
12
12
 
13
- `spooder` consists of two primary parts: the `instance` and the `watcher`.
13
+ ```bash
14
+ bun add spooder --global
15
+ ```
16
+
17
+ ## Runner
14
18
 
15
- The `instance` is an API that can be imported into a Bun process to scaffold a web server instance. It is intended as a common set of tools for building individiual domain instances.
19
+ `spooder` also includes a global command-line tool for running the server. It is recommended that you run this in a `screen` session.
16
20
 
17
- The `watcher` is a daemon responsible for updating, starting and monitoring a collection of `instance` processes. It is intended to be run as a service on the host machine.
21
+ ```bash
22
+ screen -S spooder # Create a new screen session
23
+ cd /var/www/my_server/
24
+ spooder
25
+ ```
18
26
 
19
- ## Watcher
27
+ `spooder` will load the `module` defined in your `package.json` in a new process using `bun run <module>`. This can be overridden using the `entry` property of the `spooder section` in your `package.json`.
20
28
 
21
- ```toml
22
- # /var/www/spooder.toml
23
- [[domains]]
24
- name = "testdomain.net"
25
- path = "/var/www/testdomain.net"
26
- port = 3000
29
+ ```json
30
+ {
31
+ "spooder": {
32
+ "entry": "index.ts"
33
+ }
34
+ }
27
35
  ```
28
36
 
29
- ```bash
30
- # Installation
31
- bun add spooder -g
37
+ In the event that the server exits (regardless of exit code), `spooder` will automatically restart it after a short delay. This delay is configurable in the `spooder` section of your `package.json`.
38
+
39
+ ```json
40
+ {
41
+ "spooder": {
42
+ "autoRestart": true, // Defaults to true.
43
+ "restartDelay": 5000, // Defaults to 5000ms.
44
+ }
45
+ }
32
46
  ```
33
47
 
34
- ```bash
35
- # Running the watcher
36
- screen -S spooder # Create a new screen session
37
- spooder
48
+ When starting your server, `spooder` can automatically update the source code by running `git pull` in the working directory. This feature is disabled by default and can be enabled in the `spooder` section of your `package.json`.
49
+
50
+ ```json
51
+ {
52
+ "spooder": {
53
+ "autoUpdate": true // Defaults to false.
54
+ }
55
+ }
56
+ ```
57
+
58
+ When `autoUpdate` is enabled, your server process can initiate a self-update by terminating with the exit code `205`. This will cause `spooder` to run `git pull` and restart the server, which can be useful for responding to webhooks.
59
+
60
+ If `autoUpdate` is disabled, all exit codes will be considered a crash and the server will be restarted if `autoRestart` is enabled.
61
+
62
+ ## API
63
+
64
+ `spooder` exposes a simple API which can be imported into your project for bootstrapping a server in Bun. The API is designed to be minimal to leave control in the hands of the developer and not add overhead for features you may not need.
65
+
66
+ ```ts
67
+ import serve from 'spooder'; // WIP
38
68
  ```
39
69
 
40
70
  ## License
package/bun.lockb CHANGED
Binary file
package/package.json CHANGED
@@ -1,23 +1,13 @@
1
1
  {
2
2
  "name": "spooder",
3
3
  "type": "module",
4
- "version": "2.0.7",
5
- "exports": {
6
- ".": {
7
- "bun": "./src/api.ts",
8
- "import": "./src/api.ts"
9
- }
10
- },
11
- "bin": {
12
- "spooder": "./src/instance.ts",
13
- "spooder-update": "./src/update.ts",
14
- "spooder-heartbeat": "./src/heartbeat.ts"
15
- },
4
+ "module": "./src/api.ts",
5
+ "version": "2.0.9",
16
6
  "devDependencies": {
17
7
  "@types/node": "^20.0.0",
18
8
  "bun-types": "^0.5.0"
19
9
  },
20
- "dependencies": {
21
- "zod": "^3.21.4"
10
+ "bin": {
11
+ "spooder": "./src/cli.ts"
22
12
  }
23
13
  }
package/src/api.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function test_api(): void;
package/src/api.ts ADDED
@@ -0,0 +1,3 @@
1
+ export function test_api() {
2
+ console.log('test_api :: hello world!');
3
+ }
package/src/cli.d.ts ADDED
File without changes
package/src/cli.ts ADDED
@@ -0,0 +1 @@
1
+ console.log('Welcome to the Spooder CLI!');
@@ -1 +0,0 @@
1
- #!/usr/bin/env bun
package/src/heartbeat.ts DELETED
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- // TODO: Iterate over all directories in /var/www and identify which ones are spooder domains.
4
- // TODO: For each spooder domain, check if the process is running.
5
- // TODO: Run `spooder` inside any domain directory that is not running.
6
- // TODO: Report crashed domains somewhere/somehow?
package/src/instance.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env bun
2
- export {};
package/src/instance.ts DELETED
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import { join } from 'node:path';
4
-
5
- async function write_pid_file() {
6
- const pid_file = join(process.cwd(), '.spooder_pid');
7
- await Bun.write(pid_file, process.pid.toString());
8
- }
9
-
10
- async function main() {
11
- await write_pid_file();
12
-
13
- const index_file = join(process.cwd(), 'index.ts');
14
- // TODO: Add error handling if index_file does not exist?
15
-
16
- const module = await import(index_file);
17
- console.log(module);
18
- // TODO: Add a route for GitHub webhooks.
19
- // TODO: Add authentication for the webhook to prevent abuse.
20
- // TODO: Run `spooder-update` when the webhook is triggered, then self-terminate.
21
- }
22
-
23
- main();
package/src/update.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env bun
2
- export {};
package/src/update.ts DELETED
@@ -1,93 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import { join } from 'node:path';
4
- import { z } from 'zod';
5
-
6
- const ConfigSchema = z.object({
7
- domain: z.object({
8
- name: z.string(),
9
- port: z.number()
10
- }),
11
-
12
- git: z.object({
13
- url: z.string(),
14
- branch: z.string().default('main')
15
- }).optional()
16
- });
17
-
18
- async function get_last_pid() : Promise<number> {
19
- const pid_file = Bun.file(join(process.cwd(), '.spooder_pid'));
20
- if (pid_file.size > 0) {
21
- const pid = parseInt(await pid_file.text());
22
- if (!isNaN(pid))
23
- return pid;
24
- }
25
-
26
- return -1;
27
- }
28
-
29
- async function pid_is_running(pid: number) : Promise<boolean> {
30
- const process = Bun.spawnSync(['ps', '-p', pid.toString()]);
31
- if (!process.success)
32
- return false;
33
-
34
- const stdout = process.stdout?.toString();
35
-
36
- // Ensure stdout contains more than one line.
37
- if (!stdout || stdout.split('\n').length <= 1)
38
- return false;
39
-
40
- return false;
41
- }
42
-
43
- async function wait_for_pid_to_exit(pid: number) : Promise<void> {
44
- console.log(`Waiting for process ${pid} to exit...`);
45
- while (await pid_is_running(pid))
46
- await Bun.sleep(1000);
47
- }
48
-
49
- function is_git_repository(directory: string): boolean {
50
- // The command `git rev-parse --is-inside-work-tree` returns `true` to stdout
51
- // if the current working directory is inside a git repository.
52
- const process = Bun.spawnSync(['git', 'rev-parse', '--is-inside-work-tree'], { cwd: directory });
53
- return process.stdout?.toString().trim() === 'true';
54
- }
55
-
56
- function pull_git_repository(directory: string, url: string, branch: string) {
57
- console.log(`Pulling git repository ${branch} @ ${url} into ${directory}...`);
58
- const process = Bun.spawnSync(['git', 'pull', url, branch], { cwd: directory });
59
- if (!process.success)
60
- throw new Error('Failed to pull git repository.');
61
- }
62
-
63
- function init_git_repository(directory: string) {
64
- console.log(`Initializing git repository in ${directory}...`);
65
- const process = Bun.spawnSync(['git', 'init'], { cwd: directory });
66
- if (!process.success)
67
- throw new Error('Failed to initialize git repository.');
68
- }
69
-
70
- async function load_configuration() {
71
- const config_file = join(process.cwd(), 'spooder.toml');
72
- return ConfigSchema.parse(await import(config_file));
73
- }
74
-
75
- async function main() {
76
- const config = await load_configuration();
77
-
78
- // Wait for the previous process, if it exists, to exit.
79
- await wait_for_pid_to_exit(await get_last_pid());
80
-
81
- const cwd = process.cwd();
82
- if (config.git) {
83
- if (!is_git_repository(cwd))
84
- init_git_repository(cwd);
85
-
86
- pull_git_repository(cwd, config.git.url, config.git.branch);
87
- }
88
-
89
- const server = Bun.spawn(['spooder'], { cwd });
90
- server.unref();
91
- }
92
-
93
- main();