Skip to content

Commit

Permalink
object builder
Browse files Browse the repository at this point in the history
  • Loading branch information
zoe-codez committed Nov 4, 2024
1 parent 882c849 commit 4bea3f5
Show file tree
Hide file tree
Showing 11 changed files with 1,820 additions and 1,291 deletions.
42 changes: 21 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,51 +29,51 @@
"chalk": "^5.3.0",
"chrono-node": "^2.7.7",
"dayjs": "^1.11.13",
"execa": "^9.4.0",
"execa": "^9.5.1",
"external-editor": "^3.1.0",
"figlet": "^1.7.0",
"fuzzysort": "^3.0.2",
"mute-stream": "^1.0.0"
"figlet": "^1.8.0",
"fuzzysort": "^3.1.0",
"mute-stream": "^2.0.0"
},
"peerDependencies": {
"@digital-alchemy/core": "*",
"@digital-alchemy/utils": "*"
},
"devDependencies": {
"@cspell/eslint-plugin": "^8.14.4",
"@digital-alchemy/core": "^24.9.3",
"@cspell/eslint-plugin": "^8.15.7",
"@digital-alchemy/core": "^24.10.8",
"@digital-alchemy/utils": "^24.9.1",
"@eslint/compat": "^1.1.1",
"@eslint/compat": "^1.2.2",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.11.1",
"@types/figlet": "^1.5.8",
"@types/jest": "^29.5.13",
"@eslint/js": "^9.14.0",
"@types/figlet": "^1.7.0",
"@types/jest": "^29.5.14",
"@types/js-yaml": "^4.0.9",
"@types/minimist": "^1.2.5",
"@types/mute-stream": "^0.0.4",
"@types/node": "^22.7.0",
"@types/node": "^22.8.7",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "8.7.0",
"@typescript-eslint/parser": "8.7.0",
"eslint": "9.11.1",
"@typescript-eslint/eslint-plugin": "8.12.2",
"@typescript-eslint/parser": "8.12.2",
"eslint": "9.14.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-import": "^2.30.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsonc": "^2.16.0",
"eslint-plugin-no-unsanitized": "^4.1.1",
"eslint-plugin-no-unsanitized": "^4.1.2",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-security": "^3.0.1",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-sonarjs": "^2.0.2",
"eslint-plugin-sonarjs": "^2.0.4",
"eslint-plugin-sort-keys-fix": "^1.1.2",
"eslint-plugin-unicorn": "^55.0.0",
"globals": "^15.9.0",
"eslint-plugin-unicorn": "^56.0.0",
"globals": "^15.11.0",
"jest": "^29.7.0",
"jest-environment-node": "^29.7.0",
"prettier": "^3.3.3",
"ts-jest": "^29.2.5",
"tsx": "^4.19.1",
"tsx": "^4.19.2",
"type-fest": "^4.26.1",
"typescript": "^5.6.2"
"typescript": "^5.6.3"
},
"packageManager": "[email protected]"
}
23 changes: 12 additions & 11 deletions src/extensions/components/menu-component.extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type MenuRestoreCacheData<VALUE = unknown> = {
};
const DEFAULT_HEADER_PADDING = 4;

const CACHE_KEY_RESTORE = (id: string) => `MENU_COMPONENT_RESTORE_${id}`;
// const CACHE_KEY_RESTORE = (id: string) => `MENU_COMPONENT_RESTORE_${id}`;

