@effectionx/process 0.5.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.
Files changed (58) hide show
  1. package/README.md +12 -0
  2. package/esm/mod.d.ts +3 -0
  3. package/esm/mod.d.ts.map +1 -0
  4. package/esm/mod.js +2 -0
  5. package/esm/package.json +3 -0
  6. package/esm/src/daemon.d.ts +11 -0
  7. package/esm/src/daemon.d.ts.map +1 -0
  8. package/esm/src/daemon.js +20 -0
  9. package/esm/src/eventemitter.d.ts +22 -0
  10. package/esm/src/eventemitter.d.ts.map +1 -0
  11. package/esm/src/eventemitter.js +40 -0
  12. package/esm/src/exec/api.d.ts +70 -0
  13. package/esm/src/exec/api.d.ts.map +1 -0
  14. package/esm/src/exec/api.js +1 -0
  15. package/esm/src/exec/error.d.ts +14 -0
  16. package/esm/src/exec/error.d.ts.map +1 -0
  17. package/esm/src/exec/error.js +54 -0
  18. package/esm/src/exec/posix.d.ts +3 -0
  19. package/esm/src/exec/posix.d.ts.map +1 -0
  20. package/esm/src/exec/posix.js +110 -0
  21. package/esm/src/exec/win32.d.ts +4 -0
  22. package/esm/src/exec/win32.d.ts.map +1 -0
  23. package/esm/src/exec/win32.js +173 -0
  24. package/esm/src/exec.d.ts +16 -0
  25. package/esm/src/exec.d.ts.map +1 -0
  26. package/esm/src/exec.js +75 -0
  27. package/esm/src/helpers.d.ts +12 -0
  28. package/esm/src/helpers.d.ts.map +1 -0
  29. package/esm/src/helpers.js +71 -0
  30. package/package.json +34 -0
  31. package/script/mod.d.ts +3 -0
  32. package/script/mod.d.ts.map +1 -0
  33. package/script/mod.js +20 -0
  34. package/script/package.json +3 -0
  35. package/script/src/daemon.d.ts +11 -0
  36. package/script/src/daemon.d.ts.map +1 -0
  37. package/script/src/daemon.js +23 -0
  38. package/script/src/eventemitter.d.ts +22 -0
  39. package/script/src/eventemitter.d.ts.map +1 -0
  40. package/script/src/eventemitter.js +44 -0
  41. package/script/src/exec/api.d.ts +70 -0
  42. package/script/src/exec/api.d.ts.map +1 -0
  43. package/script/src/exec/api.js +2 -0
  44. package/script/src/exec/error.d.ts +14 -0
  45. package/script/src/exec/error.d.ts.map +1 -0
  46. package/script/src/exec/error.js +59 -0
  47. package/script/src/exec/posix.d.ts +3 -0
  48. package/script/src/exec/posix.d.ts.map +1 -0
  49. package/script/src/exec/posix.js +117 -0
  50. package/script/src/exec/win32.d.ts +4 -0
  51. package/script/src/exec/win32.d.ts.map +1 -0
  52. package/script/src/exec/win32.js +178 -0
  53. package/script/src/exec.d.ts +16 -0
  54. package/script/src/exec.d.ts.map +1 -0
  55. package/script/src/exec.js +92 -0
  56. package/script/src/helpers.d.ts +12 -0
  57. package/script/src/helpers.d.ts.map +1 -0
  58. package/script/src/helpers.js +76 -0
