depfresh 0.9.2

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.
@@ -0,0 +1,624 @@
1
+ import * as readline from 'node:readline';
2
+ import * as semver from 'semver';
3
+ import { g as getVersionPrefix, f as applyVersionPrefix, h as getDiff, t as timeDifference, s as stripAnsi, i as truncate, j as padEnd, b as colorizeVersionDiff, a as arrow, e as colorDiff } from '../shared/depfresh.ClIHCCxD.mjs';
4
+ import c from 'ansis';
5
+ import '../shared/depfresh.B1o7OHO_.mjs';
6
+ import 'node:fs';
7
+ import 'node:os';
8
+ import 'find-up-simple';
9
+ import 'ini';
10
+ import 'pathe';
11
+ import 'node:child_process';
12
+ import 'detect-indent';
13
+ import 'pnpm-workspace-yaml';
14
+ import 'yaml';
15
+ import 'p-limit';
16
+ import 'better-sqlite3';
17
+ import 'tinyglobby';
18
+
19
+ const MAX_VERSIONS = 20;
20
+ function prepareDetailVersions(dep, explain) {
21
+ const { pkgData, currentVersion } = dep;
22
+ const current = semver.coerce(currentVersion);
23
+ if (!current) return [];
24
+ const newer = pkgData.versions.filter((v) => {
25
+ const parsed = semver.valid(v);
26
+ return parsed && semver.gt(v, current);
27
+ }).sort((a, b) => semver.gt(a, b) ? -1 : 1).slice(0, MAX_VERSIONS);
28
+ const tagsByVersion = /* @__PURE__ */ new Map();
29
+ for (const [tag, ver] of Object.entries(pkgData.distTags)) {
30
+ tagsByVersion.set(ver, tag);
31
+ }
32
+ return newer.map((version) => {
33
+ const diff = getDiff(currentVersion, version);
34
+ const publishedAt = pkgData.time?.[version];
35
+ const age = timeDifference(publishedAt);
36
+ const distTag = tagsByVersion.get(version);
37
+ const deprecated = pkgData.deprecated?.[version];
38
+ const nodeEngines = pkgData.engines?.[version];
39
+ const provenance = pkgData.provenance?.[version];
40
+ const result = { version, diff };
41
+ if (age) result.age = age;
42
+ if (distTag) result.distTag = distTag;
43
+ if (deprecated) result.deprecated = deprecated;
44
+ if (nodeEngines) result.nodeEngines = nodeEngines;
45
+ if (provenance) result.provenance = provenance;
46
+ if (explain) {
47
+ result.explain = getExplanation(diff, deprecated, provenance === "none");
48
+ }
49
+ return result;
50
+ });
51
+ }
52
+ function getExplanation(diff, deprecated, provenanceDowngrade, nodeIncompat) {
53
+ const parts = [];
54
+ switch (diff) {
55
+ case "major":
56
+ parts.push("Breaking change. Check migration guide.");
57
+ break;
58
+ case "minor":
59
+ parts.push("New features. Backwards compatible.");
60
+ break;
61
+ case "patch":
62
+ parts.push("Bug fixes only. Safe to update.");
63
+ break;
64
+ }
65
+ if (deprecated) parts.push("Deprecated.");
66
+ if (provenanceDowngrade) parts.push("Provenance downgrade.");
67
+ return parts.join(" ");
68
+ }
69
+ function applyVersionSelection(dep, selectedVersion) {
70
+ const prefix = getVersionPrefix(dep.currentVersion);
71
+ dep.targetVersion = applyVersionPrefix(selectedVersion, prefix);
72
+ dep.diff = getDiff(dep.currentVersion, selectedVersion);
73
+ }
74
+
75
+ function safeTermSize(value, fallback) {
76
+ return typeof value === "number" && value > 0 ? value : fallback;
77
+ }
78
+
79
+ const CHROME_LINES = 6;
80
+ function getViewportHeight(termRows, chrome) {
81
+ return Math.max(1, termRows - (chrome ?? CHROME_LINES));
82
+ }
83
+ function calculateScrollOffset(cursor, viewportHeight, totalItems, currentOffset) {
84
+ const maxOffset = Math.max(0, totalItems - viewportHeight);
85
+ let offset = currentOffset;
86
+ if (cursor < offset) {
87
+ offset = cursor;
88
+ }
89
+ if (cursor >= offset + viewportHeight) {
90
+ offset = cursor - viewportHeight + 1;
91
+ }
92
+ return Math.min(offset, maxOffset);
93
+ }
94
+ function getVisibleRange(scrollOffset, viewportHeight, totalItems) {
95
+ const start = scrollOffset;
96
+ const end = Math.min(scrollOffset + viewportHeight, totalItems);
97
+ return { start, end };
98
+ }
99
+ function hasOverflowAbove(scrollOffset) {
100
+ return scrollOffset > 0;
101
+ }
102
+ function hasOverflowBelow(scrollOffset, viewportHeight, totalItems) {
103
+ return scrollOffset + viewportHeight < totalItems;
104
+ }
105
+
106
+ function updateListScroll(state, cursor, termRows) {
107
+ const viewport = getViewportHeight(termRows);
108
+ return calculateScrollOffset(cursor, viewport, state.items.length, state.scrollOffset);
109
+ }
110
+ function updateDetailScroll(state, detailCursor, termRows, currentOffset) {
111
+ const viewport = getViewportHeight(termRows);
112
+ return calculateScrollOffset(detailCursor, viewport, state.detailVersions.length, currentOffset);
113
+ }
114
+ function resize(state, rows, cols) {
115
+ const termRows = safeTermSize(rows, state.termRows);
116
+ const termCols = safeTermSize(cols, state.termCols);
117
+ const resized = {
118
+ ...state,
119
+ termRows,
120
+ termCols
121
+ };
122
+ if (resized.view === "detail") {
123
+ return {
124
+ ...resized,
125
+ detailScrollOffset: updateDetailScroll(
126
+ resized,
127
+ resized.detailCursor,
128
+ termRows,
129
+ resized.detailScrollOffset
130
+ )
131
+ };
132
+ }
133
+ return {
134
+ ...resized,
135
+ scrollOffset: updateListScroll(resized, resized.cursor, termRows)
136
+ };
137
+ }
138
+
139
+ function enterDetail(state) {
140
+ if (state.view !== "list") return state;
141
+ const item = state.items[state.cursor];
142
+ if (item?.type !== "dep" || !item.dep) return state;
143
+ const detailVersions = prepareDetailVersions(item.dep, state.explain);
144
+ if (detailVersions.length === 0) return state;
145
+ return {
146
+ ...state,
147
+ view: "detail",
148
+ detailDep: item.dep,
149
+ detailVersions,
150
+ detailCursor: 0,
151
+ detailScrollOffset: calculateScrollOffset(
152
+ 0,
153
+ getViewportHeight(state.termRows),
154
+ detailVersions.length,
155
+ 0
156
+ )
157
+ };
158
+ }
159
+ function exitDetail(state) {
160
+ if (state.view !== "detail") return state;
161
+ return {
162
+ ...state,
163
+ view: "list",
164
+ detailDep: null,
165
+ detailVersions: [],
166
+ detailCursor: 0,
167
+ detailScrollOffset: 0
168
+ };
169
+ }
170
+ function selectDetailVersion(state) {
171
+ if (state.view !== "detail" || !state.detailDep || state.detailVersions.length === 0) return state;
172
+ const selected = state.detailVersions[state.detailCursor];
173
+ if (!selected) return state;
174
+ applyVersionSelection(state.detailDep, selected.version);
175
+ const selectedNames = new Set(state.selectedNames);
176
+ selectedNames.add(state.detailDep.name);
177
+ return {
178
+ ...state,
179
+ view: "list",
180
+ detailDep: null,
181
+ detailVersions: [],
182
+ detailCursor: 0,
183
+ detailScrollOffset: 0,
184
+ selectedNames
185
+ };
186
+ }
187
+ function moveDetailCursor(state, delta) {
188
+ if (state.view !== "detail" || state.detailVersions.length === 0 || delta === 0) return state;
189
+ const max = state.detailVersions.length - 1;
190
+ const next = Math.min(max, Math.max(0, state.detailCursor + delta));
191
+ if (next === state.detailCursor) return state;
192
+ return {
193
+ ...state,
194
+ detailCursor: next,
195
+ detailScrollOffset: updateDetailScroll(state, next, state.termRows, state.detailScrollOffset)
196
+ };
197
+ }
198
+
199
+ function findDepIndex(items, start, direction) {
200
+ let i = start;
201
+ while (i >= 0 && i < items.length) {
202
+ const item = items[i];
203
+ if (item?.type === "dep") return i;
204
+ i += direction;
205
+ }
206
+ return -1;
207
+ }
208
+ function createInitialState(updates, options = {}) {
209
+ const termRows = safeTermSize(options.termRows, 24);
210
+ const termCols = safeTermSize(options.termCols, 80);
211
+ const grouped = /* @__PURE__ */ new Map();
212
+ for (const [depIndex, dep] of updates.entries()) {
213
+ const existing = grouped.get(dep.source);
214
+ if (existing) {
215
+ existing.push({ dep, depIndex });
216
+ } else {
217
+ grouped.set(dep.source, [{ dep, depIndex }]);
218
+ }
219
+ }
220
+ const items = [];
221
+ let index = 0;
222
+ for (const [groupLabel, deps] of grouped.entries()) {
223
+ items.push({
224
+ type: "group-header",
225
+ groupLabel,
226
+ index
227
+ });
228
+ index++;
229
+ for (const entry of deps) {
230
+ items.push({
231
+ type: "dep",
232
+ dep: entry.dep,
233
+ depIndex: entry.depIndex,
234
+ index
235
+ });
236
+ index++;
237
+ }
238
+ }
239
+ const firstDepCursor = findDepIndex(items, 0, 1);
240
+ const cursor = firstDepCursor >= 0 ? firstDepCursor : 0;
241
+ const initial = {
242
+ view: "list",
243
+ items,
244
+ cursor,
245
+ scrollOffset: 0,
246
+ detailDep: null,
247
+ detailVersions: [],
248
+ detailCursor: 0,
249
+ detailScrollOffset: 0,
250
+ selectedNames: /* @__PURE__ */ new Set(),
251
+ termRows,
252
+ termCols,
253
+ explain: options.explain ?? false,
254
+ confirmed: false,
255
+ cancelled: false
256
+ };
257
+ return {
258
+ ...initial,
259
+ scrollOffset: updateListScroll(initial, cursor, termRows)
260
+ };
261
+ }
262
+ function moveCursor(state, delta) {
263
+ if (state.view !== "list" || delta === 0 || state.items.length === 0) return state;
264
+ const direction = delta > 0 ? 1 : -1;
265
+ let cursor = state.cursor;
266
+ const steps = Math.max(1, Math.abs(delta));
267
+ for (let i = 0; i < steps; i++) {
268
+ const next = findDepIndex(state.items, cursor + direction, direction);
269
+ if (next === -1) break;
270
+ cursor = next;
271
+ }
272
+ if (cursor === state.cursor) return state;
273
+ return {
274
+ ...state,
275
+ cursor,
276
+ scrollOffset: updateListScroll(state, cursor, state.termRows)
277
+ };
278
+ }
279
+ function jumpToFirst(state) {
280
+ if (state.view !== "list") return state;
281
+ const cursor = findDepIndex(state.items, 0, 1);
282
+ if (cursor === -1 || cursor === state.cursor) return state;
283
+ return {
284
+ ...state,
285
+ cursor,
286
+ scrollOffset: updateListScroll(state, cursor, state.termRows)
287
+ };
288
+ }
289
+ function jumpToLast(state) {
290
+ if (state.view !== "list") return state;
291
+ const cursor = findDepIndex(state.items, state.items.length - 1, -1);
292
+ if (cursor === -1 || cursor === state.cursor) return state;
293
+ return {
294
+ ...state,
295
+ cursor,
296
+ scrollOffset: updateListScroll(state, cursor, state.termRows)
297
+ };
298
+ }
299
+ function pageMove(state, direction) {
300
+ if (state.view !== "list") return state;
301
+ const distance = getViewportHeight(state.termRows);
302
+ return moveCursor(state, direction * distance);
303
+ }
304
+ function toggleSelection(state) {
305
+ if (state.view !== "list") return state;
306
+ const item = state.items[state.cursor];
307
+ if (item?.type !== "dep" || !item.dep) return state;
308
+ const selectedNames = new Set(state.selectedNames);
309
+ if (selectedNames.has(item.dep.name)) {
310
+ selectedNames.delete(item.dep.name);
311
+ } else {
312
+ selectedNames.add(item.dep.name);
313
+ }
314
+ return { ...state, selectedNames };
315
+ }
316
+ function toggleAll(state) {
317
+ const depNames = Array.from(
318
+ new Set(
319
+ state.items.filter(
320
+ (item) => item.type === "dep" && !!item.dep
321
+ ).map((item) => item.dep.name)
322
+ )
323
+ );
324
+ if (depNames.length === 0) return state;
325
+ const allSelected = depNames.every((name) => state.selectedNames.has(name));
326
+ return {
327
+ ...state,
328
+ selectedNames: allSelected ? /* @__PURE__ */ new Set() : new Set(depNames)
329
+ };
330
+ }
331
+
332
+ function confirm(state) {
333
+ return { ...state, confirmed: true };
334
+ }
335
+ function cancel(state) {
336
+ return { ...state, cancelled: true };
337
+ }
338
+
339
+ function isShiftG(key) {
340
+ return key.name === "G" || key.name === "g" && key.shift || key.sequence === "G";
341
+ }
342
+ function handleListViewKeypress(state, key) {
343
+ switch (key.name) {
344
+ case "down":
345
+ case "j":
346
+ return moveCursor(state, 1);
347
+ case "up":
348
+ case "k":
349
+ return moveCursor(state, -1);
350
+ case "space":
351
+ return toggleSelection(state);
352
+ case "a":
353
+ return toggleAll(state);
354
+ case "right":
355
+ case "l":
356
+ return enterDetail(state);
357
+ case "return":
358
+ return confirm(state);
359
+ case "escape":
360
+ case "q":
361
+ return cancel(state);
362
+ case "pagedown":
363
+ return pageMove(state, 1);
364
+ case "pageup":
365
+ return pageMove(state, -1);
366
+ case "g":
367
+ return isShiftG(key) ? jumpToLast(state) : jumpToFirst(state);
368
+ default:
369
+ return isShiftG(key) ? jumpToLast(state) : state;
370
+ }
371
+ }
372
+ function handleDetailViewKeypress(state, key) {
373
+ switch (key.name) {
374
+ case "down":
375
+ case "j":
376
+ return moveDetailCursor(state, 1);
377
+ case "up":
378
+ case "k":
379
+ return moveDetailCursor(state, -1);
380
+ case "space":
381
+ case "return":
382
+ return selectDetailVersion(state);
383
+ case "left":
384
+ case "h":
385
+ case "escape":
386
+ case "q":
387
+ return exitDetail(state);
388
+ default:
389
+ return state;
390
+ }
391
+ }
392
+ function handleKeypress(state, key) {
393
+ if (key.ctrl && key.name === "c") {
394
+ return cancel(state);
395
+ }
396
+ if (state.view === "detail") {
397
+ return handleDetailViewKeypress(state, key);
398
+ }
399
+ return handleListViewKeypress(state, key);
400
+ }
401
+
402
+ const LIST_HELP = " up/down navigate Space toggle -> versions a all Enter confirm Esc cancel";
403
+ const DETAIL_HELP = " up/down navigate Space/Enter select left/Esc back";
404
+ const DETAIL_CHROME_LINES = 8;
405
+ function colorAge(age) {
406
+ if (!age) return "";
407
+ if (age.color === "green") return c.green(age.text);
408
+ if (age.color === "yellow") return c.yellow(age.text);
409
+ return c.red(age.text);
410
+ }
411
+ function fitLine(line, termCols) {
412
+ if (termCols <= 0) return line;
413
+ const visible = stripAnsi(line);
414
+ if (visible.length <= termCols) return line;
415
+ return truncate(visible, termCols);
416
+ }
417
+ function getDepItems(state) {
418
+ return state.items.filter(
419
+ (item) => item.type === "dep" && !!item.dep
420
+ );
421
+ }
422
+
423
+ function renderListView(state) {
424
+ const lines = [];
425
+ const depItems = getDepItems(state);
426
+ const nameWidth = Math.min(
427
+ depItems.reduce((max, item) => Math.max(max, item.dep.name.length), 4),
428
+ 24
429
+ );
430
+ const viewportHeight = getViewportHeight(state.termRows);
431
+ const { start, end } = getVisibleRange(state.scrollOffset, viewportHeight, state.items.length);
432
+ const visibleItems = state.items.slice(start, end);
433
+ lines.push(fitLine(" Select dependencies to update", state.termCols));
434
+ lines.push("");
435
+ if (hasOverflowAbove(state.scrollOffset)) {
436
+ lines.push(fitLine(` ${c.gray("^ more")}`, state.termCols));
437
+ }
438
+ for (const item of visibleItems) {
439
+ lines.push(renderListLine(state, item, nameWidth));
440
+ }
441
+ if (hasOverflowBelow(state.scrollOffset, viewportHeight, state.items.length)) {
442
+ lines.push(fitLine(` ${c.gray("v more")}`, state.termCols));
443
+ }
444
+ const totalDeps = depItems.length;
445
+ const selectedCount = depItems.reduce(
446
+ (count, item) => state.selectedNames.has(item.dep.name) ? count + 1 : count,
447
+ 0
448
+ );
449
+ lines.push(fitLine(` ${selectedCount}/${totalDeps} selected`, state.termCols));
450
+ lines.push("");
451
+ lines.push(fitLine(LIST_HELP, state.termCols));
452
+ return lines;
453
+ }
454
+ function renderListLine(state, item, nameWidth) {
455
+ if (item.type === "group-header") {
456
+ return fitLine(` ${c.gray(item.groupLabel ?? "")}`, state.termCols);
457
+ }
458
+ if (!item.dep) return "";
459
+ return renderListDepLine(
460
+ item.dep,
461
+ item.index === state.cursor,
462
+ state.selectedNames.has(item.dep.name),
463
+ nameWidth,
464
+ state.termCols
465
+ );
466
+ }
467
+ function renderListDepLine(dep, focused, selected, nameWidth, termCols) {
468
+ const pointer = focused ? c.cyan(">") : " ";
469
+ const selectedMark = selected ? c.green("*") : c.gray("o");
470
+ const name = padEnd(truncate(dep.name, nameWidth), nameWidth);
471
+ const target = colorizeVersionDiff(dep.currentVersion, dep.targetVersion, dep.diff);
472
+ const age = timeDifference(dep.publishedAt);
473
+ let line = ` ${pointer} ${selectedMark} ${name} ${dep.currentVersion}${arrow()}${target} ${colorDiff(dep.diff)}`;
474
+ if (age) line += ` ${colorAge(age)}`;
475
+ return fitLine(line, termCols);
476
+ }
477
+
478
+ function renderDetailView(state) {
479
+ const lines = [];
480
+ const dep = state.detailDep;
481
+ if (!dep) return renderListView(state);
482
+ const header = ` ${dep.name} ${dep.currentVersion}${arrow()}?`;
483
+ lines.push(fitLine(header, state.termCols));
484
+ lines.push("");
485
+ const versionWidth = Math.min(
486
+ state.detailVersions.reduce((max, item) => Math.max(max, item.version.length), 6),
487
+ 18
488
+ );
489
+ const viewportHeight = getViewportHeight(state.termRows, DETAIL_CHROME_LINES);
490
+ const { start, end } = getVisibleRange(
491
+ state.detailScrollOffset,
492
+ viewportHeight,
493
+ state.detailVersions.length
494
+ );
495
+ const visible = state.detailVersions.slice(start, end);
496
+ if (hasOverflowAbove(state.detailScrollOffset)) {
497
+ lines.push(fitLine(` ${c.gray("^ more")}`, state.termCols));
498
+ }
499
+ for (const [index, version] of visible.entries()) {
500
+ lines.push(renderDetailVersionLine(state, version, start + index, versionWidth));
501
+ }
502
+ if (hasOverflowBelow(state.detailScrollOffset, viewportHeight, state.detailVersions.length)) {
503
+ lines.push(fitLine(` ${c.gray("v more")}`, state.termCols));
504
+ }
505
+ const distTags = Object.entries(dep.pkgData.distTags).map(([tag, version]) => `${tag}${arrow()}${version}`).join(" | ");
506
+ lines.push("");
507
+ if (distTags) {
508
+ lines.push(fitLine(` dist-tags: ${distTags}`, state.termCols));
509
+ }
510
+ if (dep.pkgData.homepage) {
511
+ lines.push(fitLine(` Homepage: ${dep.pkgData.homepage}`, state.termCols));
512
+ }
513
+ lines.push("");
514
+ lines.push(fitLine(DETAIL_HELP, state.termCols));
515
+ return lines;
516
+ }
517
+ function renderDetailVersionLine(state, version, idx, versionWidth) {
518
+ const pointer = idx === state.detailCursor ? c.cyan(">") : " ";
519
+ const versionText = padEnd(version.version, versionWidth);
520
+ let line = ` ${pointer} ${versionText} ${colorDiff(version.diff)}`;
521
+ if (version.age) line += ` ${colorAge(version.age)}`;
522
+ if (version.distTag) line += ` ${c.cyan(version.distTag)}`;
523
+ if (version.explain) line += ` ${c.gray(version.explain)}`;
524
+ if (version.deprecated) line += ` ${c.red("deprecated")}`;
525
+ if (version.provenance === "none") line += ` ${c.yellow("no-provenance")}`;
526
+ if (version.nodeEngines) line += ` ${c.gray(`node ${version.nodeEngines}`)}`;
527
+ return fitLine(line, state.termCols);
528
+ }
529
+
530
+ function renderFrame(state) {
531
+ const lines = state.view === "detail" ? renderDetailView(state) : renderListView(state);
532
+ return `${lines.join("\n")}
533
+ `;
534
+ }
535
+ function eraseLines(count) {
536
+ if (count <= 0) return "";
537
+ return `\x1B[${count}A\x1B[0J`;
538
+ }
539
+
540
+ const HIDE_CURSOR = "\x1B[?25l";
541
+ const SHOW_CURSOR = "\x1B[?25h";
542
+ function getRows() {
543
+ return process.stdout.rows ?? 24;
544
+ }
545
+ function getCols() {
546
+ return process.stdout.columns ?? 80;
547
+ }
548
+ function countFrameLines(frame) {
549
+ const parts = frame.split("\n");
550
+ return frame.endsWith("\n") ? parts.length - 1 : parts.length;
551
+ }
552
+ function getSelectedUpdates(state, updates) {
553
+ return updates.filter((dep) => state.selectedNames.has(dep.name));
554
+ }
555
+ async function createInteractiveTUI(updates, options) {
556
+ if (updates.length === 0) return [];
557
+ const input = process.stdin;
558
+ const output = process.stdout;
559
+ if (typeof input.setRawMode !== "function") {
560
+ return [];
561
+ }
562
+ return new Promise((resolve, reject) => {
563
+ let state = createInitialState(updates, {
564
+ termRows: getRows(),
565
+ termCols: getCols(),
566
+ explain: options.explain
567
+ });
568
+ let lastFrameLineCount = 0;
569
+ let finished = false;
570
+ const render = () => {
571
+ const frame = renderFrame(state);
572
+ if (lastFrameLineCount > 0) {
573
+ output.write(eraseLines(lastFrameLineCount));
574
+ }
575
+ output.write(frame);
576
+ lastFrameLineCount = countFrameLines(frame);
577
+ };
578
+ const cleanup = () => {
579
+ input.off("keypress", onKeypress);
580
+ output.off("resize", onResize);
581
+ if (lastFrameLineCount > 0) {
582
+ output.write(eraseLines(lastFrameLineCount));
583
+ }
584
+ output.write(SHOW_CURSOR);
585
+ input.setRawMode(false);
586
+ input.pause();
587
+ };
588
+ const finish = (result) => {
589
+ if (finished) return;
590
+ finished = true;
591
+ cleanup();
592
+ resolve(result);
593
+ };
594
+ const onResize = () => {
595
+ state = resize(state, getRows(), getCols());
596
+ render();
597
+ };
598
+ const onKeypress = (_sequence, key) => {
599
+ state = handleKeypress(state, key);
600
+ render();
601
+ if (state.cancelled) {
602
+ finish([]);
603
+ return;
604
+ }
605
+ if (state.confirmed) {
606
+ finish(getSelectedUpdates(state, updates));
607
+ }
608
+ };
609
+ try {
610
+ readline.emitKeypressEvents(input);
611
+ input.setRawMode(true);
612
+ input.resume();
613
+ output.write(HIDE_CURSOR);
614
+ render();
615
+ input.on("keypress", onKeypress);
616
+ output.on("resize", onResize);
617
+ } catch (error) {
618
+ cleanup();
619
+ reject(error);
620
+ }
621
+ });
622
+ }
623
+
624
+ export { createInteractiveTUI };