Initial commit

This commit is contained in:
2025-03-07 19:22:02 +01:00
commit 4a98255d83
55743 changed files with 5280367 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Separator = exports.createPrompt = exports.usePagination = exports.useKeypress = exports.useRef = exports.useMemo = exports.useEffect = exports.useState = exports.usePrefix = void 0;
__exportStar(require('./lib/key.js'), exports);
var use_prefix_mjs_1 = require('./lib/use-prefix.js');
Object.defineProperty(exports, "usePrefix", { enumerable: true, get: function () { return use_prefix_mjs_1.usePrefix; } });
var use_state_mjs_1 = require('./lib/use-state.js');
Object.defineProperty(exports, "useState", { enumerable: true, get: function () { return use_state_mjs_1.useState; } });
var use_effect_mjs_1 = require('./lib/use-effect.js');
Object.defineProperty(exports, "useEffect", { enumerable: true, get: function () { return use_effect_mjs_1.useEffect; } });
var use_memo_mjs_1 = require('./lib/use-memo.js');
Object.defineProperty(exports, "useMemo", { enumerable: true, get: function () { return use_memo_mjs_1.useMemo; } });
var use_ref_mjs_1 = require('./lib/use-ref.js');
Object.defineProperty(exports, "useRef", { enumerable: true, get: function () { return use_ref_mjs_1.useRef; } });
var use_keypress_mjs_1 = require('./lib/use-keypress.js');
Object.defineProperty(exports, "useKeypress", { enumerable: true, get: function () { return use_keypress_mjs_1.useKeypress; } });
var use_pagination_mjs_1 = require('./lib/pagination/use-pagination.js');
Object.defineProperty(exports, "usePagination", { enumerable: true, get: function () { return use_pagination_mjs_1.usePagination; } });
var create_prompt_mjs_1 = require('./lib/create-prompt.js');
Object.defineProperty(exports, "createPrompt", { enumerable: true, get: function () { return create_prompt_mjs_1.createPrompt; } });
var Separator_mjs_1 = require('./lib/Separator.js');
Object.defineProperty(exports, "Separator", { enumerable: true, get: function () { return Separator_mjs_1.Separator; } });
+35
View File
@@ -0,0 +1,35 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Separator = void 0;
const chalk_1 = __importDefault(require("chalk"));
const figures_1 = __importDefault(require("figures"));
/**
* Separator object
* Used to space/separate choices group
*/
class Separator {
constructor(separator) {
Object.defineProperty(this, "separator", {
enumerable: true,
configurable: true,
writable: true,
value: chalk_1.default.dim(new Array(15).join(figures_1.default.line))
});
Object.defineProperty(this, "type", {
enumerable: true,
configurable: true,
writable: true,
value: 'separator'
});
if (separator) {
this.separator = separator;
}
}
static isSeparator(choice) {
return Boolean(choice && choice.type === 'separator');
}
}
exports.Separator = Separator;
+137
View File
@@ -0,0 +1,137 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPrompt = void 0;
const readline = __importStar(require("node:readline"));
const type_1 = require("@inquirer/type");
const mute_stream_1 = __importDefault(require("mute-stream"));
const signal_exit_1 = require("signal-exit");
const screen_manager_mjs_1 = __importDefault(require('./screen-manager.js'));
const hook_engine_mjs_1 = require('./hook-engine.js');
// Take an AsyncPromptConfig and resolves all it's values.
function getPromptConfig(config) {
return __awaiter(this, void 0, void 0, function* () {
const message = typeof config.message === 'function' ? config.message() : config.message;
return Object.assign(Object.assign({}, config), { message: yield message });
});
}
function createPrompt(view) {
const prompt = (config, context) => {
var _a, _b;
// Default `input` to stdin
const input = (_a = context === null || context === void 0 ? void 0 : context.input) !== null && _a !== void 0 ? _a : process.stdin;
// Add mute capabilities to the output
const output = new mute_stream_1.default();
output.pipe((_b = context === null || context === void 0 ? void 0 : context.output) !== null && _b !== void 0 ? _b : process.stdout);
const rl = readline.createInterface({
terminal: true,
input,
output,
});
const screen = new screen_manager_mjs_1.default(rl);
let cancel = () => { };
const answer = new type_1.CancelablePromise((resolve, reject) => {
(0, hook_engine_mjs_1.withHooks)(rl, (store) => {
function checkCursorPos() {
screen.checkCursorPos();
}
const removeExitListener = (0, signal_exit_1.onExit)((code, signal) => {
onExit();
reject(new Error(`User force closed the prompt with ${code} ${signal}`));
});
function onExit() {
try {
store.hooksCleanup.forEach((cleanFn) => {
cleanFn === null || cleanFn === void 0 ? void 0 : cleanFn();
});
}
catch (err) {
reject(err);
}
if (context === null || context === void 0 ? void 0 : context.clearPromptOnDone) {
screen.clean();
}
else {
screen.clearContent();
}
screen.done();
removeExitListener();
store.rl.input.removeListener('keypress', checkCursorPos);
}
cancel = () => {
onExit();
reject(new Error('Prompt was canceled'));
};
function done(value) {
// Delay execution to let time to the hookCleanup functions to registers.
setImmediate(() => {
onExit();
// Finally we resolve our promise
resolve(value);
});
}
function workLoop(resolvedConfig) {
store.index = 0;
store.handleChange = () => workLoop(resolvedConfig);
try {
const nextView = view(resolvedConfig, done);
const [content, bottomContent] = typeof nextView === 'string' ? [nextView] : nextView;
screen.render(content, bottomContent);
hook_engine_mjs_1.effectScheduler.run();
}
catch (err) {
onExit();
reject(err);
}
}
// TODO: we should display a loader while we get the default options.
getPromptConfig(config).then((resolvedConfig) => {
workLoop(resolvedConfig);
// Re-renders only happen when the state change; but the readline cursor could change position
// and that also requires a re-render (and a manual one because we mute the streams).
// We set the listener after the initial workLoop to avoid a double render if render triggered
// by a state change sets the cursor to the right position.
store.rl.input.on('keypress', checkCursorPos);
}, reject);
});
});
answer.cancel = cancel;
return answer;
};
return prompt;
}
exports.createPrompt = createPrompt;
+102
View File
@@ -0,0 +1,102 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.effectScheduler = exports.handleChange = exports.withPointer = exports.withUpdates = exports.readline = exports.withHooks = void 0;
const node_async_hooks_1 = require("node:async_hooks");
const hookStorage = new node_async_hooks_1.AsyncLocalStorage();
function createStore(rl) {
const store = {
rl,
hooks: [],
hooksCleanup: [],
hooksEffect: [],
index: 0,
handleChange() { },
};
return store;
}
// Run callback in with the hook engine setup.
function withHooks(rl, cb) {
const store = createStore(rl);
return hookStorage.run(store, () => {
cb(store);
});
}
exports.withHooks = withHooks;
// Safe getStore utility that'll return the store or throw if undefined.
function getStore() {
const store = hookStorage.getStore();
if (!store) {
throw new Error('[Inquirer] Hook functions can only be called from within a prompt');
}
return store;
}
function readline() {
return getStore().rl;
}
exports.readline = readline;
// Merge state updates happening within the callback function to avoid multiple renders.
function withUpdates(fn) {
const wrapped = (...args) => {
const store = getStore();
let shouldUpdate = false;
const oldHandleChange = store.handleChange;
store.handleChange = () => {
shouldUpdate = true;
};
const returnValue = fn(...args);
if (shouldUpdate) {
oldHandleChange();
}
store.handleChange = oldHandleChange;
return returnValue;
};
return node_async_hooks_1.AsyncResource.bind(wrapped);
}
exports.withUpdates = withUpdates;
function withPointer(cb) {
const store = getStore();
const { index } = store;
const pointer = {
get() {
return store.hooks[index];
},
set(value) {
store.hooks[index] = value;
},
initialized: index in store.hooks,
};
const returnValue = cb(pointer);
store.index++;
return returnValue;
}
exports.withPointer = withPointer;
function handleChange() {
getStore().handleChange();
}
exports.handleChange = handleChange;
exports.effectScheduler = {
queue(cb) {
const store = getStore();
const { index } = store;
store.hooksEffect.push(() => {
var _a, _b;
(_b = (_a = store.hooksCleanup)[index]) === null || _b === void 0 ? void 0 : _b.call(_a);
const cleanFn = cb(readline());
if (cleanFn != null && typeof cleanFn !== 'function') {
throw new Error('useEffect return value must be a cleanup function or nothing.');
}
store.hooksCleanup[index] = cleanFn;
});
},
run() {
const store = getStore();
withUpdates(() => {
store.hooksEffect.forEach((effect) => {
effect();
});
// Warning: Clean the hooks before exiting the `withUpdates` block.
// Failure to do so means an updates would hit the same effects again.
store.hooksEffect.length = 0;
})();
},
};
+27
View File
@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isEnterKey = exports.isNumberKey = exports.isBackspaceKey = exports.isSpaceKey = exports.isDownKey = exports.isUpKey = void 0;
const isUpKey = (key) =>
// The up key
key.name === 'up' ||
// Vim keybinding
key.name === 'k' ||
// Emacs keybinding
(key.ctrl && key.name === 'p');
exports.isUpKey = isUpKey;
const isDownKey = (key) =>
// The down key
key.name === 'down' ||
// Vim keybinding
key.name === 'j' ||
// Emacs keybinding
(key.ctrl && key.name === 'n');
exports.isDownKey = isDownKey;
const isSpaceKey = (key) => key.name === 'space';
exports.isSpaceKey = isSpaceKey;
const isBackspaceKey = (key) => key.name === 'backspace';
exports.isBackspaceKey = isBackspaceKey;
const isNumberKey = (key) => '123456789'.includes(key.name);
exports.isNumberKey = isNumberKey;
const isEnterKey = (key) => key.name === 'enter' || key.name === 'return';
exports.isEnterKey = isEnterKey;
+63
View File
@@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.lines = void 0;
const utils_mjs_1 = require('../utils.js');
function split(content, width) {
return (0, utils_mjs_1.breakLines)(content, width).split('\n');
}
/**
* Rotates an array of items by an integer number of positions.
* @param {number} count The number of positions to rotate by
* @param {T[]} items The items to rotate
*/
function rotate(count, items) {
const max = items.length;
const offset = ((count % max) + max) % max;
return items.slice(offset).concat(items.slice(0, offset));
}
/**
* Renders a page of items as lines that fit within the given width ensuring
* that the number of lines is not greater than the page size, and the active
* item renders at the provided position, while prioritizing that as many lines
* of the active item get rendered as possible.
*/
function lines({ items, width, renderItem, active, position: requested, pageSize, }) {
const layouts = items.map((item, index) => ({
item,
index,
isActive: index === active,
}));
const layoutsInPage = rotate(active - requested, layouts).slice(0, pageSize);
const renderItemAt = (index) => split(renderItem(layoutsInPage[index]), width);
// Create a blank array of lines for the page
const pageBuffer = new Array(pageSize);
// Render the active item to decide the position
const activeItem = renderItemAt(requested).slice(0, pageSize);
const position = requested + activeItem.length <= pageSize ? requested : pageSize - activeItem.length;
// Add the lines of the active item into the page
pageBuffer.splice(position, activeItem.length, ...activeItem);
// Fill the page under the active item
let bufferPointer = position + activeItem.length;
let layoutPointer = requested + 1;
while (bufferPointer < pageSize && layoutPointer < layoutsInPage.length) {
for (const line of renderItemAt(layoutPointer)) {
pageBuffer[bufferPointer++] = line;
if (bufferPointer >= pageSize)
break;
}
layoutPointer++;
}
// Fill the page over the active item
bufferPointer = position - 1;
layoutPointer = requested - 1;
while (bufferPointer >= 0 && layoutPointer >= 0) {
for (const line of renderItemAt(layoutPointer).reverse()) {
pageBuffer[bufferPointer--] = line;
if (bufferPointer < 0)
break;
}
layoutPointer--;
}
return pageBuffer.filter((line) => typeof line === 'string');
}
exports.lines = lines;
+32
View File
@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.infinite = exports.finite = void 0;
/**
* Creates the next position for the active item considering a finite list of
* items to be rendered on a page.
*/
function finite({ active, pageSize, total, }) {
const middle = Math.floor(pageSize / 2);
if (total <= pageSize || active < middle)
return active;
if (active >= total - middle)
return active + pageSize - total;
return middle;
}
exports.finite = finite;
/**
* Creates the next position for the active item considering an infinitely
* looping list of items to be rendered on the page.
*/
function infinite({ active, lastActive, total, pageSize, pointer, }) {
if (total <= pageSize)
return active;
// Move the position only when the user moves down, and when the
// navigation fits within a single page
if (lastActive < active && active - lastActive < pageSize) {
// Limit it to the middle of the list
return Math.min(Math.floor(pageSize / 2), pointer + active - lastActive);
}
return pointer;
}
exports.infinite = infinite;
+42
View File
@@ -0,0 +1,42 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.usePagination = void 0;
const chalk_1 = __importDefault(require("chalk"));
const use_ref_mjs_1 = require('../use-ref.js');
const utils_mjs_1 = require('../utils.js');
const lines_mjs_1 = require('./lines.js');
const position_mjs_1 = require('./position.js');
function usePagination({ items, active, renderItem, pageSize = 7, loop = true, }) {
const state = (0, use_ref_mjs_1.useRef)({ position: 0, lastActive: 0 });
const position = loop
? (0, position_mjs_1.infinite)({
active,
lastActive: state.current.lastActive,
total: items.length,
pageSize,
pointer: state.current.position,
})
: (0, position_mjs_1.finite)({
active,
total: items.length,
pageSize,
});
state.current.position = position;
state.current.lastActive = active;
const visibleLines = (0, lines_mjs_1.lines)({
items,
width: (0, utils_mjs_1.readlineWidth)(),
renderItem,
active,
position,
pageSize,
}).join('\n');
if (items.length > pageSize) {
return `${visibleLines}\n${chalk_1.default.dim('(Use arrow keys to reveal more choices)')}`;
}
return visibleLines;
}
exports.usePagination = usePagination;
+2
View File
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
+128
View File
@@ -0,0 +1,128 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const strip_ansi_1 = __importDefault(require("strip-ansi"));
const ansi_escapes_1 = __importDefault(require("ansi-escapes"));
const utils_mjs_1 = require('./utils.js');
const height = (content) => content.split('\n').length;
const lastLine = (content) => { var _a; return (_a = content.split('\n').pop()) !== null && _a !== void 0 ? _a : ''; };
class ScreenManager {
constructor(rl) {
Object.defineProperty(this, "rl", {
enumerable: true,
configurable: true,
writable: true,
value: rl
});
// These variables are keeping information to allow correct prompt re-rendering
Object.defineProperty(this, "height", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "extraLinesUnderPrompt", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "cursorPos", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.rl = rl;
this.cursorPos = rl.getCursorPos();
}
render(content, bottomContent = '') {
this.clean();
this.rl.output.unmute();
/**
* Write message to screen and setPrompt to control backspace
*/
const promptLine = lastLine(content);
const rawPromptLine = (0, strip_ansi_1.default)(promptLine);
// Remove the rl.line from our prompt. We can't rely on the content of
// rl.line (mainly because of the password prompt), so just rely on it's
// length.
let prompt = rawPromptLine;
if (this.rl.line.length) {
prompt = prompt.slice(0, -this.rl.line.length);
}
this.rl.setPrompt(prompt);
// SetPrompt will change cursor position, now we can get correct value
this.cursorPos = this.rl.getCursorPos();
const width = (0, utils_mjs_1.readlineWidth)();
content = (0, utils_mjs_1.breakLines)(content, width);
bottomContent = (0, utils_mjs_1.breakLines)(bottomContent, width);
// Manually insert an extra line if we're at the end of the line.
// This prevent the cursor from appearing at the beginning of the
// current line.
if (rawPromptLine.length % width === 0) {
content += '\n';
}
let output = content + (bottomContent ? '\n' + bottomContent : '');
/**
* Re-adjust the cursor at the correct position.
*/
// We need to consider parts of the prompt under the cursor as part of the bottom
// content in order to correctly cleanup and re-render.
const promptLineUpDiff = Math.floor(rawPromptLine.length / width) - this.cursorPos.rows;
const bottomContentHeight = promptLineUpDiff + (bottomContent ? height(bottomContent) : 0);
// Return cursor to the input position (on top of the bottomContent)
if (bottomContentHeight > 0)
output += ansi_escapes_1.default.cursorUp(bottomContentHeight);
// Return cursor to the initial left offset.
output += ansi_escapes_1.default.cursorTo(this.cursorPos.cols);
/**
* Set up state for next re-rendering
*/
this.extraLinesUnderPrompt = bottomContentHeight;
this.height = height(output);
this.rl.output.write(output);
this.rl.output.mute();
}
checkCursorPos() {
const cursorPos = this.rl.getCursorPos();
if (cursorPos.cols !== this.cursorPos.cols) {
this.rl.output.unmute();
this.rl.output.write(ansi_escapes_1.default.cursorTo(cursorPos.cols));
this.rl.output.mute();
this.cursorPos = cursorPos;
}
}
clean() {
this.rl.output.unmute();
this.rl.output.write([
this.extraLinesUnderPrompt > 0
? ansi_escapes_1.default.cursorDown(this.extraLinesUnderPrompt)
: '',
ansi_escapes_1.default.eraseLines(this.height),
].join(''));
this.extraLinesUnderPrompt = 0;
this.rl.output.mute();
}
clearContent() {
this.rl.output.unmute();
// Reset the cursor at the end of the previously displayed content
this.rl.output.write([
this.extraLinesUnderPrompt > 0
? ansi_escapes_1.default.cursorDown(this.extraLinesUnderPrompt)
: '',
'\n',
].join(''));
this.rl.output.mute();
}
done() {
this.rl.setPrompt('');
this.rl.output.unmute();
this.rl.output.write(ansi_escapes_1.default.cursorShow);
this.rl.output.end();
this.rl.close();
}
}
exports.default = ScreenManager;
+15
View File
@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useEffect = void 0;
const hook_engine_mjs_1 = require('./hook-engine.js');
function useEffect(cb, depArray) {
(0, hook_engine_mjs_1.withPointer)((pointer) => {
const oldDeps = pointer.get();
const hasChanged = !Array.isArray(oldDeps) || depArray.some((dep, i) => !Object.is(dep, oldDeps[i]));
if (hasChanged) {
hook_engine_mjs_1.effectScheduler.queue(cb);
}
pointer.set(depArray);
});
}
exports.useEffect = useEffect;
+20
View File
@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useKeypress = void 0;
const use_ref_mjs_1 = require('./use-ref.js');
const use_effect_mjs_1 = require('./use-effect.js');
const hook_engine_mjs_1 = require('./hook-engine.js');
function useKeypress(userHandler) {
const signal = (0, use_ref_mjs_1.useRef)(userHandler);
signal.current = userHandler;
(0, use_effect_mjs_1.useEffect)((rl) => {
const handler = (0, hook_engine_mjs_1.withUpdates)((_input, event) => {
signal.current(event, rl);
});
rl.input.on('keypress', handler);
return () => {
rl.input.removeListener('keypress', handler);
};
}, []);
}
exports.useKeypress = useKeypress;
+18
View File
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useMemo = void 0;
const hook_engine_mjs_1 = require('./hook-engine.js');
function useMemo(fn, dependencies) {
return (0, hook_engine_mjs_1.withPointer)((pointer) => {
const prev = pointer.get();
if (!prev ||
prev.dependencies.length !== dependencies.length ||
prev.dependencies.some((dep, i) => dep !== dependencies[i])) {
const value = fn();
pointer.set({ value, dependencies });
return value;
}
return prev.value;
});
}
exports.useMemo = useMemo;
+28
View File
@@ -0,0 +1,28 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.usePrefix = void 0;
const chalk_1 = __importDefault(require("chalk"));
const cli_spinners_1 = __importDefault(require("cli-spinners"));
const use_state_mjs_1 = require('./use-state.js');
const use_effect_mjs_1 = require('./use-effect.js');
const spinner = cli_spinners_1.default.dots;
function usePrefix(isLoading = false) {
const [tick, setTick] = (0, use_state_mjs_1.useState)(0);
(0, use_effect_mjs_1.useEffect)(() => {
if (isLoading) {
const timeout = setTimeout(() => {
setTick(tick + 1);
}, spinner.interval);
return () => clearTimeout(timeout);
}
}, [isLoading, tick]);
if (isLoading) {
const frame = tick % spinner.frames.length;
return chalk_1.default.yellow(spinner.frames[frame]);
}
return chalk_1.default.green('?');
}
exports.usePrefix = usePrefix;
+8
View File
@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useRef = void 0;
const use_state_mjs_1 = require('./use-state.js');
function useRef(val) {
return (0, use_state_mjs_1.useState)({ current: val })[0];
}
exports.useRef = useRef;
+23
View File
@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useState = void 0;
const hook_engine_mjs_1 = require('./hook-engine.js');
function useState(defaultValue) {
return (0, hook_engine_mjs_1.withPointer)((pointer) => {
const setFn = (newValue) => {
// Noop if the value is still the same.
if (pointer.get() !== newValue) {
pointer.set(newValue);
// Trigger re-render
(0, hook_engine_mjs_1.handleChange)();
}
};
if (pointer.initialized) {
return [pointer.get(), setFn];
}
const value = typeof defaultValue === 'function' ? defaultValue() : defaultValue;
pointer.set(value);
return [value, setFn];
});
}
exports.useState = useState;
+33
View File
@@ -0,0 +1,33 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.readlineWidth = exports.breakLines = void 0;
const cli_width_1 = __importDefault(require("cli-width"));
const wrap_ansi_1 = __importDefault(require("wrap-ansi"));
const hook_engine_mjs_1 = require('./hook-engine.js');
/**
* Force line returns at specific width. This function is ANSI code friendly and it'll
* ignore invisible codes during width calculation.
* @param {string} content
* @param {number} width
* @return {string}
*/
function breakLines(content, width) {
return content
.split('\n')
.flatMap((line) => (0, wrap_ansi_1.default)(line, width, { trim: false, hard: true })
.split('\n')
.map((str) => str.trimEnd()))
.join('\n');
}
exports.breakLines = breakLines;
/**
* Returns the width of the active readline, or 80 as default value.
* @returns {number}
*/
function readlineWidth() {
return (0, cli_width_1.default)({ defaultWidth: 80, output: (0, hook_engine_mjs_1.readline)().output });
}
exports.readlineWidth = readlineWidth;
+11
View File
@@ -0,0 +1,11 @@
export * from './lib/key.js';
export { usePrefix } from './lib/use-prefix.js';
export { useState } from './lib/use-state.js';
export { useEffect } from './lib/use-effect.js';
export { useMemo } from './lib/use-memo.js';
export { useRef } from './lib/use-ref.js';
export { useKeypress } from './lib/use-keypress.js';
export { usePagination } from './lib/pagination/use-pagination.js';
export { createPrompt, type PromptConfig, type AsyncPromptConfig, } from './lib/create-prompt.js';
export { Separator } from './lib/Separator.js';
export { type InquirerReadline } from './lib/read-line.type.js';
+10
View File
@@ -0,0 +1,10 @@
/**
* Separator object
* Used to space/separate choices group
*/
export declare class Separator {
readonly separator: string;
readonly type = "separator";
constructor(separator?: string);
static isSeparator(choice: undefined | Separator | Record<string, unknown>): choice is Separator;
}
+11
View File
@@ -0,0 +1,11 @@
import { type Prompt, type Prettify } from '@inquirer/type';
export type AsyncPromptConfig = {
message: string | Promise<string> | (() => Promise<string>);
};
export type PromptConfig<Config> = Prettify<AsyncPromptConfig & Config>;
type ResolvedPromptConfig = {
message: string;
};
type ViewFunction<Value, Config> = (config: Prettify<Config & ResolvedPromptConfig>, done: (value: Value) => void) => string | [string, string | undefined];
export declare function createPrompt<Value, Config extends AsyncPromptConfig>(view: ViewFunction<Value, Config>): Prompt<Value, Config>;
export {};
+30
View File
@@ -0,0 +1,30 @@
import type { InquirerReadline } from './read-line.type.js';
type HookStore = {
rl: InquirerReadline;
hooks: any[];
hooksCleanup: Array<void | (() => void)>;
hooksEffect: Array<() => void>;
index: number;
handleChange: () => void;
};
export declare function withHooks(rl: InquirerReadline, cb: (store: HookStore) => void): void;
export declare function readline(): InquirerReadline;
export declare function withUpdates<T extends (...args: any) => any>(fn: T): (...args: Parameters<T>) => ReturnType<T>;
type SetPointer<Value> = {
get(): Value;
set(value: Value): void;
initialized: true;
};
type UnsetPointer<Value> = {
get(): void;
set(value: Value): void;
initialized: false;
};
type Pointer<Value> = SetPointer<Value> | UnsetPointer<Value>;
export declare function withPointer<Value, ReturnValue>(cb: (pointer: Pointer<Value>) => ReturnValue): ReturnValue;
export declare function handleChange(): void;
export declare const effectScheduler: {
queue(cb: (readline: InquirerReadline) => void): void;
run(): void;
};
export {};
+10
View File
@@ -0,0 +1,10 @@
export type KeypressEvent = {
name: string;
ctrl: boolean;
};
export declare const isUpKey: (key: KeypressEvent) => boolean;
export declare const isDownKey: (key: KeypressEvent) => boolean;
export declare const isSpaceKey: (key: KeypressEvent) => boolean;
export declare const isBackspaceKey: (key: KeypressEvent) => boolean;
export declare const isNumberKey: (key: KeypressEvent) => boolean;
export declare const isEnterKey: (key: KeypressEvent) => boolean;
+26
View File
@@ -0,0 +1,26 @@
import { type Prettify } from '@inquirer/type';
/** Represents an item that's part of a layout, about to be rendered */
export type Layout<T> = {
item: T;
index: number;
isActive: boolean;
};
/**
* Renders a page of items as lines that fit within the given width ensuring
* that the number of lines is not greater than the page size, and the active
* item renders at the provided position, while prioritizing that as many lines
* of the active item get rendered as possible.
*/
export declare function lines<T>({ items, width, renderItem, active, position: requested, pageSize, }: {
items: readonly T[];
/** The width of a rendered line in characters. */
width: number;
/** Renders an item as part of a page. */
renderItem: (layout: Prettify<Layout<T>>) => string;
/** The index of the active item in the list of items. */
active: number;
/** The position on the page at which to render the active item. */
position: number;
/** The number of lines to render per page. */
pageSize: number;
}): string[];
@@ -0,0 +1,20 @@
/**
* Creates the next position for the active item considering a finite list of
* items to be rendered on a page.
*/
export declare function finite({ active, pageSize, total, }: {
active: number;
pageSize: number;
total: number;
}): number;
/**
* Creates the next position for the active item considering an infinitely
* looping list of items to be rendered on the page.
*/
export declare function infinite({ active, lastActive, total, pageSize, pointer, }: {
active: number;
lastActive: number;
total: number;
pageSize: number;
pointer: number;
}): number;
@@ -0,0 +1,13 @@
import { type Prettify } from '@inquirer/type';
import { type Layout } from './lines.js';
export declare function usePagination<T>({ items, active, renderItem, pageSize, loop, }: {
items: readonly T[];
/** The index of the active item. */
active: number;
/** Renders an item as part of a page. */
renderItem: (layout: Prettify<Layout<T>>) => string;
/** The size of the page. `7` if unspecified. */
pageSize?: number;
/** Allows creating an infinitely looping list. `true` if unspecified. */
loop?: boolean;
}): string;
+9
View File
@@ -0,0 +1,9 @@
/// <reference types="node" />
/// <reference types="node" />
import * as readline from 'node:readline';
import MuteStream from 'mute-stream';
export type InquirerReadline = readline.ReadLine & {
output: MuteStream;
input: NodeJS.ReadableStream;
clearLine: (dir: 0 | 1 | -1) => void;
};
+13
View File
@@ -0,0 +1,13 @@
import type { InquirerReadline } from './read-line.type.js';
export default class ScreenManager {
private readonly rl;
private height;
private extraLinesUnderPrompt;
private cursorPos;
constructor(rl: InquirerReadline);
render(content: string, bottomContent?: string): void;
checkCursorPos(): void;
clean(): void;
clearContent(): void;
done(): void;
}
+2
View File
@@ -0,0 +1,2 @@
import type { InquirerReadline } from './read-line.type.js';
export declare function useEffect(cb: (rl: InquirerReadline) => void | (() => void), depArray: unknown[]): void;
+3
View File
@@ -0,0 +1,3 @@
import { type InquirerReadline } from './read-line.type.js';
import { type KeypressEvent } from './key.js';
export declare function useKeypress(userHandler: (event: KeypressEvent, rl: InquirerReadline) => void): void;
+1
View File
@@ -0,0 +1 @@
export declare function useMemo<Value>(fn: () => Value, dependencies: unknown[]): Value;
+1
View File
@@ -0,0 +1 @@
export declare function usePrefix(isLoading?: boolean): string;
+3
View File
@@ -0,0 +1,3 @@
export declare function useRef<Value>(val: Value): {
current: Value;
};
+3
View File
@@ -0,0 +1,3 @@
type NotFunction<T> = T extends Function ? never : T;
export declare function useState<Value>(defaultValue: NotFunction<Value> | (() => Value)): [Value, (newValue: Value) => void];
export {};
+13
View File
@@ -0,0 +1,13 @@
/**
* Force line returns at specific width. This function is ANSI code friendly and it'll
* ignore invisible codes during width calculation.
* @param {string} content
* @param {number} width
* @return {string}
*/
export declare function breakLines(content: string, width: number): string;
/**
* Returns the width of the active readline, or 80 as default value.
* @returns {number}
*/
export declare function readlineWidth(): number;