@effect/platform-node-shared 0.45.0 → 0.46.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.
@@ -7,92 +7,81 @@ exports.make = exports.layer = void 0;
7
7
  var Error = _interopRequireWildcard(require("@effect/platform/Error"));
8
8
  var Terminal = _interopRequireWildcard(require("@effect/platform/Terminal"));
9
9
  var Effect = _interopRequireWildcard(require("effect/Effect"));
10
+ var Exit = _interopRequireWildcard(require("effect/Exit"));
10
11
  var Layer = _interopRequireWildcard(require("effect/Layer"));
12
+ var Mailbox = _interopRequireWildcard(require("effect/Mailbox"));
11
13
  var Option = _interopRequireWildcard(require("effect/Option"));
14
+ var RcRef = _interopRequireWildcard(require("effect/RcRef"));
12
15
  var readline = _interopRequireWildcard(require("node:readline"));
13
16
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
14
17
  const defaultShouldQuit = input => input.key.ctrl && (input.key.name === "c" || input.key.name === "d");
15
18
  /** @internal */
16
- const make = (shouldQuit = defaultShouldQuit) => Effect.gen(function* () {
17
- const input = yield* Effect.sync(() => globalThis.process.stdin);
18
- const output = yield* Effect.sync(() => globalThis.process.stdout);
19
- // Acquire a readline interface
20
- const acquireReadlineInterface = Effect.sync(() => readline.createInterface({
21
- input,
22
- escapeCodeTimeout: 50
23
- }));
24
- // Uses the readline interface to force `stdin` to emit keypress events
25
- const emitKeypressEvents = rl => {
26
- readline.emitKeypressEvents(input, rl);
27
- if (input.isTTY) {
28
- input.setRawMode(true);
29
- }
30
- return rl;
31
- };
32
- // Close the `readline` interface
33
- const releaseReadlineInterface = rl => Effect.sync(() => {
34
- if (input.isTTY) {
35
- input.setRawMode(false);
36
- }
37
- rl.close();
19
+ const make = exports.make = /*#__PURE__*/Effect.fnUntraced(function* (shouldQuit = defaultShouldQuit) {
20
+ const stdin = process.stdin;
21
+ const stdout = process.stdout;
22
+ // Acquire readline interface with TTY setup/cleanup inside the scope
23
+ const rlRef = yield* RcRef.make({
24
+ acquire: Effect.acquireRelease(Effect.sync(() => {
25
+ const rl = readline.createInterface({
26
+ input: stdin,
27
+ escapeCodeTimeout: 50
28
+ });
29
+ readline.emitKeypressEvents(stdin, rl);
30
+ if (stdin.isTTY) {
31
+ stdin.setRawMode(true);
32
+ }
33
+ return rl;
34
+ }), rl => Effect.sync(() => {
35
+ if (stdin.isTTY) {
36
+ stdin.setRawMode(false);
37
+ }
38
+ rl.close();
39
+ }))
38
40
  });
39
- // Handle the `"keypress"` event emitted by `stdin` (forced by readline)
40
- const handleKeypressEvent = input => Effect.async(resume => {
41
- const handleKeypress = (input, key) => {
41
+ const columns = Effect.sync(() => stdout.columns ?? 0);
42
+ const readInput = Effect.gen(function* () {
43
+ yield* RcRef.get(rlRef);
44
+ const mailbox = yield* Mailbox.make();
45
+ const handleKeypress = (s, k) => {
42
46
  const userInput = {
43
- input: Option.fromNullable(input),
47
+ input: Option.fromNullable(s),
44
48
  key: {
45
- name: key.name || "",
46
- ctrl: key.ctrl || false,
47
- meta: key.meta || false,
48
- shift: key.shift || false
49
+ name: k.name ?? "",
50
+ ctrl: !!k.ctrl,
51
+ meta: !!k.meta,
52
+ shift: !!k.shift
49
53
  }
50
54
  };
51
55
  if (shouldQuit(userInput)) {
52
- resume(Effect.fail(new Terminal.QuitException()));
56
+ mailbox.unsafeDone(Exit.void);
53
57
  } else {
54
- resume(Effect.succeed(userInput));
58
+ mailbox.unsafeOffer(userInput);
55
59
  }
56
60
  };
57
- input.once("keypress", handleKeypress);
58
- return Effect.sync(() => {
59
- input.removeListener("keypress", handleKeypress);
60
- });
61
+ yield* Effect.addFinalizer(() => Effect.sync(() => stdin.off("keypress", handleKeypress)));
62
+ stdin.on("keypress", handleKeypress);
63
+ return mailbox;
61
64
  });
62
- // Handle the `"line"` event emitted by the readline interface
63
- const handleLineEvent = rl => Effect.async(resume => {
64
- const handleLine = line => {
65
- resume(Effect.succeed(line));
66
- };
67
- rl.on("line", handleLine);
68
- return Effect.sync(() => {
69
- rl.removeListener("line", handleLine);
70
- });
71
- });
72
- const readInput = Effect.acquireUseRelease(acquireReadlineInterface.pipe(Effect.map(emitKeypressEvents)), () => handleKeypressEvent(input), releaseReadlineInterface);
73
- const readLine = Effect.acquireUseRelease(acquireReadlineInterface, rl => handleLineEvent(rl), releaseReadlineInterface);
65
+ const readLine = RcRef.get(rlRef).pipe(Effect.flatMap(readlineInterface => Effect.async(resume => {
66
+ const onLine = line => resume(Effect.succeed(line));
67
+ readlineInterface.once("line", onLine);
68
+ return Effect.sync(() => readlineInterface.off("line", onLine));
69
+ })), Effect.scoped);
74
70
  const display = prompt => Effect.uninterruptible(Effect.async(resume => {
75
- output.write(prompt, err => {
76
- if (err) {
77
- resume(Effect.fail(new Error.BadArgument({
78
- module: "Terminal",
79
- method: "display",
80
- description: "Failed to write prompt to output",
81
- cause: err
82
- })));
83
- }
84
- resume(Effect.void);
85
- });
71
+ stdout.write(prompt, err => err ? resume(Effect.fail(new Error.BadArgument({
72
+ module: "Terminal",
73
+ method: "display",
74
+ description: "Failed to write prompt to stdout",
75
+ cause: err
76
+ }))) : resume(Effect.void));
86
77
  }));
87
78
  return Terminal.Terminal.of({
88
- // The columns property can be undefined if stdout was redirected
89
- columns: Effect.sync(() => output.columns || 0),
79
+ columns,
90
80
  readInput,
91
81
  readLine,
92
82
  display
93
83
  });
94
84
  });
95
85
  /** @internal */
96
- exports.make = make;
97
86
  const layer = exports.layer = /*#__PURE__*/Layer.scoped(Terminal.Terminal, /*#__PURE__*/make(defaultShouldQuit));
98
87
  //# sourceMappingURL=terminal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"terminal.js","names":["Error","_interopRequireWildcard","require","Terminal","Effect","Layer","Option","readline","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","defaultShouldQuit","input","key","ctrl","name","make","shouldQuit","gen","sync","globalThis","process","stdin","output","stdout","acquireReadlineInterface","createInterface","escapeCodeTimeout","emitKeypressEvents","rl","isTTY","setRawMode","releaseReadlineInterface","close","handleKeypressEvent","async","resume","handleKeypress","userInput","fromNullable","meta","shift","fail","QuitException","succeed","once","removeListener","handleLineEvent","handleLine","line","on","readInput","acquireUseRelease","pipe","map","readLine","display","prompt","uninterruptible","write","err","BadArgument","module","method","description","cause","void","of","columns","exports","layer","scoped"],"sources":["../../../src/internal/terminal.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"terminal.js","names":["Error","_interopRequireWildcard","require","Terminal","Effect","Exit","Layer","Mailbox","Option","RcRef","readline","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","defaultShouldQuit","input","key","ctrl","name","make","exports","fnUntraced","shouldQuit","stdin","process","stdout","rlRef","acquire","acquireRelease","sync","rl","createInterface","escapeCodeTimeout","emitKeypressEvents","isTTY","setRawMode","close","columns","readInput","gen","mailbox","handleKeypress","s","k","userInput","fromNullable","meta","shift","unsafeDone","void","unsafeOffer","addFinalizer","off","on","readLine","pipe","flatMap","readlineInterface","async","resume","onLine","line","succeed","once","scoped","display","prompt","uninterruptible","write","err","fail","BadArgument","module","method","description","cause","of","layer"],"sources":["../../../src/internal/terminal.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -1,85 +1,75 @@
1
1
  import * as Error from "@effect/platform/Error";
2
2
  import * as Terminal from "@effect/platform/Terminal";
3
3
  import * as Effect from "effect/Effect";
4
+ import * as Exit from "effect/Exit";
4
5
  import * as Layer from "effect/Layer";
6
+ import * as Mailbox from "effect/Mailbox";
5
7
  import * as Option from "effect/Option";
8
+ import * as RcRef from "effect/RcRef";
6
9
  import * as readline from "node:readline";
7
10
  const defaultShouldQuit = input => input.key.ctrl && (input.key.name === "c" || input.key.name === "d");
8
11
  /** @internal */
9
- export const make = (shouldQuit = defaultShouldQuit) => Effect.gen(function* () {
10
- const input = yield* Effect.sync(() => globalThis.process.stdin);
11
- const output = yield* Effect.sync(() => globalThis.process.stdout);
12
- // Acquire a readline interface
13
- const acquireReadlineInterface = Effect.sync(() => readline.createInterface({
14
- input,
15
- escapeCodeTimeout: 50
16
- }));
17
- // Uses the readline interface to force `stdin` to emit keypress events
18
- const emitKeypressEvents = rl => {
19
- readline.emitKeypressEvents(input, rl);
20
- if (input.isTTY) {
21
- input.setRawMode(true);
22
- }
23
- return rl;
24
- };
25
- // Close the `readline` interface
26
- const releaseReadlineInterface = rl => Effect.sync(() => {
27
- if (input.isTTY) {
28
- input.setRawMode(false);
29
- }
30
- rl.close();
12
+ export const make = /*#__PURE__*/Effect.fnUntraced(function* (shouldQuit = defaultShouldQuit) {
13
+ const stdin = process.stdin;
14
+ const stdout = process.stdout;
15
+ // Acquire readline interface with TTY setup/cleanup inside the scope
16
+ const rlRef = yield* RcRef.make({
17
+ acquire: Effect.acquireRelease(Effect.sync(() => {
18
+ const rl = readline.createInterface({
19
+ input: stdin,
20
+ escapeCodeTimeout: 50
21
+ });
22
+ readline.emitKeypressEvents(stdin, rl);
23
+ if (stdin.isTTY) {
24
+ stdin.setRawMode(true);
25
+ }
26
+ return rl;
27
+ }), rl => Effect.sync(() => {
28
+ if (stdin.isTTY) {
29
+ stdin.setRawMode(false);
30
+ }
31
+ rl.close();
32
+ }))
31
33
  });
32
- // Handle the `"keypress"` event emitted by `stdin` (forced by readline)
33
- const handleKeypressEvent = input => Effect.async(resume => {
34
- const handleKeypress = (input, key) => {
34
+ const columns = Effect.sync(() => stdout.columns ?? 0);
35
+ const readInput = Effect.gen(function* () {
36
+ yield* RcRef.get(rlRef);
37
+ const mailbox = yield* Mailbox.make();
38
+ const handleKeypress = (s, k) => {
35
39
  const userInput = {
36
- input: Option.fromNullable(input),
40
+ input: Option.fromNullable(s),
37
41
  key: {
38
- name: key.name || "",
39
- ctrl: key.ctrl || false,
40
- meta: key.meta || false,
41
- shift: key.shift || false
42
+ name: k.name ?? "",
43
+ ctrl: !!k.ctrl,
44
+ meta: !!k.meta,
45
+ shift: !!k.shift
42
46
  }
43
47
  };
44
48
  if (shouldQuit(userInput)) {
45
- resume(Effect.fail(new Terminal.QuitException()));
49
+ mailbox.unsafeDone(Exit.void);
46
50
  } else {
47
- resume(Effect.succeed(userInput));
51
+ mailbox.unsafeOffer(userInput);
48
52
  }
49
53
  };
50
- input.once("keypress", handleKeypress);
51
- return Effect.sync(() => {
52
- input.removeListener("keypress", handleKeypress);
53
- });
54
+ yield* Effect.addFinalizer(() => Effect.sync(() => stdin.off("keypress", handleKeypress)));
55
+ stdin.on("keypress", handleKeypress);
56
+ return mailbox;
54
57
  });
55
- // Handle the `"line"` event emitted by the readline interface
56
- const handleLineEvent = rl => Effect.async(resume => {
57
- const handleLine = line => {
58
- resume(Effect.succeed(line));
59
- };
60
- rl.on("line", handleLine);
61
- return Effect.sync(() => {
62
- rl.removeListener("line", handleLine);
63
- });
64
- });
65
- const readInput = Effect.acquireUseRelease(acquireReadlineInterface.pipe(Effect.map(emitKeypressEvents)), () => handleKeypressEvent(input), releaseReadlineInterface);
66
- const readLine = Effect.acquireUseRelease(acquireReadlineInterface, rl => handleLineEvent(rl), releaseReadlineInterface);
58
+ const readLine = RcRef.get(rlRef).pipe(Effect.flatMap(readlineInterface => Effect.async(resume => {
59
+ const onLine = line => resume(Effect.succeed(line));
60
+ readlineInterface.once("line", onLine);
61
+ return Effect.sync(() => readlineInterface.off("line", onLine));
62
+ })), Effect.scoped);
67
63
  const display = prompt => Effect.uninterruptible(Effect.async(resume => {
68
- output.write(prompt, err => {
69
- if (err) {
70
- resume(Effect.fail(new Error.BadArgument({
71
- module: "Terminal",
72
- method: "display",
73
- description: "Failed to write prompt to output",
74
- cause: err
75
- })));
76
- }
77
- resume(Effect.void);
78
- });
64
+ stdout.write(prompt, err => err ? resume(Effect.fail(new Error.BadArgument({
65
+ module: "Terminal",
66
+ method: "display",
67
+ description: "Failed to write prompt to stdout",
68
+ cause: err
69
+ }))) : resume(Effect.void));
79
70
  }));
80
71
  return Terminal.Terminal.of({
81
- // The columns property can be undefined if stdout was redirected
82
- columns: Effect.sync(() => output.columns || 0),
72
+ columns,
83
73
  readInput,
84
74
  readLine,
85
75
  display
@@ -1 +1 @@
1
- {"version":3,"file":"terminal.js","names":["Error","Terminal","Effect","Layer","Option","readline","defaultShouldQuit","input","key","ctrl","name","make","shouldQuit","gen","sync","globalThis","process","stdin","output","stdout","acquireReadlineInterface","createInterface","escapeCodeTimeout","emitKeypressEvents","rl","isTTY","setRawMode","releaseReadlineInterface","close","handleKeypressEvent","async","resume","handleKeypress","userInput","fromNullable","meta","shift","fail","QuitException","succeed","once","removeListener","handleLineEvent","handleLine","line","on","readInput","acquireUseRelease","pipe","map","readLine","display","prompt","uninterruptible","write","err","BadArgument","module","method","description","cause","void","of","columns","layer","scoped"],"sources":["../../../src/internal/terminal.ts"],"sourcesContent":[null],"mappings":"AAAA,OAAO,KAAKA,KAAK,MAAM,wBAAwB;AAC/C,OAAO,KAAKC,QAAQ,MAAM,2BAA2B;AACrD,OAAO,KAAKC,MAAM,MAAM,eAAe;AACvC,OAAO,KAAKC,KAAK,MAAM,cAAc;AACrC,OAAO,KAAKC,MAAM,MAAM,eAAe;AACvC,OAAO,KAAKC,QAAQ,MAAM,eAAe;AAEzC,MAAMC,iBAAiB,GAAIC,KAAyB,IAClDA,KAAK,CAACC,GAAG,CAACC,IAAI,KAAKF,KAAK,CAACC,GAAG,CAACE,IAAI,KAAK,GAAG,IAAIH,KAAK,CAACC,GAAG,CAACE,IAAI,KAAK,GAAG,CAAC;AAEtE;AACA,OAAO,MAAMC,IAAI,GAAGA,CAClBC,UAAA,GAAqDN,iBAAiB,KAEtEJ,MAAM,CAACW,GAAG,CAAC,aAAS;EAClB,MAAMN,KAAK,GAAG,OAAOL,MAAM,CAACY,IAAI,CAAC,MAAMC,UAAU,CAACC,OAAO,CAACC,KAAK,CAAC;EAChE,MAAMC,MAAM,GAAG,OAAOhB,MAAM,CAACY,IAAI,CAAC,MAAMC,UAAU,CAACC,OAAO,CAACG,MAAM,CAAC;EAElE;EACA,MAAMC,wBAAwB,GAAGlB,MAAM,CAACY,IAAI,CAAC,MAC3CT,QAAQ,CAACgB,eAAe,CAAC;IACvBd,KAAK;IACLe,iBAAiB,EAAE;GACpB,CAAC,CACH;EAED;EACA,MAAMC,kBAAkB,GAAIC,EAAsB,IAAwB;IACxEnB,QAAQ,CAACkB,kBAAkB,CAAChB,KAAK,EAAEiB,EAAE,CAAC;IACtC,IAAIjB,KAAK,CAACkB,KAAK,EAAE;MACflB,KAAK,CAACmB,UAAU,CAAC,IAAI,CAAC;IACxB;IACA,OAAOF,EAAE;EACX,CAAC;EAED;EACA,MAAMG,wBAAwB,GAAIH,EAAsB,IACtDtB,MAAM,CAACY,IAAI,CAAC,MAAK;IACf,IAAIP,KAAK,CAACkB,KAAK,EAAE;MACflB,KAAK,CAACmB,UAAU,CAAC,KAAK,CAAC;IACzB;IACAF,EAAE,CAACI,KAAK,EAAE;EACZ,CAAC,CAAC;EAEJ;EACA,MAAMC,mBAAmB,GAAItB,KAAsC,IACjEL,MAAM,CAAC4B,KAAK,CAA8CC,MAAM,IAAI;IAClE,MAAMC,cAAc,GAAGA,CAACzB,KAAyB,EAAEC,GAAiB,KAAI;MACtE,MAAMyB,SAAS,GAAuB;QACpC1B,KAAK,EAAEH,MAAM,CAAC8B,YAAY,CAAC3B,KAAK,CAAC;QACjCC,GAAG,EAAE;UACHE,IAAI,EAAEF,GAAG,CAACE,IAAI,IAAI,EAAE;UACpBD,IAAI,EAAED,GAAG,CAACC,IAAI,IAAI,KAAK;UACvB0B,IAAI,EAAE3B,GAAG,CAAC2B,IAAI,IAAI,KAAK;UACvBC,KAAK,EAAE5B,GAAG,CAAC4B,KAAK,IAAI;;OAEvB;MACD,IAAIxB,UAAU,CAACqB,SAAS,CAAC,EAAE;QACzBF,MAAM,CAAC7B,MAAM,CAACmC,IAAI,CAAC,IAAIpC,QAAQ,CAACqC,aAAa,EAAE,CAAC,CAAC;MACnD,CAAC,MAAM;QACLP,MAAM,CAAC7B,MAAM,CAACqC,OAAO,CAACN,SAAS,CAAC,CAAC;MACnC;IACF,CAAC;IACD1B,KAAK,CAACiC,IAAI,CAAC,UAAU,EAAER,cAAc,CAAC;IACtC,OAAO9B,MAAM,CAACY,IAAI,CAAC,MAAK;MACtBP,KAAK,CAACkC,cAAc,CAAC,UAAU,EAAET,cAAc,CAAC;IAClD,CAAC,CAAC;EACJ,CAAC,CAAC;EAEJ;EACA,MAAMU,eAAe,GAAIlB,EAAsB,IAC7CtB,MAAM,CAAC4B,KAAK,CAAyCC,MAAM,IAAI;IAC7D,MAAMY,UAAU,GAAIC,IAAY,IAAI;MAClCb,MAAM,CAAC7B,MAAM,CAACqC,OAAO,CAACK,IAAI,CAAC,CAAC;IAC9B,CAAC;IACDpB,EAAE,CAACqB,EAAE,CAAC,MAAM,EAAEF,UAAU,CAAC;IACzB,OAAOzC,MAAM,CAACY,IAAI,CAAC,MAAK;MACtBU,EAAE,CAACiB,cAAc,CAAC,MAAM,EAAEE,UAAU,CAAC;IACvC,CAAC,CAAC;EACJ,CAAC,CAAC;EAEJ,MAAMG,SAAS,GAAG5C,MAAM,CAAC6C,iBAAiB,CACxC3B,wBAAwB,CAAC4B,IAAI,CAAC9C,MAAM,CAAC+C,GAAG,CAAC1B,kBAAkB,CAAC,CAAC,EAC7D,MAAMM,mBAAmB,CAACtB,KAAK,CAAC,EAChCoB,wBAAwB,CACzB;EAED,MAAMuB,QAAQ,GAAGhD,MAAM,CAAC6C,iBAAiB,CACvC3B,wBAAwB,EACvBI,EAAE,IAAKkB,eAAe,CAAClB,EAAE,CAAC,EAC3BG,wBAAwB,CACzB;EAED,MAAMwB,OAAO,GAAIC,MAAc,IAC7BlD,MAAM,CAACmD,eAAe,CACpBnD,MAAM,CAAC4B,KAAK,CAAEC,MAAM,IAAI;IACtBb,MAAM,CAACoC,KAAK,CAACF,MAAM,EAAGG,GAAG,IAAI;MAC3B,IAAIA,GAAG,EAAE;QACPxB,MAAM,CAAC7B,MAAM,CAACmC,IAAI,CAChB,IAAIrC,KAAK,CAACwD,WAAW,CAAC;UACpBC,MAAM,EAAE,UAAU;UAClBC,MAAM,EAAE,SAAS;UACjBC,WAAW,EAAE,kCAAkC;UAC/CC,KAAK,EAAEL;SACR,CAAC,CACH,CAAC;MACJ;MACAxB,MAAM,CAAC7B,MAAM,CAAC2D,IAAI,CAAC;IACrB,CAAC,CAAC;EACJ,CAAC,CAAC,CACH;EAEH,OAAO5D,QAAQ,CAACA,QAAQ,CAAC6D,EAAE,CAAC;IAC1B;IACAC,OAAO,EAAE7D,MAAM,CAACY,IAAI,CAAC,MAAMI,MAAM,CAAC6C,OAAO,IAAI,CAAC,CAAC;IAC/CjB,SAAS;IACTI,QAAQ;IACRC;GACD,CAAC;AACJ,CAAC,CAAC;AAEJ;AACA,OAAO,MAAMa,KAAK,gBAAmC7D,KAAK,CAAC8D,MAAM,CAC/DhE,QAAQ,CAACA,QAAQ,eACjBU,IAAI,CAACL,iBAAiB,CAAC,CACxB","ignoreList":[]}
1
+ {"version":3,"file":"terminal.js","names":["Error","Terminal","Effect","Exit","Layer","Mailbox","Option","RcRef","readline","defaultShouldQuit","input","key","ctrl","name","make","fnUntraced","shouldQuit","stdin","process","stdout","rlRef","acquire","acquireRelease","sync","rl","createInterface","escapeCodeTimeout","emitKeypressEvents","isTTY","setRawMode","close","columns","readInput","gen","get","mailbox","handleKeypress","s","k","userInput","fromNullable","meta","shift","unsafeDone","void","unsafeOffer","addFinalizer","off","on","readLine","pipe","flatMap","readlineInterface","async","resume","onLine","line","succeed","once","scoped","display","prompt","uninterruptible","write","err","fail","BadArgument","module","method","description","cause","of","layer"],"sources":["../../../src/internal/terminal.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect/platform-node-shared",
3
- "version": "0.45.0",
3
+ "version": "0.46.0",
4
4
  "description": "Unified interfaces for common platform-specific services",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -16,10 +16,10 @@
16
16
  "ws": "^8.18.2"
17
17
  },
18
18
  "peerDependencies": {
19
- "@effect/cluster": "^0.44.0",
20
- "@effect/platform": "^0.89.0",
21
- "@effect/rpc": "^0.66.0",
22
- "@effect/sql": "^0.43.0",
19
+ "@effect/cluster": "^0.45.0",
20
+ "@effect/platform": "^0.90.0",
21
+ "@effect/rpc": "^0.67.0",
22
+ "@effect/sql": "^0.44.0",
23
23
  "effect": "^3.17.0"
24
24
  },
25
25
  "publishConfig": {
@@ -1,126 +1,101 @@
1
1
  import * as Error from "@effect/platform/Error"
2
2
  import * as Terminal from "@effect/platform/Terminal"
3
3
  import * as Effect from "effect/Effect"
4
+ import * as Exit from "effect/Exit"
4
5
  import * as Layer from "effect/Layer"
6
+ import * as Mailbox from "effect/Mailbox"
5
7
  import * as Option from "effect/Option"
8
+ import * as RcRef from "effect/RcRef"
6
9
  import * as readline from "node:readline"
7
10
 
8
- const defaultShouldQuit = (input: Terminal.UserInput): boolean =>
11
+ const defaultShouldQuit = (input: Terminal.UserInput) =>
9
12
  input.key.ctrl && (input.key.name === "c" || input.key.name === "d")
10
13
 
11
14
  /** @internal */
12
- export const make = (
15
+ export const make = Effect.fnUntraced(function*(
13
16
  shouldQuit: (input: Terminal.UserInput) => boolean = defaultShouldQuit
14
- ) =>
15
- Effect.gen(function*() {
16
- const input = yield* Effect.sync(() => globalThis.process.stdin)
17
- const output = yield* Effect.sync(() => globalThis.process.stdout)
17
+ ) {
18
+ const stdin = process.stdin
19
+ const stdout = process.stdout
18
20
 
19
- // Acquire a readline interface
20
- const acquireReadlineInterface = Effect.sync(() =>
21
- readline.createInterface({
22
- input,
23
- escapeCodeTimeout: 50
24
- })
21
+ // Acquire readline interface with TTY setup/cleanup inside the scope
22
+ const rlRef = yield* RcRef.make({
23
+ acquire: Effect.acquireRelease(
24
+ Effect.sync(() => {
25
+ const rl = readline.createInterface({ input: stdin, escapeCodeTimeout: 50 })
26
+ readline.emitKeypressEvents(stdin, rl)
27
+
28
+ if (stdin.isTTY) {
29
+ stdin.setRawMode(true)
30
+ }
31
+ return rl
32
+ }),
33
+ (rl) =>
34
+ Effect.sync(() => {
35
+ if (stdin.isTTY) {
36
+ stdin.setRawMode(false)
37
+ }
38
+ rl.close()
39
+ })
25
40
  )
41
+ })
26
42
 
27
- // Uses the readline interface to force `stdin` to emit keypress events
28
- const emitKeypressEvents = (rl: readline.Interface): readline.Interface => {
29
- readline.emitKeypressEvents(input, rl)
30
- if (input.isTTY) {
31
- input.setRawMode(true)
43
+ const columns = Effect.sync(() => stdout.columns ?? 0)
44
+
45
+ const readInput = Effect.gen(function*() {
46
+ yield* RcRef.get(rlRef)
47
+ const mailbox = yield* Mailbox.make<Terminal.UserInput>()
48
+ const handleKeypress = (s: string | undefined, k: readline.Key) => {
49
+ const userInput = {
50
+ input: Option.fromNullable(s),
51
+ key: { name: k.name ?? "", ctrl: !!k.ctrl, meta: !!k.meta, shift: !!k.shift }
52
+ }
53
+ if (shouldQuit(userInput)) {
54
+ mailbox.unsafeDone(Exit.void)
55
+ } else {
56
+ mailbox.unsafeOffer(userInput)
32
57
  }
33
- return rl
34
58
  }
59
+ yield* Effect.addFinalizer(() => Effect.sync(() => stdin.off("keypress", handleKeypress)))
60
+ stdin.on("keypress", handleKeypress)
61
+ return mailbox as Mailbox.ReadonlyMailbox<Terminal.UserInput>
62
+ })
35
63
 
36
- // Close the `readline` interface
37
- const releaseReadlineInterface = (rl: readline.Interface) =>
38
- Effect.sync(() => {
39
- if (input.isTTY) {
40
- input.setRawMode(false)
41
- }
42
- rl.close()
43
- })
44
-
45
- // Handle the `"keypress"` event emitted by `stdin` (forced by readline)
46
- const handleKeypressEvent = (input: typeof globalThis.process.stdin) =>
47
- Effect.async<Terminal.UserInput, Terminal.QuitException>((resume) => {
48
- const handleKeypress = (input: string | undefined, key: readline.Key) => {
49
- const userInput: Terminal.UserInput = {
50
- input: Option.fromNullable(input),
51
- key: {
52
- name: key.name || "",
53
- ctrl: key.ctrl || false,
54
- meta: key.meta || false,
55
- shift: key.shift || false
56
- }
57
- }
58
- if (shouldQuit(userInput)) {
59
- resume(Effect.fail(new Terminal.QuitException()))
60
- } else {
61
- resume(Effect.succeed(userInput))
62
- }
63
- }
64
- input.once("keypress", handleKeypress)
65
- return Effect.sync(() => {
66
- input.removeListener("keypress", handleKeypress)
67
- })
64
+ const readLine = RcRef.get(rlRef).pipe(
65
+ Effect.flatMap((readlineInterface) =>
66
+ Effect.async<string, Terminal.QuitException>((resume) => {
67
+ const onLine = (line: string) => resume(Effect.succeed(line))
68
+ readlineInterface.once("line", onLine)
69
+ return Effect.sync(() => readlineInterface.off("line", onLine))
68
70
  })
71
+ ),
72
+ Effect.scoped
73
+ )
69
74
 
70
- // Handle the `"line"` event emitted by the readline interface
71
- const handleLineEvent = (rl: readline.Interface) =>
72
- Effect.async<string, Terminal.QuitException, never>((resume) => {
73
- const handleLine = (line: string) => {
74
- resume(Effect.succeed(line))
75
- }
76
- rl.on("line", handleLine)
77
- return Effect.sync(() => {
78
- rl.removeListener("line", handleLine)
79
- })
75
+ const display = (prompt: string) =>
76
+ Effect.uninterruptible(
77
+ Effect.async<void, Error.PlatformError>((resume) => {
78
+ stdout.write(prompt, (err) =>
79
+ err
80
+ ? resume(Effect.fail(
81
+ new Error.BadArgument({
82
+ module: "Terminal",
83
+ method: "display",
84
+ description: "Failed to write prompt to stdout",
85
+ cause: err
86
+ })
87
+ ))
88
+ : resume(Effect.void))
80
89
  })
81
-
82
- const readInput = Effect.acquireUseRelease(
83
- acquireReadlineInterface.pipe(Effect.map(emitKeypressEvents)),
84
- () => handleKeypressEvent(input),
85
- releaseReadlineInterface
86
- )
87
-
88
- const readLine = Effect.acquireUseRelease(
89
- acquireReadlineInterface,
90
- (rl) => handleLineEvent(rl),
91
- releaseReadlineInterface
92
90
  )
93
91
 
94
- const display = (prompt: string): Effect.Effect<void, Error.PlatformError> =>
95
- Effect.uninterruptible(
96
- Effect.async((resume) => {
97
- output.write(prompt, (err) => {
98
- if (err) {
99
- resume(Effect.fail(
100
- new Error.BadArgument({
101
- module: "Terminal",
102
- method: "display",
103
- description: "Failed to write prompt to output",
104
- cause: err
105
- })
106
- ))
107
- }
108
- resume(Effect.void)
109
- })
110
- })
111
- )
112
-
113
- return Terminal.Terminal.of({
114
- // The columns property can be undefined if stdout was redirected
115
- columns: Effect.sync(() => output.columns || 0),
116
- readInput,
117
- readLine,
118
- display
119
- })
92
+ return Terminal.Terminal.of({
93
+ columns,
94
+ readInput,
95
+ readLine,
96
+ display
120
97
  })
98
+ })
121
99
 
122
100
  /** @internal */
123
- export const layer: Layer.Layer<Terminal.Terminal> = Layer.scoped(
124
- Terminal.Terminal,
125
- make(defaultShouldQuit)
126
- )
101
+ export const layer: Layer.Layer<Terminal.Terminal> = Layer.scoped(Terminal.Terminal, make(defaultShouldQuit))