interface LastMenuResultInfo<VALUE = unknown> {
key?: {
Expand Down Expand Up @@ -133,7 +133,7 @@ function isSearchEnabled(options: MenuSearchOptions) {
let LAST_RESULT: LastMenuResultInfo<unknown>;
type LR = "left" | "right";

export function Menu<VALUE = unknown>({ config, terminal, internal, cache }: TServiceParams) {
export function Menu<VALUE = unknown>({ config, terminal, internal }: TServiceParams) {
const { ansiPadEnd, template, GV } = terminal.internals;

let value: VALUE;
Expand Down Expand Up @@ -1089,7 +1089,8 @@ export function Menu<VALUE = unknown>({ config, terminal, internal, cache }: TSe

// If a restore id is available, attempt to get data from that
if (!is.empty(restore?.id)) {
const data = await cache.get<MenuRestoreCacheData<VALUE>>(CACHE_KEY_RESTORE(restore.id));
const data = undefined as MenuRestoreCacheData<VALUE>;
// const data = await cache.get<MenuRestoreCacheData<VALUE>>(CACHE_KEY_RESTORE(restore.id));

if (data) {
// Position based value restoration
Expand Down Expand Up @@ -1249,14 +1250,14 @@ export function Menu<VALUE = unknown>({ config, terminal, internal, cache }: TSe
};
component.render();
done = undefined;
if (opt.restore) {
setImmediate(async () => {
await cache.set<MenuRestoreCacheData<VALUE>>(CACHE_KEY_RESTORE(opt.restore?.id), {
position: [selectedType, index],
value: GV(list[index]) ?? value,
});
});
}
// if (opt.restore) {
// setImmediate(async () => {
// await cache.set<MenuRestoreCacheData<VALUE>>(CACHE_KEY_RESTORE(opt.restore?.id), {
// position: [selectedType, index],
// value: GV(list[index]) ?? value,
// });
// });
// }
},

/**
Expand Down
53 changes: 37 additions & 16 deletions src/extensions/components/object-builder-component.extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
deepCloneArray,
deepExtend,
is,
SECOND,
sleep,
START,
TServiceParams,
Expand All @@ -26,13 +25,12 @@ type HelpText = {
};

const HELP_ERASE_SIZE = 3;
const DEFAULT_MESSAGE_TIMEOUT = 3;
const NORMAL_EXIT = Symbol();

export function ObjectBuilder<
VALUE extends object = Record<string, unknown>,
CANCEL extends unknown = never,
>({ terminal, internal }: TServiceParams) {
>({ terminal, internal, config }: TServiceParams) {
const { GV, template } = terminal.internals;

const CANCELLABLE: TTYComponentKeymap = new Map([
Expand Down Expand Up @@ -89,6 +87,7 @@ export function ObjectBuilder<
*/
let selectedRow = START;

// #MARK: dirtyProperties
function dirtyProperties(): (keyof VALUE)[] {
const original = opt.current ?? {};
const current = value;
Expand All @@ -100,6 +99,7 @@ export function ObjectBuilder<
.map(({ path }) => path);
}

// #MARK: headerMessage
function headerMessage(): string {
const { headerMessage } = opt;
if (is.string(headerMessage)) {
Expand All @@ -118,6 +118,7 @@ export function ObjectBuilder<
return ``;
}

// #MARK: helpNotes
function helpNotes(): string {
const { helpNotes } = opt;
if (is.string(helpNotes)) {
Expand All @@ -129,10 +130,12 @@ export function ObjectBuilder<
return `\n `;
}

// #MARK: columns
function columns() {
return opt.elements;
}

// #MARK: visibleColumns
function visibleColumns() {
return columns().filter(i => {
if (!i.hidden) {
Expand All @@ -155,6 +158,7 @@ export function ObjectBuilder<
*
* Immediate end, return cancel value
*/
// #MARK: cancel
function cancel(): void {
const { cancel, current } = opt;
if (is.function(cancel)) {
Expand All @@ -181,7 +185,7 @@ export function ObjectBuilder<
*/
sendMessage: async ({
message,
timeout = DEFAULT_MESSAGE_TIMEOUT,
timeout = config.terminal.DEFAULT_MESSAGE_TIMEOUT_MS,
position = "below-bar",
immediateClear = false,
}) => {
Expand All @@ -191,7 +195,7 @@ export function ObjectBuilder<
displayMessagePosition = position;
displayMessage = message;
component.render();
displayMessageTimeout = sleep(timeout * SECOND);
displayMessageTimeout = sleep(timeout);
await displayMessageTimeout;
displayMessage = undefined;
displayMessageTimeout = undefined;
Expand All @@ -209,6 +213,7 @@ export function ObjectBuilder<
/**
* keyboard event
*/
// #MARK: enableEdit
async function enableEdit(): Promise<void> {
await terminal.screen.footerWrap(async () => {
const column = visibleColumns()[selectedRow];
Expand Down Expand Up @@ -254,6 +259,7 @@ export function ObjectBuilder<
) as MainMenuEntry<VALUE | string>[];
updated = await terminal.prompt.pickMany<VALUE>({
current: selected,
items: column.items,
source,
});
break;
Expand Down Expand Up @@ -281,6 +287,7 @@ export function ObjectBuilder<
/**
* keyboard event
*/
// #MARK: onDown
function onDown(): void {
if (selectedRow === visibleColumns().length - ARRAY_OFFSET) {
onPageUp();
Expand All @@ -293,6 +300,7 @@ export function ObjectBuilder<
/**
* keyboard event
*/
// #MARK: onPageDown
function onPageDown(): void {
selectedRow = visibleColumns().length - ARRAY_OFFSET;
component.render();
Expand All @@ -301,6 +309,7 @@ export function ObjectBuilder<
/**
* keyboard event
*/
// #MARK: onPageUp
function onPageUp(): void {
selectedRow = START;
component.render();
Expand All @@ -309,6 +318,7 @@ export function ObjectBuilder<
/**
* keyboard event
*/
// #MARK: onUp
function onUp(): void {
if (selectedRow === START) {
onPageDown();
Expand All @@ -321,6 +331,7 @@ export function ObjectBuilder<
/**
* Undo any changes done during the current editing session
*/
// #MARK: resetField
async function resetField(): Promise<void> {
let value: boolean;
const field = visibleColumns()[selectedRow];
Expand Down Expand Up @@ -353,6 +364,7 @@ export function ObjectBuilder<
/**
* Terminate editor
*/
// #MARK: end
function end(code: unknown): void {
complete = true;
component.render();
Expand All @@ -376,6 +388,7 @@ export function ObjectBuilder<
);
}

// #MARK: setDefault
function setDefault(column: TableBuilderElement<VALUE>): void {
const current = internal.utils.object.get(value, column.path);
if (!is.undefined(current)) {
Expand Down Expand Up @@ -408,6 +421,7 @@ export function ObjectBuilder<
/**
* Build up a keymap to match the current conditions
*/
// #MARK: setKeymap
function setKeymap(): void {
const maps: TTYComponentKeymap[] = [];
maps.push(FORM_KEYMAP);
Expand All @@ -417,6 +431,7 @@ export function ObjectBuilder<
terminal.keyboard.setKeymap(this, ...maps);
}

// #MARK: <register>
const component = terminal.registry.registerComponent("object", {
configure(
config: ObjectBuilderOptions<VALUE, CANCEL>,
Expand Down Expand Up @@ -448,6 +463,7 @@ export function ObjectBuilder<
/**
* keyboard event
*/
// #MARK: onEnd
async onEnd(): Promise<void> {
const { validate, current } = opt;
if (is.function(validate)) {
Expand All @@ -465,7 +481,7 @@ export function ObjectBuilder<
original: current,
sendMessage: async ({
message,
timeout = DEFAULT_MESSAGE_TIMEOUT,
timeout = config.terminal.DEFAULT_MESSAGE_TIMEOUT_MS,
position = "below-bar",
immediateClear = false,
// TODO This shouldn't be a thing
Expand All @@ -476,7 +492,7 @@ export function ObjectBuilder<
displayMessagePosition = position;
displayMessage = message;
component.render();
displayMessageTimeout = sleep(timeout * SECOND);
displayMessageTimeout = sleep(timeout);
await displayMessageTimeout;
displayMessage = undefined;
displayMessageTimeout = undefined;
Expand All @@ -492,31 +508,36 @@ export function ObjectBuilder<
end(NORMAL_EXIT);
},

// #MARK: render
// eslint-disable-next-line sonarjs/cognitive-complexity
render(): void {
terminal.application.reprintHeader();
if (complete) {
terminal.screen.render("", "");
return;
}
const visible = visibleColumns();
const aboveBar =
displayMessagePosition === "above-bar" && !is.empty(displayMessage)
? { helpText: displayMessage }
: (visibleColumns()[selectedRow] as HelpText);
: (visible[selectedRow] as HelpText);

const belowBar =
displayMessagePosition === "below-bar" && !is.empty(displayMessage)
? displayMessage
: helpNotes();

const message = terminal.text.mergeHelp(
terminal.text.pad(
terminal.form.renderForm(
{ ...opt, elements: visibleColumns() },
value,
opt.current,
selectedRow,
),
),
is.empty(visible)
? chalk.red.bold("\nError: ") + chalk.yellow("no visible columns to render")
: terminal.text.pad(
terminal.form.renderForm(
{ ...opt, elements: visible },
value,
opt.current,
selectedRow,
),
),
aboveBar,
);

Expand Down
Loading

0 comments on commit 4bea3f5

Please sign in to comment.