@procedures/server 0.11.0 → 0.12.1
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/CHANGELOG.md +44 -0
- package/README.md +15 -6
- package/dist/.tsbuildinfo +1 -1
- package/dist/host.d.ts +52 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +51 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/run.d.ts +11 -3
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +53 -44
- package/dist/run.js.map +1 -1
- package/package.json +5 -4
- package/src/host.ts +76 -0
- package/src/index.ts +4 -2
- package/src/run.ts +70 -52
package/dist/host.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runner entry of the procedures host (CLI-8, decisions D2, D6, D7 and D17).
|
|
3
|
+
*
|
|
4
|
+
* `runProcedureHost(config)` is the only entry that starts `run()` of `@mark1russell7/service` for
|
|
5
|
+
* `procedure-server`, `mark serve` and `mark --server`. It declares the parts of
|
|
6
|
+
* `createProcedureHost()` of `@procedures/peer` in one service. The runner owns the signals, the
|
|
7
|
+
* stop in stages and the exit. Thus the entry installs no signal handler and no hard-exit timer.
|
|
8
|
+
*
|
|
9
|
+
* - The profile: `localDev` for a run in the foreground, where a second Ctrl-C exits at once, and
|
|
10
|
+
* `daemon` for the background host of `mark`, where a repeat signal has no effect (D6, D7).
|
|
11
|
+
* - The caps of the stages sum to 10 s. They replace the hard-exit timer of 10 s of the entries.
|
|
12
|
+
* - No check gates readiness or liveness, so the host is ready from the end of its startup.
|
|
13
|
+
* - The lockfile is a dependency: its connect writes it before the listeners start, and its close
|
|
14
|
+
* removes it after the listeners close.
|
|
15
|
+
*/
|
|
16
|
+
import { type Lifecycle, type Profile, type RunOptions, type ServiceBuilder } from "@mark1russell7/service";
|
|
17
|
+
import { type ProcedureHost, type ProcedureHostOptions } from "@procedures/peer";
|
|
18
|
+
import { type LockfileData } from "@procedures/peer/lockfile";
|
|
19
|
+
/** The mode of a run: in the foreground of a terminal, or as the background host of `mark`. */
|
|
20
|
+
export type HostRunMode = "foreground" | "background";
|
|
21
|
+
/** The profile of each mode, as data: `localDev` in the foreground, and `daemon` in the background. */
|
|
22
|
+
export declare const HOST_PROFILES: Readonly<Record<HostRunMode, Profile>>;
|
|
23
|
+
/** The configuration of `runProcedureHost()`. */
|
|
24
|
+
export interface ProcedureHostRunConfig {
|
|
25
|
+
/** The name of the service of the process. */
|
|
26
|
+
readonly name: string;
|
|
27
|
+
/** The options of the host: the registry, the policy, the faces, the listeners and the collections. */
|
|
28
|
+
readonly host: ProcedureHostOptions;
|
|
29
|
+
readonly mode: HostRunMode;
|
|
30
|
+
/** A profile in place of the profile of the mode. The caller can change a field of it with a spread. */
|
|
31
|
+
readonly profile?: Profile | undefined;
|
|
32
|
+
/** The lockfile of the host, for `mark --server`. */
|
|
33
|
+
readonly lockfile?: LockfileData | undefined;
|
|
34
|
+
/** This function prints the lines of the run, for example at the start of the shutdown. */
|
|
35
|
+
readonly log?: ((line: string) => void) | undefined;
|
|
36
|
+
/** The options of `run()`: a process port and a clock, for a test. The host gets the same clock. */
|
|
37
|
+
readonly run?: RunOptions | undefined;
|
|
38
|
+
}
|
|
39
|
+
/** A host that runs under `run()`: the host, the service of the process and its lifecycle. */
|
|
40
|
+
export interface RunningHost {
|
|
41
|
+
readonly host: ProcedureHost;
|
|
42
|
+
readonly service: ServiceBuilder;
|
|
43
|
+
/** The lifecycle. Its state is `running` after a startup that ended, and `draining` or `exited` after a startup that failed. */
|
|
44
|
+
readonly life: Lifecycle;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* This function declares the service of a procedures host and starts `run()`. It gives the host
|
|
48
|
+
* when the startup ends. After a startup that failed, `life.errors` tells why, and the process
|
|
49
|
+
* exits with the code 1 after the shutdown.
|
|
50
|
+
*/
|
|
51
|
+
export declare function runProcedureHost(config: ProcedureHostRunConfig): Promise<RunningHost>;
|
|
52
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAA6B,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEvI,OAAO,EAAuB,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACtG,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9E,+FAA+F;AAC/F,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,YAAY,CAAC;AAEtD,uGAAuG;AACvG,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAA+D,CAAC;AAEjI,iDAAiD;AACjD,MAAM,WAAW,sBAAsB;IACrC,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uGAAuG;IACvG,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,wGAAwG;IACxG,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAC7C,2FAA2F;IAC3F,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACpD,oGAAoG;IACpG,QAAQ,CAAC,GAAG,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CACvC;AAED,8FAA8F;AAC9F,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,gIAAgI;IAChI,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC,CAkB3F"}
|
package/dist/host.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runner entry of the procedures host (CLI-8, decisions D2, D6, D7 and D17).
|
|
3
|
+
*
|
|
4
|
+
* `runProcedureHost(config)` is the only entry that starts `run()` of `@mark1russell7/service` for
|
|
5
|
+
* `procedure-server`, `mark serve` and `mark --server`. It declares the parts of
|
|
6
|
+
* `createProcedureHost()` of `@procedures/peer` in one service. The runner owns the signals, the
|
|
7
|
+
* stop in stages and the exit. Thus the entry installs no signal handler and no hard-exit timer.
|
|
8
|
+
*
|
|
9
|
+
* - The profile: `localDev` for a run in the foreground, where a second Ctrl-C exits at once, and
|
|
10
|
+
* `daemon` for the background host of `mark`, where a repeat signal has no effect (D6, D7).
|
|
11
|
+
* - The caps of the stages sum to 10 s. They replace the hard-exit timer of 10 s of the entries.
|
|
12
|
+
* - No check gates readiness or liveness, so the host is ready from the end of its startup.
|
|
13
|
+
* - The lockfile is a dependency: its connect writes it before the listeners start, and its close
|
|
14
|
+
* removes it after the listeners close.
|
|
15
|
+
*/
|
|
16
|
+
import { daemon, localDev, service } from "@mark1russell7/service";
|
|
17
|
+
import { seconds } from "@procedures/client";
|
|
18
|
+
import { createProcedureHost } from "@procedures/peer";
|
|
19
|
+
import { lockfileHandle } from "@procedures/peer/lockfile";
|
|
20
|
+
/** The profile of each mode, as data: `localDev` in the foreground, and `daemon` in the background. */
|
|
21
|
+
export const HOST_PROFILES = Object.freeze({ foreground: localDev, background: daemon });
|
|
22
|
+
/**
|
|
23
|
+
* This function declares the service of a procedures host and starts `run()`. It gives the host
|
|
24
|
+
* when the startup ends. After a startup that failed, `life.errors` tells why, and the process
|
|
25
|
+
* exits with the code 1 after the shutdown.
|
|
26
|
+
*/
|
|
27
|
+
export async function runProcedureHost(config) {
|
|
28
|
+
const clock = config.run?.clock;
|
|
29
|
+
const host = createProcedureHost({ ...config.host, ...(clock ? { clock } : {}) });
|
|
30
|
+
const profile = config.profile ?? HOST_PROFILES[config.mode];
|
|
31
|
+
const svc = service(config.name).profile(profile);
|
|
32
|
+
// The profiles of the computer of a developer leave the policies to the service. No check gates them.
|
|
33
|
+
if (!profile.readiness)
|
|
34
|
+
svc.readiness({ type: "debounce", interval: seconds(5), failAfter: 3, recoverAfter: 1 });
|
|
35
|
+
if (!profile.liveness)
|
|
36
|
+
svc.liveness({ type: "window", failAfter: seconds(45) });
|
|
37
|
+
if (!profile.startup)
|
|
38
|
+
svc.startup(seconds(30));
|
|
39
|
+
// A repeat signal: an exit at once in the foreground, no effect in the background (D6)
|
|
40
|
+
svc.onRepeatSignal(profile.onRepeatSignal ?? (config.mode === "foreground" ? "exit" : "ignore"));
|
|
41
|
+
host.declare(svc);
|
|
42
|
+
// The lockfile: after the storages it connects, and before them it closes
|
|
43
|
+
if (config.lockfile)
|
|
44
|
+
svc.dependency("lockfile", { system: null, knobs: {}, operations: {} }, lockfileHandle(config.lockfile));
|
|
45
|
+
const log = config.log;
|
|
46
|
+
if (log && profile.phases?.some((phase) => phase.name === "stop intake"))
|
|
47
|
+
svc.onPhase("stop intake", () => log("\nShutting down..."));
|
|
48
|
+
const life = await svc.run(config.run);
|
|
49
|
+
return { host, service: svc, life };
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=host.js.map
|
package/dist/host.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAsE,MAAM,wBAAwB,CAAC;AACvI,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAiD,MAAM,kBAAkB,CAAC;AACtG,OAAO,EAAE,cAAc,EAAqB,MAAM,2BAA2B,CAAC;AAK9E,uGAAuG;AACvG,MAAM,CAAC,MAAM,aAAa,GAA2C,MAAM,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;AA2BjI;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAA8B;IACnE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC;IAChC,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAClF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,sGAAsG;IACtG,IAAI,CAAC,OAAO,CAAC,SAAS;QAAE,GAAG,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;IACjH,IAAI,CAAC,OAAO,CAAC,QAAQ;QAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAChF,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/C,uFAAuF;IACvF,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClB,0EAA0E;IAC1E,IAAI,MAAM,CAAC,QAAQ;QAAE,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9H,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IACvB,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC;QAAE,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACtI,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACtC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* @procedures/server
|
|
3
3
|
*
|
|
4
4
|
* General procedure server - run any procedure packages via HTTP/WebSocket. Importing this entry
|
|
5
|
-
* starts nothing: `runServer(argv)` is the CLI (`server` and `mark serve`),
|
|
6
|
-
* starts a server
|
|
5
|
+
* starts nothing: `runServer(argv)` is the CLI (`server` and `mark serve`), `runProcedureHost()`
|
|
6
|
+
* runs a procedures host under `run()`, and `startServer()` starts a server outside a service.
|
|
7
7
|
*/
|
|
8
8
|
export { parseConfig, parseTopicPatterns } from "./config.js";
|
|
9
9
|
export { runServer, startServer, loadProcedureModule, type RunningServer, type ServerRunOptions } from "./run.js";
|
|
10
|
+
export { runProcedureHost, HOST_PROFILES, type ProcedureHostRunConfig, type RunningHost, type HostRunMode } from "./host.js";
|
|
10
11
|
export type { ServerConfig, TransportConfig, ServerCreateResult, ServerStartInput, ServerStartOutput, ServerStopInput, ServerStopOutput, ServerStatusInput, ServerStatusOutput, } from "./types.js";
|
|
11
12
|
export * from "./module.js";
|
|
12
13
|
export { serverStartProcedure } from "./procedures/server.start.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAElH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,KAAK,sBAAsB,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7H,YAAY,EACV,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAIpB,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
* @procedures/server
|
|
3
3
|
*
|
|
4
4
|
* General procedure server - run any procedure packages via HTTP/WebSocket. Importing this entry
|
|
5
|
-
* starts nothing: `runServer(argv)` is the CLI (`server` and `mark serve`),
|
|
6
|
-
* starts a server
|
|
5
|
+
* starts nothing: `runServer(argv)` is the CLI (`server` and `mark serve`), `runProcedureHost()`
|
|
6
|
+
* runs a procedures host under `run()`, and `startServer()` starts a server outside a service.
|
|
7
7
|
*/
|
|
8
8
|
export { parseConfig, parseTopicPatterns } from "./config.js";
|
|
9
9
|
export { runServer, startServer, loadProcedureModule } from "./run.js";
|
|
10
|
+
// The runner entry of the procedures host (CLI-8): the only entry that starts run()
|
|
11
|
+
export { runProcedureHost, HOST_PROFILES } from "./host.js";
|
|
10
12
|
// server.start, server.stop and server.status (from @procedures/peer). The root registers
|
|
11
13
|
// nothing: import "@procedures/server/register", or give the module to createRegistry().
|
|
12
14
|
export * from "./module.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,mBAAmB,EAA6C,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,mBAAmB,EAA6C,MAAM,UAAU,CAAC;AAClH,oFAAoF;AACpF,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAmE,MAAM,WAAW,CAAC;AAa7H,0FAA0F;AAC1F,yFAAyF;AACzF,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,cAAc,CAAC"}
|
package/dist/run.d.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* (`confineToRoot()` of `@procedures/fs`).
|
|
13
13
|
*/
|
|
14
14
|
import { type HostPolicy, type ProcedureModule, type ProcedureRegistry } from "@procedures/client";
|
|
15
|
+
import type { RunOptions } from "@mark1russell7/service";
|
|
15
16
|
import { type Peer, type PeerEndpoint } from "@procedures/peer";
|
|
16
17
|
import type { ServerConfig } from "./types.js";
|
|
17
18
|
/**
|
|
@@ -39,12 +40,19 @@ export interface RunningServer {
|
|
|
39
40
|
export interface ServerRunOptions {
|
|
40
41
|
/** The folders that a `--procedures` package resolves from, first to last (default: the current folder). */
|
|
41
42
|
resolveFrom?: readonly string[] | undefined;
|
|
43
|
+
/** The options of `run()` of `runServer()`: a process port and a clock, for a test (CLI-8). */
|
|
44
|
+
run?: RunOptions | undefined;
|
|
42
45
|
}
|
|
43
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* This function starts the server of a configuration outside a service, as a peer. It returns when
|
|
48
|
+
* the transports listen. `peer.stop()` stops it. The `server` CLI uses `runServer()` instead.
|
|
49
|
+
*/
|
|
44
50
|
export declare function startServer(config: ServerConfig, log?: (line: string) => void, options?: ServerRunOptions): Promise<RunningServer>;
|
|
45
51
|
/**
|
|
46
|
-
* The `server` CLI: parse the options, start the server
|
|
47
|
-
*
|
|
52
|
+
* The `server` CLI: parse the options, start the server under `run()` of `@mark1russell7/service`,
|
|
53
|
+
* and print where it listens. `mark serve` calls it with its own arguments. The runner owns the
|
|
54
|
+
* signals, the stop in stages and the exit: this function installs no signal handler and no
|
|
55
|
+
* hard-exit timer (CLI-8). Its promise ends when the lifecycle ends.
|
|
48
56
|
*/
|
|
49
57
|
export declare function runServer(argv: string[], options?: ServerRunOptions): Promise<void>;
|
|
50
58
|
//# sourceMappingURL=run.d.ts.map
|
package/dist/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,EAML,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,EAML,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAA+B,KAAK,IAAI,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAK7F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA8C/C;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,GAAE,SAAS,MAAM,EAAoB,GAAG,OAAO,CAAC,eAAe,CAAC,CAclI;AAwCD,6CAA6C;AAC7C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,kDAAkD;IAClD,cAAc,EAAE,OAAO,CAAC;IACxB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CACzC;AAcD,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,4GAA4G;IAC5G,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5C,+FAA+F;IAC/F,GAAG,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC9B;AAqDD;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,YAAY,EACpB,GAAG,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAkB,EACzC,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,aAAa,CAAC,CAaxB;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkD7F"}
|
package/dist/run.js
CHANGED
|
@@ -16,11 +16,11 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
16
16
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
17
17
|
import { pathToFileURL } from "node:url";
|
|
18
18
|
import { PROCEDURE_REGISTRY, createRegistry, hostPolicy, pathToKey, } from "@procedures/client";
|
|
19
|
-
import { createPeer } from "@procedures/peer";
|
|
19
|
+
import { createPeer, peerHostOptions } from "@procedures/peer";
|
|
20
20
|
import peerModule from "@procedures/peer/module";
|
|
21
21
|
import { parseConfig } from "./config.js";
|
|
22
|
+
import { runProcedureHost } from "./host.js";
|
|
22
23
|
import { serverModule } from "./module.js";
|
|
23
|
-
import { seconds } from "@procedures/client";
|
|
24
24
|
/** A package name and the subpath after it: "@a/b/register" gives ["@a/b", "./register"]. */
|
|
25
25
|
function splitSpec(spec) {
|
|
26
26
|
const parts = spec.split("/");
|
|
@@ -115,7 +115,10 @@ async function confineRoot(registry, root, resolveFrom) {
|
|
|
115
115
|
throw new Error("--fs-root needs a version of @procedures/fs with confineToRoot");
|
|
116
116
|
return confine(registry, root);
|
|
117
117
|
}
|
|
118
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* The token of a configuration: `--token`, else `SERVER_TOKEN`, else a random one of 32 bytes, the
|
|
120
|
+
* size of the token of `mark --server` (CLI-8). `--no-token`: none.
|
|
121
|
+
*/
|
|
119
122
|
function tokenOf(config) {
|
|
120
123
|
const envToken = process.env["SERVER_TOKEN"] || undefined;
|
|
121
124
|
if (config.token === null)
|
|
@@ -124,10 +127,14 @@ function tokenOf(config) {
|
|
|
124
127
|
return { token: config.token, generated: false };
|
|
125
128
|
if (envToken !== undefined)
|
|
126
129
|
return { token: envToken, generated: false };
|
|
127
|
-
return { token: randomBytes(
|
|
130
|
+
return { token: randomBytes(32).toString("hex"), generated: true };
|
|
128
131
|
}
|
|
129
|
-
/**
|
|
130
|
-
|
|
132
|
+
/** A new peer id. */
|
|
133
|
+
function newPeerId() {
|
|
134
|
+
return `peer-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
135
|
+
}
|
|
136
|
+
/** This function builds the registry and the host policy of a configuration. */
|
|
137
|
+
async function prepareServer(config, log, options) {
|
|
131
138
|
// The server.* procedures: those of the peer package (server.create, server.call and the
|
|
132
139
|
// others), and server.start, server.stop and server.status of this package
|
|
133
140
|
const modules = [peerModule, serverModule];
|
|
@@ -161,12 +168,15 @@ export async function startServer(config, log = console.log, options = {}) {
|
|
|
161
168
|
// bus, which is also the ctx.bus of the procedures.
|
|
162
169
|
events: { topics: config.events ?? [] },
|
|
163
170
|
});
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
171
|
+
return { registry, policy, token, generated, confined };
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* This function starts the server of a configuration outside a service, as a peer. It returns when
|
|
175
|
+
* the transports listen. `peer.stop()` stops it. The `server` CLI uses `runServer()` instead.
|
|
176
|
+
*/
|
|
177
|
+
export async function startServer(config, log = console.log, options = {}) {
|
|
178
|
+
const { registry, policy, token, generated, confined } = await prepareServer(config, log, options);
|
|
179
|
+
const peer = await createPeer({ id: newPeerId(), transports: config.transports, registry, policy });
|
|
170
180
|
await peer.start();
|
|
171
181
|
return {
|
|
172
182
|
peer,
|
|
@@ -179,8 +189,10 @@ export async function startServer(config, log = console.log, options = {}) {
|
|
|
179
189
|
};
|
|
180
190
|
}
|
|
181
191
|
/**
|
|
182
|
-
* The `server` CLI: parse the options, start the server
|
|
183
|
-
*
|
|
192
|
+
* The `server` CLI: parse the options, start the server under `run()` of `@mark1russell7/service`,
|
|
193
|
+
* and print where it listens. `mark serve` calls it with its own arguments. The runner owns the
|
|
194
|
+
* signals, the stop in stages and the exit: this function installs no signal handler and no
|
|
195
|
+
* hard-exit timer (CLI-8). Its promise ends when the lifecycle ends.
|
|
184
196
|
*/
|
|
185
197
|
export async function runServer(argv, options = {}) {
|
|
186
198
|
const config = parseConfig(argv);
|
|
@@ -189,19 +201,34 @@ export async function runServer(argv, options = {}) {
|
|
|
189
201
|
console.log(" Procedures:", config.procedures.join(", ") || "(none specified)");
|
|
190
202
|
console.log(" Transports:", config.transports.map((t) => t.type).join(", "));
|
|
191
203
|
}
|
|
192
|
-
const
|
|
204
|
+
const { registry, policy, token, generated, confined } = await prepareServer(config, console.log, options);
|
|
205
|
+
const { host, life } = await runProcedureHost({
|
|
206
|
+
name: "procedure-server",
|
|
207
|
+
mode: "foreground",
|
|
208
|
+
host: peerHostOptions({ id: newPeerId(), transports: config.transports, registry, policy }, "procedures"),
|
|
209
|
+
log: console.log,
|
|
210
|
+
...(options.run ? { run: options.run } : {}),
|
|
211
|
+
});
|
|
212
|
+
if (life.state !== "running") {
|
|
213
|
+
// The startup failed: the lifecycle stops the parts that started, and the process exits with 1
|
|
214
|
+
console.error("Server failed to start:");
|
|
215
|
+
for (const error of life.errors)
|
|
216
|
+
console.error(` ${error}`);
|
|
217
|
+
await life.done;
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
193
220
|
console.log("\nServer started!");
|
|
194
|
-
console.log(` Server ID: ${
|
|
195
|
-
console.log(` Procedures: ${
|
|
221
|
+
console.log(` Server ID: ${host.id}`);
|
|
222
|
+
console.log(` Procedures: ${host.server.procedureCount}`);
|
|
196
223
|
console.log("\nEndpoints:");
|
|
197
|
-
for (const endpoint of
|
|
224
|
+
for (const endpoint of host.info.endpoints()) {
|
|
198
225
|
console.log(` [${endpoint.type}] ${endpoint.address}`);
|
|
199
226
|
}
|
|
200
|
-
if (
|
|
227
|
+
if (token === undefined) {
|
|
201
228
|
console.log("\nNo token: any program on this computer can call the server.");
|
|
202
229
|
}
|
|
203
230
|
else {
|
|
204
|
-
console.log(`\nToken${
|
|
231
|
+
console.log(`\nToken${generated ? " (random, for this run)" : ""}: ${token}`);
|
|
205
232
|
console.log(" Send it as 'Authorization: Bearer <token>', or as ?token=<token> for WebSocket.");
|
|
206
233
|
}
|
|
207
234
|
if (config.expose.length > 0) {
|
|
@@ -209,31 +236,13 @@ export async function runServer(argv, options = {}) {
|
|
|
209
236
|
}
|
|
210
237
|
const events = config.events ?? [];
|
|
211
238
|
console.log(events.length > 0 ? `Event topics (events.subscribe): ${events.join(", ")}` : "Event topics: none (--events adds them)");
|
|
212
|
-
if (
|
|
213
|
-
console.log(`File root: ${
|
|
214
|
-
console.log(` Refused under the root: ${
|
|
239
|
+
if (confined !== undefined) {
|
|
240
|
+
console.log(`File root: ${confined.root} (each procedure refuses a path outside it)`);
|
|
241
|
+
console.log(` Refused under the root: ${confined.refused.length} procedures that the root cannot confine`);
|
|
215
242
|
}
|
|
216
243
|
console.log("\nPress Ctrl+C to stop the server.");
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
|
|
220
|
-
const stop = () => {
|
|
221
|
-
if (stopping)
|
|
222
|
-
process.exit(1);
|
|
223
|
-
stopping = true;
|
|
224
|
-
console.log("\nShutting down...");
|
|
225
|
-
setTimeout(() => process.exit(1), 10_000).unref();
|
|
226
|
-
// The calls in flight have 5 seconds to end (roadmap R14)
|
|
227
|
-
running.peer.stop({ grace: seconds(5) }).then(() => process.exit(0), (error) => {
|
|
228
|
-
console.error(`The server did not stop cleanly: ${error instanceof Error ? error.message : String(error)}`);
|
|
229
|
-
process.exit(1);
|
|
230
|
-
});
|
|
231
|
-
};
|
|
232
|
-
process.on("SIGINT", stop);
|
|
233
|
-
process.on("SIGTERM", stop);
|
|
234
|
-
// Keep the process alive
|
|
235
|
-
await new Promise(() => {
|
|
236
|
-
// Never resolves - keeps process running
|
|
237
|
-
});
|
|
244
|
+
// A signal starts the stop in stages: the stop of the intake, the drain, the close of the
|
|
245
|
+
// listeners and of the storages. A second Ctrl-C exits at once (the profile localDev, D6).
|
|
246
|
+
await life.done;
|
|
238
247
|
}
|
|
239
248
|
//# sourceMappingURL=run.js.map
|
package/dist/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,SAAS,GAKV,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,SAAS,GAKV,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,UAAU,EAAE,eAAe,EAAgC,MAAM,kBAAkB,CAAC;AAC7F,OAAO,UAAU,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,6FAA6F;AAC7F,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,IAAY,EAAE,OAAe,EAAE,IAAY;IAChE,IAAI,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,SAAS,CAAC;QACR,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7D,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QAClD,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAyD,CAAC;YACxH,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC;YACjF,MAAM,MAAM,GACV,OAAO,KAAK,KAAK,QAAQ;gBACvB,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,CAAE,KAA2D,EAAE,MAAM,IAAK,KAA0C,EAAE,OAAO,CAAC,CAAC;YACrI,IAAI,MAAM;gBAAE,OAAO,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACxC,IAAI,OAAO,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI;gBAAE,OAAO,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YACzE,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,SAAS,CAAC;QACrC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED,0GAA0G;AAC1G,SAAS,YAAY,CAAC,IAAY,EAAE,OAAe,EAAE,OAA0B;IAC7E,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAChD,IAAI,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;IAChE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAY,EAAE,WAAW,GAAsB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IACtG,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;IACpF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QAC9D,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,SAAS,IAAI,GAAG,IAAI,SAAS,CAAC,CAAkC,CAAC;YAC/F,IAAI,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC;QAC3F,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;QACD,OAAO,cAAc,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,IAAI,IAAI,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACnG,CAAC;AAED,uFAAuF;AACvF,KAAK,UAAU,cAAc,CAAC,IAAY,EAAE,MAAc;IACxD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IACrB,MAAM,KAAK,GAAmB,kBAAkB,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxH,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACrC,CAAC;AAaD;;;;;GAKG;AACH,KAAK,UAAU,WAAW,CAAC,QAA2B,EAAE,IAAY,EAAE,WAA8B;IAClG,MAAM,MAAM,GAAG,YAAY,CAAC,gBAAgB,EAAE,UAAU,EAAE,WAAW,CAAC,IAAI,uBAAuB,CAAC;IAClG,IAAI,OAAkC,CAAC;IACvC,IAAI,CAAC;QACH,OAAO,GAAI,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,CAAuC,CAAC,aAAa,CAAC;IACxF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,+CAA+C,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC3H,CAAC;IACD,gFAAgF;IAChF,IAAI,OAAO,OAAO,KAAK,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACrH,OAAO,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACjC,CAAC;AAiBD;;;GAGG;AACH,SAAS,OAAO,CAAC,MAAoB;IACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC;IAC1D,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACzE,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACjF,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACzE,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACrE,CAAC;AAmBD,qBAAqB;AACrB,SAAS,SAAS;IAChB,OAAO,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACxE,CAAC;AAED,gFAAgF;AAChF,KAAK,UAAU,aAAa,CAAC,MAAoB,EAAE,GAA2B,EAAE,OAAyB;IACvG,yFAAyF;IACzF,2EAA2E;IAC3E,MAAM,OAAO,GAAsB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAC9D,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACrC,IAAI,MAAM,CAAC,OAAO;YAAE,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,MAAM,mBAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACxF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzH,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,OAAO,CAAC,CAAC;IAC5C,IAAI,MAAM,CAAC,OAAO;QAAE,GAAG,CAAC,4BAA4B,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IAEhF,2FAA2F;IAC3F,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC9I,IAAI,QAAQ,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAC/B,GAAG,CAAC,iBAAiB,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC,MAAM,mBAAmB,QAAQ,CAAC,QAAQ,CAAC,MAAM,sBAAsB,QAAQ,CAAC,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;IAC/J,CAAC;IAED,wFAAwF;IACxF,yDAAyD;IACzD,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,UAAU,CAAC;QACxB,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzC,4FAA4F;QAC5F,4FAA4F;QAC5F,oDAAoD;QACpD,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE;KACxC,CAAC,CAAC;IACH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAoB,EACpB,GAAG,GAA2B,OAAO,CAAC,GAAG,EACzC,OAAO,GAAqB,EAAE;IAE9B,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACnG,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACpG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACnB,OAAO;QACL,IAAI;QACJ,QAAQ;QACR,MAAM;QACN,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE;QAC9B,KAAK;QACL,cAAc,EAAE,SAAS;QACzB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACnF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAc,EAAE,OAAO,GAAqB,EAAE;IAC5E,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC5C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,CAAC;QACjF,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChF,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC3G,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,gBAAgB,CAAC;QAC5C,IAAI,EAAE,kBAAkB;QACxB,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,eAAe,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,YAAY,CAAC;QACzG,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7C,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,+FAA+F;QAC/F,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACzC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;QAC7D,MAAM,IAAI,CAAC,IAAI,CAAC;QAChB,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;IAC/E,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,UAAU,SAAS,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC,CAAC;QAC9E,OAAO,CAAC,GAAG,CAAC,mFAAmF,CAAC,CAAC;IACnG,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,oCAAoC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,yCAAyC,CAAC,CAAC;IACrI,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,CAAC,IAAI,6CAA6C,CAAC,CAAC;QACtF,OAAO,CAAC,GAAG,CAAC,6BAA6B,QAAQ,CAAC,OAAO,CAAC,MAAM,0CAA0C,CAAC,CAAC;IAC9G,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAClD,0FAA0F;IAC1F,2FAA2F;IAC3F,MAAM,IAAI,CAAC,IAAI,CAAC;AAClB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@procedures/server",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.12.1",
|
|
5
5
|
"description": "A standalone procedure server: load procedure packages and serve them over HTTP and WebSocket with a token and an expose list. Its procedures server.start, server.stop and server.status manage the background server of the mark CLI.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"server",
|
|
@@ -60,13 +60,14 @@
|
|
|
60
60
|
"provenance": true
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@
|
|
64
|
-
"@procedures/
|
|
63
|
+
"@mark1russell7/service": "^0.5.2",
|
|
64
|
+
"@procedures/client": "0.12.1",
|
|
65
|
+
"@procedures/peer": "0.12.1",
|
|
65
66
|
"zod": "^4.6.5"
|
|
66
67
|
},
|
|
67
68
|
"devDependencies": {
|
|
68
69
|
"@mark1russell7/cue": "^1.0.0",
|
|
69
|
-
"@procedures/fs": "0.
|
|
70
|
+
"@procedures/fs": "0.12.1",
|
|
70
71
|
"@types/node": "^22.0.0",
|
|
71
72
|
"typescript": "^7.0.2",
|
|
72
73
|
"vitest": "^5.0.3"
|
package/src/host.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runner entry of the procedures host (CLI-8, decisions D2, D6, D7 and D17).
|
|
3
|
+
*
|
|
4
|
+
* `runProcedureHost(config)` is the only entry that starts `run()` of `@mark1russell7/service` for
|
|
5
|
+
* `procedure-server`, `mark serve` and `mark --server`. It declares the parts of
|
|
6
|
+
* `createProcedureHost()` of `@procedures/peer` in one service. The runner owns the signals, the
|
|
7
|
+
* stop in stages and the exit. Thus the entry installs no signal handler and no hard-exit timer.
|
|
8
|
+
*
|
|
9
|
+
* - The profile: `localDev` for a run in the foreground, where a second Ctrl-C exits at once, and
|
|
10
|
+
* `daemon` for the background host of `mark`, where a repeat signal has no effect (D6, D7).
|
|
11
|
+
* - The caps of the stages sum to 10 s. They replace the hard-exit timer of 10 s of the entries.
|
|
12
|
+
* - No check gates readiness or liveness, so the host is ready from the end of its startup.
|
|
13
|
+
* - The lockfile is a dependency: its connect writes it before the listeners start, and its close
|
|
14
|
+
* removes it after the listeners close.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { daemon, localDev, service, type Lifecycle, type Profile, type RunOptions, type ServiceBuilder } from "@mark1russell7/service";
|
|
18
|
+
import { seconds } from "@procedures/client";
|
|
19
|
+
import { createProcedureHost, type ProcedureHost, type ProcedureHostOptions } from "@procedures/peer";
|
|
20
|
+
import { lockfileHandle, type LockfileData } from "@procedures/peer/lockfile";
|
|
21
|
+
|
|
22
|
+
/** The mode of a run: in the foreground of a terminal, or as the background host of `mark`. */
|
|
23
|
+
export type HostRunMode = "foreground" | "background";
|
|
24
|
+
|
|
25
|
+
/** The profile of each mode, as data: `localDev` in the foreground, and `daemon` in the background. */
|
|
26
|
+
export const HOST_PROFILES: Readonly<Record<HostRunMode, Profile>> = Object.freeze({ foreground: localDev, background: daemon });
|
|
27
|
+
|
|
28
|
+
/** The configuration of `runProcedureHost()`. */
|
|
29
|
+
export interface ProcedureHostRunConfig {
|
|
30
|
+
/** The name of the service of the process. */
|
|
31
|
+
readonly name: string;
|
|
32
|
+
/** The options of the host: the registry, the policy, the faces, the listeners and the collections. */
|
|
33
|
+
readonly host: ProcedureHostOptions;
|
|
34
|
+
readonly mode: HostRunMode;
|
|
35
|
+
/** A profile in place of the profile of the mode. The caller can change a field of it with a spread. */
|
|
36
|
+
readonly profile?: Profile | undefined;
|
|
37
|
+
/** The lockfile of the host, for `mark --server`. */
|
|
38
|
+
readonly lockfile?: LockfileData | undefined;
|
|
39
|
+
/** This function prints the lines of the run, for example at the start of the shutdown. */
|
|
40
|
+
readonly log?: ((line: string) => void) | undefined;
|
|
41
|
+
/** The options of `run()`: a process port and a clock, for a test. The host gets the same clock. */
|
|
42
|
+
readonly run?: RunOptions | undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** A host that runs under `run()`: the host, the service of the process and its lifecycle. */
|
|
46
|
+
export interface RunningHost {
|
|
47
|
+
readonly host: ProcedureHost;
|
|
48
|
+
readonly service: ServiceBuilder;
|
|
49
|
+
/** The lifecycle. Its state is `running` after a startup that ended, and `draining` or `exited` after a startup that failed. */
|
|
50
|
+
readonly life: Lifecycle;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* This function declares the service of a procedures host and starts `run()`. It gives the host
|
|
55
|
+
* when the startup ends. After a startup that failed, `life.errors` tells why, and the process
|
|
56
|
+
* exits with the code 1 after the shutdown.
|
|
57
|
+
*/
|
|
58
|
+
export async function runProcedureHost(config: ProcedureHostRunConfig): Promise<RunningHost> {
|
|
59
|
+
const clock = config.run?.clock;
|
|
60
|
+
const host = createProcedureHost({ ...config.host, ...(clock ? { clock } : {}) });
|
|
61
|
+
const profile = config.profile ?? HOST_PROFILES[config.mode];
|
|
62
|
+
const svc = service(config.name).profile(profile);
|
|
63
|
+
// The profiles of the computer of a developer leave the policies to the service. No check gates them.
|
|
64
|
+
if (!profile.readiness) svc.readiness({ type: "debounce", interval: seconds(5), failAfter: 3, recoverAfter: 1 });
|
|
65
|
+
if (!profile.liveness) svc.liveness({ type: "window", failAfter: seconds(45) });
|
|
66
|
+
if (!profile.startup) svc.startup(seconds(30));
|
|
67
|
+
// A repeat signal: an exit at once in the foreground, no effect in the background (D6)
|
|
68
|
+
svc.onRepeatSignal(profile.onRepeatSignal ?? (config.mode === "foreground" ? "exit" : "ignore"));
|
|
69
|
+
host.declare(svc);
|
|
70
|
+
// The lockfile: after the storages it connects, and before them it closes
|
|
71
|
+
if (config.lockfile) svc.dependency("lockfile", { system: null, knobs: {}, operations: {} }, lockfileHandle(config.lockfile));
|
|
72
|
+
const log = config.log;
|
|
73
|
+
if (log && profile.phases?.some((phase) => phase.name === "stop intake")) svc.onPhase("stop intake", () => log("\nShutting down..."));
|
|
74
|
+
const life = await svc.run(config.run);
|
|
75
|
+
return { host, service: svc, life };
|
|
76
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* @procedures/server
|
|
3
3
|
*
|
|
4
4
|
* General procedure server - run any procedure packages via HTTP/WebSocket. Importing this entry
|
|
5
|
-
* starts nothing: `runServer(argv)` is the CLI (`server` and `mark serve`),
|
|
6
|
-
* starts a server
|
|
5
|
+
* starts nothing: `runServer(argv)` is the CLI (`server` and `mark serve`), `runProcedureHost()`
|
|
6
|
+
* runs a procedures host under `run()`, and `startServer()` starts a server outside a service.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
export { parseConfig, parseTopicPatterns } from "./config.js";
|
|
10
10
|
export { runServer, startServer, loadProcedureModule, type RunningServer, type ServerRunOptions } from "./run.js";
|
|
11
|
+
// The runner entry of the procedures host (CLI-8): the only entry that starts run()
|
|
12
|
+
export { runProcedureHost, HOST_PROFILES, type ProcedureHostRunConfig, type RunningHost, type HostRunMode } from "./host.js";
|
|
11
13
|
export type {
|
|
12
14
|
ServerConfig,
|
|
13
15
|
TransportConfig,
|