spooder 4.0.1 → 4.1.0

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
@@ -56,6 +56,7 @@ If there are any issues with the provided configuration, a warning will be print
56
56
  The `CLI` component of `spooder` is a global command-line tool for running server processes.
57
57
 
58
58
  - [CLI > Usage](#cli-usage)
59
+ - [CLI > Dev Mode](#cli-dev-mode)
59
60
  - [CLI > Auto Restart](#cli-auto-restart)
60
61
  - [CLI > Auto Update](#cli-auto-update)
61
62
  - [CLI > Canary](#cli-canary)
@@ -94,6 +95,33 @@ While `spooder` uses a `bun run` command by default, it is possible to use any c
94
95
  }
95
96
  }
96
97
  ```
98
+
99
+ <a id="cli-dev-mode"></a>
100
+ ## CLI > Dev Mode
101
+
102
+ `spooder` can be started in development mode by providing the `--dev` flag when starting the server.
103
+
104
+ ```bash
105
+ spooder --dev
106
+ ```
107
+
108
+ The following differences will be observed when running in development mode:
109
+
110
+ - Update commands defined in `spooder.update` will not be executed when starting a server.
111
+ - If the server crashes and `auto_restart` is enabled, the server will not be restarted, and spooder will exit with the same exit code as the server.
112
+ - If canary is configured, reports will not be dispatched to GitHub and instead be printed to the console; this includes crash reports.
113
+
114
+ It is possible to detect in userland if a server is running in development mode by checking the `SPOODER_ENV` environment variable.
115
+
116
+ ```ts
117
+ if (process.env.SPOODER_DEV === 'dev') {
118
+ // Server is running in development mode.
119
+ }
120
+ ```
121
+
122
+ > [!NOTE]
123
+ > `SPOODER_ENV` should be either `dev` or `prod`. If the variable is not defined, the server was not started by the `spooder` CLI.
124
+
97
125
  <a id="cli-auto-restart"></a>
98
126
  ## CLI > Auto Restart
99
127
 
@@ -458,6 +486,20 @@ server.route('/test/route', (req, url) => {
458
486
  server.route('/redirect', () => Response.redirect('/redirected', 301));
459
487
  ```
460
488
 
489
+ ### Status Code Text
490
+
491
+ `spooder` exposes `HTTP_STATUS_CODE` to convieniently access status code text.
492
+
493
+ ```ts
494
+ import { HTTP_STATUS_CODE } from 'spooder';
495
+
496
+ server.default((req, status_code) => {
497
+ // status_code: 404
498
+ // Body: Not Found
499
+ return new Response(HTTP_STATUS_CODE[status_code], { status: status_code });
500
+ });
501
+ ```
502
+
461
503
  <a id="api-routing-request-handler"></a>
462
504
  ## API > Routing > RequestHandler
463
505
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "spooder",
3
3
  "type": "module",
4
- "version": "4.0.1",
4
+ "version": "4.1.0",
5
5
  "exports": {
6
6
  ".": {
7
7
  "bun": "./src/api.ts",
package/src/api.d.ts CHANGED
@@ -4,6 +4,10 @@
4
4
  /// <reference types="node" />
5
5
  import fs from 'node:fs/promises';
6
6
  import { Blob } from 'node:buffer';
7
+ export declare const HTTP_STATUS_CODE: {
8
+ [errorCode: number]: string | undefined;
9
+ [errorCode: string]: string | undefined;
10
+ };
7
11
  export declare class ErrorWithMetadata extends Error {
8
12
  metadata: Record<string, unknown>;
9
13
  constructor(message: string, metadata: Record<string, unknown>);
package/src/api.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { dispatch_report } from './dispatch';
2
- import { get_config } from './config';
3
2
  import http from 'node:http';
4
3
  import path from 'node:path';
5
4
  import fs from 'node:fs/promises';
@@ -7,6 +6,8 @@ import { log } from './utils';
7
6
  import crypto from 'crypto';
8
7
  import { Blob } from 'node:buffer';
9
8
 
9
+ export const HTTP_STATUS_CODE = http.STATUS_CODES;
10
+
10
11
  export class ErrorWithMetadata extends Error {
11
12
  constructor(message: string, public metadata: Record<string, unknown>) {
12
13
  super(message);
@@ -70,7 +71,13 @@ async function handle_error(prefix: string, err_message_or_obj: string | object,
70
71
  }
71
72
  }
72
73
 
73
- await dispatch_report(prefix + error_message, final_err);
74
+ if (process.env.SPOODER_ENV === 'dev') {
75
+ log('[dev] dispatch_report %s', prefix + error_message);
76
+ log('[dev] without --dev, this would raise a canary report');
77
+ log('[dev] %o', final_err);
78
+ } else {
79
+ await dispatch_report(prefix + error_message, final_err);
80
+ }
74
81
  }
75
82
 
76
83
  export async function panic(err_message_or_obj: string | object, ...err: object[]): Promise<void> {
package/src/cli.ts CHANGED
@@ -6,34 +6,44 @@ import { dispatch_report } from './dispatch';
6
6
  async function start_server() {
7
7
  log('start_server');
8
8
 
9
+ const argv = process.argv.slice(2);
10
+ const is_dev_mode = argv.includes('--dev');
11
+
12
+ if (is_dev_mode)
13
+ log('[dev] spooder has been started in dev mode');
14
+
9
15
  const config = await get_config();
10
16
 
11
- const update_commands = config.update;
12
- const n_update_commands = update_commands.length;
17
+ if (!is_dev_mode) {
18
+ const update_commands = config.update;
19
+ const n_update_commands = update_commands.length;
13
20
 
14
- if (n_update_commands > 0) {
15
- log('running %d update commands', n_update_commands);
21
+ if (n_update_commands > 0) {
22
+ log('running %d update commands', n_update_commands);
16
23
 
17
- for (let i = 0; i < n_update_commands; i++) {
18
- const config_update_command = update_commands[i];
24
+ for (let i = 0; i < n_update_commands; i++) {
25
+ const config_update_command = update_commands[i];
19
26
 
20
- log('[%d] %s', i, config_update_command);
27
+ log('[%d] %s', i, config_update_command);
21
28
 
22
- const update_proc = Bun.spawn(parse_command_line(config_update_command), {
23
- cwd: process.cwd(),
24
- stdout: 'inherit',
25
- stderr: 'inherit'
26
- });
29
+ const update_proc = Bun.spawn(parse_command_line(config_update_command), {
30
+ cwd: process.cwd(),
31
+ stdout: 'inherit',
32
+ stderr: 'inherit'
33
+ });
27
34
 
28
- await update_proc.exited;
35
+ await update_proc.exited;
29
36
 
30
- log('[%d] exited with code %d', i, update_proc.exitCode);
37
+ log('[%d] exited with code %d', i, update_proc.exitCode);
31
38
 
32
- if (update_proc.exitCode !== 0) {
33
- log('aborting update due to non-zero exit code from [%d]', i);
34
- break;
39
+ if (update_proc.exitCode !== 0) {
40
+ log('aborting update due to non-zero exit code from [%d]', i);
41
+ break;
42
+ }
35
43
  }
36
44
  }
45
+ } else {
46
+ log('[dev] skipping update commands in dev mode');
37
47
  }
38
48
 
39
49
  const crash_console_history = config.canary.crash_console_history;
@@ -42,6 +52,7 @@ async function start_server() {
42
52
  const std_mode = include_crash_history ? 'pipe' : 'inherit';
43
53
  const proc = Bun.spawn(parse_command_line(config.run), {
44
54
  cwd: process.cwd(),
55
+ env: { ...process.env, SPOODER_ENV: is_dev_mode ? 'dev' : 'prod' },
45
56
  stdout: std_mode,
46
57
  stderr: std_mode
47
58
  });
@@ -79,16 +90,27 @@ async function start_server() {
79
90
 
80
91
  if (proc_exit_code !== 0) {
81
92
  const console_output = include_crash_history ? strip_color_codes(stream_history.join('\n')) : undefined;
82
- dispatch_report('crash: server exited unexpectedly', [{
83
- proc_exit_code, console_output
84
- }]);
93
+
94
+ if (is_dev_mode) {
95
+ log('[dev] crash: server exited unexpectedly (exit code %d)', proc_exit_code);
96
+ log('[dev] without --dev, this would raise a canary report');
97
+ log('[dev] console output:\n%s', console_output);
98
+ } else {
99
+ dispatch_report('crash: server exited unexpectedly', [{
100
+ proc_exit_code, console_output
101
+ }]);
102
+ }
85
103
  }
86
-
87
104
 
88
105
  const auto_restart_ms = config.auto_restart;
89
106
  if (auto_restart_ms > -1) {
90
- log('restarting server in %dms', auto_restart_ms);
91
- setTimeout(start_server, auto_restart_ms);
107
+ if (is_dev_mode) {
108
+ log('[dev] auto-restart is disabled in dev mode');
109
+ process.exit(proc_exit_code ?? 0);
110
+ } else {
111
+ log('restarting server in %dms', auto_restart_ms);
112
+ setTimeout(start_server, auto_restart_ms);
113
+ }
92
114
  }
93
115
  }
94
116