@@ -0,0 +1,75 @@
1
+ import { split } from "shellwords";
2
+ import { spawn } from "effection";
3
+ import { createPosixProcess } from "./exec/posix.js";
4
+ import { createWin32Process, isWin32 } from "./exec/win32.js";
5
+ export * from "./exec/api.js";
6
+ export * from "./exec/error.js";
7
+ const createProcess = (cmd, opts) => {
8
+ if (isWin32()) {
9
+ return createWin32Process(cmd, opts);
10
+ }
11
+ else {
12
+ return createPosixProcess(cmd, opts);
13
+ }
14
+ };
15
+ /**
16
+ * Execute `command` with `options`. You should use this operation for processes
17
+ * that have a finite lifetime and on which you may wish to synchronize on the
18
+ * exit status. If you want to start a process like a server that spins up and runs
19
+ * forever, consider using `daemon()`
20
+ */
21
+ export function exec(command, options = {}) {
22
+ let [cmd, ...args] = options.shell ? [command] : split(command);
23
+ let opts = { ...options, arguments: args.concat(options.arguments || []) };
24
+ return {
25
+ *[Symbol.iterator]() {
26
+ return yield* createProcess(cmd, opts);
27
+ },
28
+ *join() {
29
+ const process = yield* createProcess(cmd, opts);
30
+ let stdout = "";
31
+ let stderr = "";
32
+ yield* spawn(function* () {
33
+ let subscription = yield* process.stdout;
34
+ let next = yield* subscription.next();
35
+ while (!next.done) {
36
+ stdout += next.value;
37
+ next = yield* subscription.next();
38
+ }
39
+ });
40
+ yield* spawn(function* () {
41
+ let subscription = yield* process.stderr;
42
+ let next = yield* subscription.next();
43
+ while (!next.done) {
44
+ stderr += next.value;
45
+ next = yield* subscription.next();
46
+ }
47
+ });
48
+ let status = yield* process.join();
49
+ return { ...status, stdout, stderr };
50
+ },
51
+ *expect() {
52
+ const process = yield* createProcess(cmd, opts);
53
+ let stdout = "";
54
+ let stderr = "";
55
+ yield* spawn(function* () {
56
+ let subscription = yield* process.stdout;
57
+ let next = yield* subscription.next();
58
+ while (!next.done) {
59
+ stdout += next.value;
60
+ next = yield* subscription.next();
61
+ }
62
+ });
63
+ yield* spawn(function* () {
64
+ let subscription = yield* process.stderr;
65
+ let next = yield* subscription.next();
66
+ while (!next.done) {
67
+ stderr += next.value;
68
+ next = yield* subscription.next();
69
+ }
70
+ });
71
+ let status = yield* process.expect();
72
+ return { ...status, stdout, stderr };
73
+ },
74
+ };
75
+ }
@@ -0,0 +1,12 @@
1
+ import { type Operation, type Result, type Stream } from "effection";
2
+ import type { Readable } from "node:stream";
3
+ export type OutputStream = Stream<Uint8Array, void>;
4
+ export declare function useReadable(target: Readable | null): Stream<Uint8Array, void>;
5
+ interface Remainder<T> {
6
+ remainder: string;
7
+ result: T;
8
+ }
9
+ export declare function lines(): <T extends Uint8Array, TReturn>(stream: Stream<T, TReturn>) => Stream<string, Remainder<TReturn>>;
10
+ export declare function box<T>(op: () => Operation<T>): Operation<Result<T>>;
11
+ export {};
12
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,SAAS,EAEd,KAAK,MAAM,EACX,KAAK,MAAM,EACZ,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAEpD,wBAAgB,WAAW,CACzB,MAAM,EAAE,QAAQ,GAAG,IAAI,GACtB,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,CAoB1B;AAED,UAAU,SAAS,CAAC,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,CAAC,CAAC;CACX;AAED,wBAAgB,KAAK,IAAI,CAAC,CAAC,SAAS,UAAU,EAAE,OAAO,EACrD,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,KACvB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAyCtC;AAED,wBAAiB,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAOpE"}
@@ -0,0 +1,71 @@
1
+ import { createSignal, Err, Ok, resource, } from "effection";
2
+ export function useReadable(target) {
3
+ return resource(function* (provide) {
4
+ let signal = createSignal();
5
+ let listener = (chunk) => {
6
+ signal.send(chunk);
7
+ };
8
+ target?.on("data", listener);
9
+ target?.on("end", signal.close);
10
+ try {
11
+ yield* provide(yield* signal);
12
+ }
13
+ finally {
14
+ target?.off("data", listener);
15
+ target?.off("end", signal.close);
16
+ signal.close();
17
+ }
18
+ });
19
+ }
20
+ export function lines() {
21
+ const decoder = new TextDecoder();
22
+ return function (stream) {
23
+ return {
24
+ *[Symbol.iterator]() {
25
+ let subscription = yield* stream;
26
+ let buffer = [];
27
+ let remainder = "";
28
+ return {
29
+ *next() {
30
+ while (buffer.length === 0) {
31
+ let next = yield* subscription.next();
32
+ if (next.done) {
33
+ return {
34
+ done: true,
35
+ value: {
36
+ remainder,
37
+ result: next.value,
38
+ },
39
+ };
40
+ }
41
+ else {
42
+ let current = remainder + decoder.decode(next.value);
43
+ let lines = current.split("\n");
44
+ if (lines.length > 0) {
45
+ buffer.push(...lines.slice(0, -1));
46
+ remainder = lines.slice(-1)[0];
47
+ }
48
+ else {
49
+ remainder = current;
50
+ }
51
+ }
52
+ }
53
+ return {
54
+ done: false,
55
+ value: buffer.pop(),
56
+ };
57
+ },
58
+ };
59
+ },
60
+ };
61
+ };
62
+ }
63
+ export function* box(op) {
64
+ try {
65
+ let value = yield* op();
66
+ return Ok(value);
67
+ }
68
+ catch (e) {
69
+ return Err(e);
70
+ }
71
+ }
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@effectionx/process",
3
+ "version": "0.5.0",
4
+ "author": "engineering@frontside.com",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/thefrontside/effectionx.git"
8
+ },
9
+ "license": "MIT",
10
+ "bugs": {
11
+ "url": "https://github.com/thefrontside/effectionx/issues"
12
+ },
13
+ "main": "./script/mod.js",
14
+ "module": "./esm/mod.js",
15
+ "exports": {
16
+ ".": {
17
+ "import": "./esm/mod.js",
18
+ "require": "./script/mod.js"
19
+ }
20
+ },
21
+ "scripts": {},
22
+ "engines": {
23
+ "node": ">= 16"
24
+ },
25
+ "sideEffects": false,
26
+ "dependencies": {
27
+ "@types/cross-spawn": "6.0.6",
28
+ "cross-spawn": "7.0.6",
29
+ "ctrlc-windows": "2.2.0",
30
+ "effection": "^3",
31
+ "shellwords": "^1.1.1"
32
+ },
33
+ "_generatedBy": "dnt@dev"
34
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./src/exec.js";
2
+ export { type Daemon, daemon } from "./src/daemon.js";
3
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC"}
package/script/mod.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.daemon = void 0;
18
+ __exportStar(require("./src/exec.js"), exports);
19
+ var daemon_js_1 = require("./src/daemon.js");
20
+ Object.defineProperty(exports, "daemon", { enumerable: true, get: function () { return daemon_js_1.daemon; } });
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,11 @@
1
+ import { type Operation } from "effection";
2
+ import { type ExecOptions, type Process } from "./exec.js";
3
+ export interface Daemon extends Operation<void>, Process {
4
+ }
5
+ /**
6
+ * Start a long-running process, like a web server that run perpetually.
7
+ * Daemon operations are expected to run forever, and if they exit pre-maturely
8
+ * before the operation containing them passes out of scope it raises an error.
9
+ */
10
+ export declare function daemon(command: string, options?: ExecOptions): Operation<Daemon>;
11
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/src/daemon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,WAAW,CAAC;AAErD,OAAO,EAGL,KAAK,WAAW,EAEhB,KAAK,OAAO,EACb,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,MAAO,SAAQ,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO;CACvD;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CACpB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,WAAgB,GACxB,SAAS,CAAC,MAAM,CAAC,CAanB"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.daemon = daemon;
4
+ const effection_1 = require("effection");
5
+ const exec_js_1 = require("./exec.js");
6
+ /**
7
+ * Start a long-running process, like a web server that run perpetually.
8
+ * Daemon operations are expected to run forever, and if they exit pre-maturely
9
+ * before the operation containing them passes out of scope it raises an error.
10
+ */
11
+ function daemon(command, options = {}) {
12
+ return (0, effection_1.resource)(function* (provide) {
13
+ // TODO: should we be able to terminate the process from here?
14
+ let process = yield* (0, exec_js_1.exec)(command, options);
15
+ yield* provide({
16
+ *[Symbol.iterator]() {
17
+ let status = yield* process.join();
18
+ throw new exec_js_1.DaemonExitError(status, command, options);
19
+ },
20
+ ...process,
21
+ });
22
+ });
23
+ }
@@ -0,0 +1,22 @@
1
+ import type { Operation, Stream } from "effection";
2
+ import type { EventEmitter } from "node:stream";
3
+ /**
4
+ * Create a {@link Stream} of events from any EventEmitter.
5
+ *
6
+ * See the guide on [Streams and Subscriptions](https://frontside.com/effection/docs/collections)
7
+ * for details on how to use streams.
8
+ *
9
+ * @param target - the event target whose events will be streamed
10
+ * @param name - the name of the event to stream. E.g. "click"
11
+ * @returns a stream that will see one item for each event
12
+ */
13
+ export declare function on<T extends unknown[]>(target: EventEmitter | null, eventName: string): Stream<T, never>;
14
+ /**
15
+ * Create an {@link Operation} that yields the next event to be emitted by an EventEmitter.
16
+ *
17
+ * @param target - the event target to be watched
18
+ * @param name - the name of the event to watch. E.g. "click"
19
+ * @returns an Operation that yields the next emitted event
20
+ */
21
+ export declare function once<TArgs extends unknown[] = unknown[]>(source: EventEmitter | null, eventName: string): Operation<TArgs>;
22
+ //# sourceMappingURL=eventemitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eventemitter.d.ts","sourceRoot":"","sources":["../../src/src/eventemitter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAgB,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;;;GASG;AACH,wBAAgB,EAAE,CAChB,CAAC,SAAS,OAAO,EAAE,EACnB,MAAM,EAAE,YAAY,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAkBlE;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,KAAK,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE,EACtD,MAAM,EAAE,YAAY,GAAG,IAAI,EAC3B,SAAS,EAAE,MAAM,GAChB,SAAS,CAAC,KAAK,CAAC,CAWlB"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.on = on;
4
+ exports.once = once;
5
+ const effection_1 = require("effection");
6
+ /**
7
+ * Create a {@link Stream} of events from any EventEmitter.
8
+ *
9
+ * See the guide on [Streams and Subscriptions](https://frontside.com/effection/docs/collections)
10
+ * for details on how to use streams.
11
+ *
12
+ * @param target - the event target whose events will be streamed
13
+ * @param name - the name of the event to stream. E.g. "click"
14
+ * @returns a stream that will see one item for each event
15
+ */
16
+ function on(target, eventName) {
17
+ return (0, effection_1.resource)(function* (provide) {
18
+ let signal = (0, effection_1.createSignal)();
19
+ let listener = (...args) => signal.send(args);
20
+ target?.on(eventName, listener);
21
+ try {
22
+ yield* provide(yield* signal);
23
+ }
24
+ finally {
25
+ target?.off(eventName, listener);
26
+ }
27
+ });
28
+ }
29
+ /**
30
+ * Create an {@link Operation} that yields the next event to be emitted by an EventEmitter.
31
+ *
32
+ * @param target - the event target to be watched
33
+ * @param name - the name of the event to watch. E.g. "click"
34
+ * @returns an Operation that yields the next emitted event
35
+ */
36
+ function once(source, eventName) {
37
+ const result = (0, effection_1.withResolvers)();
38
+ let listener = (...args) => {
39
+ result.resolve(args);
40
+ source?.off(eventName, listener);
41
+ };
42
+ source?.on(eventName, listener);
43
+ return result.operation;
44
+ }
@@ -0,0 +1,70 @@
1
+ import type { Operation } from "effection";
2
+ import type { OutputStream } from "../helpers.js";
3
+ export interface Writable<T> {
4
+ send(message: T): void;
5
+ }
6
+ /**
7
+ * The process type is what is returned by the `exec` operation. It has all of
8
+ * standard io handles, and methods for synchronizing on return.
9
+ */
10
+ export interface Process extends StdIO {
11
+ readonly pid: number;
12
+ /**
13
+ * Completes once the process has finished regardless of whether it was
14
+ * successful or not.
15
+ */
16
+ join(): Operation<ExitStatus>;
17
+ /**
18
+ * Completes once the process has finished successfully. If the process does
19
+ * not complete successfully, it will raise an ExecError.
20
+ */
21
+ expect(): Operation<ExitStatus>;
22
+ }
23
+ export interface ExecOptions {
24
+ /**
25
+ * When not using passing the `shell` option all arguments must be passed
26
+ * as an array.
27
+ */
28
+ arguments?: string[];
29
+ /**
30
+ * Map of environment variables to use for the process.
31
+ */
32
+ env?: Record<string, string>;
33
+ /**
34
+ * Create an intermediate shell process; defaults to `false`. Useful if you
35
+ * need to handle glob expansion or passing environment variables. A truthy value
36
+ * will use an intermediate shell to interpret the command using the default system shell.
37
+ * However, if the value is a string, that will be used as the executable path
38
+ * for the intermediate shell.
39
+ */
40
+ shell?: boolean | string;
41
+ /**
42
+ * Sets the working directory of the process
43
+ */
44
+ cwd?: string;
45
+ }
46
+ export interface StdIO {
47
+ stdout: OutputStream;
48
+ stderr: OutputStream;
49
+ stdin: Writable<string>;
50
+ }
51
+ export interface ExitStatus {
52
+ /**
53
+ * exit code
54
+ * //TODO: is this pertinent on Windows? Do we need an 'OK' flag
55
+ */
56
+ code?: number;
57
+ /**
58
+ * If the process exited with a signal instead of an exit code, it
59
+ * is recorded here.
60
+ */
61
+ signal?: string;
62
+ }
63
+ export interface ProcessResult extends ExitStatus {
64
+ stdout: string;
65
+ stderr: string;
66
+ }
67
+ export interface CreateOSProcess {
68
+ (command: string, options: ExecOptions): Operation<Process>;
69
+ }
70
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/src/exec/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,OAAQ,SAAQ,KAAK;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,IAAI,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC;IAE9B;;;OAGG;IACH,MAAM,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAEzB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,eAAe;IAC9B,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;CAC7D"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,14 @@
1
+ import type { ExecOptions, ExitStatus } from "./api.js";
2
+ export declare class ExecError extends Error {
3
+ status: ExitStatus;
4
+ command: string;
5
+ options: ExecOptions;
6
+ constructor(status: ExitStatus, command: string, options: ExecOptions);
7
+ name: string;
8
+ get message(): string;
9
+ }
10
+ export declare class DaemonExitError extends ExecError {
11
+ name: string;
12
+ get message(): string;
13
+ }
14
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../src/src/exec/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAExD,qBAAa,SAAU,SAAQ,KAAK;IAEzB,MAAM,EAAE,UAAU;IAClB,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,WAAW;gBAFpB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,WAAW;IAKpB,IAAI,SAAe;IAE5B,IAAa,OAAO,IAAI,MAAM,CAgB7B;CACF;AAED,qBAAa,eAAgB,SAAQ,SAAS;IACnC,IAAI,SAAqB;IAElC,IAAa,OAAO,IAAI,MAAM,CAE7B;CACF"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DaemonExitError = exports.ExecError = void 0;
4
+ class ExecError extends Error {
5
+ constructor(status, command, options) {
6
+ super();
7
+ Object.defineProperty(this, "status", {
8
+ enumerable: true,
9
+ configurable: true,
10
+ writable: true,
11
+ value: status
12
+ });
13
+ Object.defineProperty(this, "command", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: command
18
+ });
19
+ Object.defineProperty(this, "options", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: options
24
+ });
25
+ Object.defineProperty(this, "name", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: "ExecError"
30
+ });
31
+ }
32
+ get message() {
33
+ let code = this.status.code ? `code: ${this.status.code}` : null;
34
+ let signal = this.status.signal ? `signal: ${this.status.signal}` : null;
35
+ let env = `env: ${JSON.stringify(this.options.env || {})}`;
36
+ let shell = this.options.shell ? `shell: ${this.options.shell}` : null;
37
+ let cwd = this.options.cwd ? `cwd: ${this.options.cwd}` : null;
38
+ let command = `$ ${this.command} ${this.options.arguments?.join(" ")}`
39
+ .trim();
40
+ return [code, signal, env, shell, cwd, command].filter((item) => !!item)
41
+ .join("\n");
42
+ }
43
+ }
44
+ exports.ExecError = ExecError;
45
+ class DaemonExitError extends ExecError {
46
+ constructor() {
47
+ super(...arguments);
48
+ Object.defineProperty(this, "name", {
49
+ enumerable: true,
50
+ configurable: true,
51
+ writable: true,
52
+ value: "DaemonExitError"
53
+ });
54
+ }
55
+ get message() {
56
+ return `daemon process quit unexpectedly\n${super.message}`;
57
+ }
58
+ }
59
+ exports.DaemonExitError = DaemonExitError;
@@ -0,0 +1,3 @@
1
+ import type { CreateOSProcess } from "./api.js";
2
+ export declare const createPosixProcess: CreateOSProcess;
3
+ //# sourceMappingURL=posix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"posix.d.ts","sourceRoot":"","sources":["../../../src/src/exec/posix.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAwB,MAAM,UAAU,CAAC;AAKtE,eAAO,MAAM,kBAAkB,EAAE,eAkHhC,CAAC"}
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createPosixProcess = void 0;
7
+ const node_child_process_1 = require("node:child_process");
8
+ const effection_1 = require("effection");
9
+ const node_process_1 = __importDefault(require("node:process"));
10
+ const eventemitter_js_1 = require("../eventemitter.js");
11
+ const helpers_js_1 = require("../helpers.js");
12
+ const error_js_1 = require("./error.js");
13
+ const createPosixProcess = function* createPosixProcess(command, options) {
14
+ let processResult = (0, effection_1.withResolvers)();
15
+ // Killing all child processes started by this command is surprisingly
16
+ // tricky. If a process spawns another processes and we kill the parent,
17
+ // then the child process is NOT automatically killed. Instead we're using
18
+ // the `detached` option to force the child into its own process group,
19
+ // which all of its children in turn will inherit. By sending the signal to
20
+ // `-pid` rather than `pid`, we are sending it to the entire process group
21
+ // instead. This will send the signal to all processes started by the child
22
+ // process.
23
+ //
24
+ // More information here: https://unix.stackexchange.com/questions/14815/process-descendants
25
+ let childProcess = (0, node_child_process_1.spawn)(command, options.arguments || [], {
26
+ detached: true,
27
+ shell: options.shell,
28
+ env: options.env,
29
+ cwd: options.cwd,
30
+ stdio: "pipe",
31
+ });
32
+ let { pid } = childProcess;
33
+ let io = {
34
+ stdout: yield* (0, helpers_js_1.useReadable)(childProcess.stdout),
35
+ stderr: yield* (0, helpers_js_1.useReadable)(childProcess.stderr),
36
+ stdoutDone: (0, effection_1.withResolvers)(),
37
+ stderrDone: (0, effection_1.withResolvers)(),
38
+ };
39
+ let stdout = (0, effection_1.createSignal)();
40
+ let stderr = (0, effection_1.createSignal)();
41
+ yield* (0, effection_1.spawn)(function* () {
42
+ let next = yield* io.stdout.next();
43
+ while (!next.done) {
44
+ stdout.send(next.value);
45
+ next = yield* io.stdout.next();
46
+ }
47
+ stdout.close();
48
+ io.stdoutDone.resolve();
49
+ });
50
+ yield* (0, effection_1.spawn)(function* () {
51
+ let next = yield* io.stderr.next();
52
+ while (!next.done) {
53
+ stderr.send(next.value);
54
+ next = yield* io.stderr.next();
55
+ }
56
+ stderr.close();
57
+ io.stderrDone.resolve();
58
+ });
59
+ yield* (0, effection_1.spawn)(function* trapError() {
60
+ let [error] = yield* (0, eventemitter_js_1.once)(childProcess, "error");
61
+ processResult.resolve((0, effection_1.Err)(error));
62
+ });
63
+ let stdin = {
64
+ send(data) {
65
+ childProcess.stdin.write(data);
66
+ },
67
+ };
68
+ yield* (0, effection_1.spawn)(function* () {
69
+ try {
70
+ let value = yield* (0, eventemitter_js_1.once)(childProcess, "close");
71
+ yield* (0, effection_1.all)([io.stdoutDone.operation, io.stderrDone.operation]);
72
+ processResult.resolve((0, effection_1.Ok)(value));
73
+ }
74
+ finally {
75
+ try {
76
+ if (typeof childProcess.pid === "undefined") {
77
+ // deno-lint-ignore no-unsafe-finally
78
+ throw new Error("no pid for childProcess");
79
+ }
80
+ node_process_1.default.kill(-childProcess.pid, "SIGTERM");
81
+ yield* (0, effection_1.all)([io.stdoutDone.operation, io.stderrDone.operation]);
82
+ }
83
+ catch (_e) {
84
+ // do nothing, process is probably already dead
85
+ }
86
+ }
87
+ });
88
+ function* join() {
89
+ let result = yield* processResult.operation;
90
+ if (result.ok) {
91
+ let [code, signal] = result.value;
92
+ return { command, options, code, signal };
93
+ }
94
+ else {
95
+ throw result.error;
96
+ }
97
+ }
98
+ function* expect() {
99
+ let status = yield* join();
100
+ if (status.code != 0) {
101
+ throw new error_js_1.ExecError(status, command, options);
102
+ }
103
+ else {
104
+ return status;
105
+ }
106
+ }
107
+ // FYI: this function starts a process and returns without blocking
108
+ return {
109
+ pid: pid,
110
+ stdin,
111
+ stdout,
112
+ stderr,
113
+ join,
114
+ expect,
115
+ };
116
+ };
117
+ exports.createPosixProcess = createPosixProcess;
@@ -0,0 +1,4 @@
1
+ import type { CreateOSProcess } from "./api.js";
2
+ export declare const createWin32Process: CreateOSProcess;
3
+ export declare const isWin32: () => boolean;
4
+ //# sourceMappingURL=win32.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"win32.d.ts","sourceRoot":"","sources":["../../../src/src/exec/win32.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,eAAe,EAAwB,MAAM,UAAU,CAAC;AAkBtE,eAAO,MAAM,kBAAkB,EAAE,eA8KhC,CAAC;AAEF,eAAO,MAAM,OAAO,QAAO,OAAiC,CAAC"}