diff --git a/src/tools/cli-command-editor/cli-command-editor.e2e.spec.ts b/src/tools/cli-command-editor/cli-command-editor.e2e.spec.ts index 15255768..b80e444b 100644 --- a/src/tools/cli-command-editor/cli-command-editor.e2e.spec.ts +++ b/src/tools/cli-command-editor/cli-command-editor.e2e.spec.ts @@ -1,4 +1,4 @@ -import { test, expect } from '@playwright/test'; +import { expect, test } from '@playwright/test'; test.describe('Tool - Cli command editor', () => { test.beforeEach(async ({ page }) => { @@ -8,8 +8,4 @@ test.describe('Tool - Cli command editor', () => { test('Has correct title', async ({ page }) => { await expect(page).toHaveTitle('Cli command editor - IT Tools'); }); - - test('', async ({ page }) => { - - }); -}); \ No newline at end of file +}); diff --git a/src/tools/cli-command-editor/cli-command-editor.service.test.ts b/src/tools/cli-command-editor/cli-command-editor.service.test.ts index 912db682..9524564a 100644 --- a/src/tools/cli-command-editor/cli-command-editor.service.test.ts +++ b/src/tools/cli-command-editor/cli-command-editor.service.test.ts @@ -1,140 +1,140 @@ -import { expect, describe, it } from 'vitest'; -import { extractOptions, buildOptionsObject, sanitizeOption, buildEditedCommand, isOption } from './cli-command-editor.service'; +import { describe, expect, it } from 'vitest'; +import { buildEditedCommand, buildOptionsObject, extractOptions, isOption, sanitizeOption } from './cli-command-editor.service'; describe('cli-command-editor', () => { - describe("extractOptions", () => { - it ("extracts all the options from a command", () => { + describe('extractOptions', () => { + it ('extracts all the options from a command', () => { expect( - extractOptions("aws elb describe-load-balancers --load-balancer-name my-load-balancer")[0] - ).toContain("--load-balancer-name"); + extractOptions('aws elb describe-load-balancers --load-balancer-name my-load-balancer')[0], + ).toContain('--load-balancer-name'); expect( - extractOptions("aws elb describe-load-balancers --load-balancer-name my-load-balancer --debug --query my-queryyy")[0] - ).toContain("--load-balancer-name"); + extractOptions('aws elb describe-load-balancers --load-balancer-name my-load-balancer --debug --query my-queryyy')[0], + ).toContain('--load-balancer-name'); expect( - extractOptions("aws elb describe-load-balancers --load-balancer-name my-load-balancer --debug --query my-queryyy")[1] - ).toContain("--debug"); + extractOptions('aws elb describe-load-balancers --load-balancer-name my-load-balancer --debug --query my-queryyy')[1], + ).toContain('--debug'); expect( - extractOptions("aws elb describe-load-balancers --load-balancer-name my-load-balancer --debug --query my-queryyy")[2] - ).toContain("--query"); + extractOptions('aws elb describe-load-balancers --load-balancer-name my-load-balancer --debug --query my-queryyy')[2], + ).toContain('--query'); }); - it("extracts all the option from a command with a mix of hyphen and double hyphens", () => { + it('extracts all the option from a command with a mix of hyphen and double hyphens', () => { expect( - extractOptions("npm i lodash -g --legacy-peer-deps")[0] - ).toContain("-g"); + extractOptions('npm i lodash -g --legacy-peer-deps')[0], + ).toContain('-g'); expect( - extractOptions("npm i lodash -g --legacy-peer-deps")[1] - ).toContain("--legacy-peer-deps"); + extractOptions('npm i lodash -g --legacy-peer-deps')[1], + ).toContain('--legacy-peer-deps'); }); - it("shouldn't extract any options from a command without options", () => { + it('shouldn\'t extract any options from a command without options', () => { expect( - extractOptions("npm i lodash") + extractOptions('npm i lodash'), ).toEqual([]); }); - it("shouldn't return any options if command is not passed", () => { + it('shouldn\'t return any options if command is not passed', () => { expect(extractOptions()).toEqual([]); }); }); - describe("buildOptionsObject", () => { - it("returns a valid options object with the given options", () => { + describe('buildOptionsObject', () => { + it('returns a valid options object with the given options', () => { expect( - buildOptionsObject(["--debug", "--load-balancer-names"]) + buildOptionsObject(['--debug', '--load-balancer-names']), ).toEqual({ - "--debug": "", - "--load-balancer-names": "", + '--debug': '', + '--load-balancer-names': '', }); }); - it("returns an empty obnject with blank options array", () => { + it('returns an empty obnject with blank options array', () => { expect( - buildOptionsObject([]) + buildOptionsObject([]), ).toEqual({}); }); }); - describe("sanitizeOption", () => { - it("returns the sanitized option without 'id' suffix", () => { - expect(sanitizeOption("--debug-id-1dfsj")) - .toEqual("--debug"); + describe('sanitizeOption', () => { + it('returns the sanitized option without `id` suffix', () => { + expect(sanitizeOption('--debug-id-1dfsj')) + .toEqual('--debug'); }); - it("returns the blank string", () => { - expect(sanitizeOption("")).toEqual(""); + it('returns the blank string', () => { + expect(sanitizeOption('')).toEqual(''); }); }); - describe("isOption", () => { - it("returns true for a valid double hyphen option token", () => { - expect(isOption("--debug")).toBe(true); + describe('isOption', () => { + it('returns true for a valid double hyphen option token', () => { + expect(isOption('--debug')).toBe(true); }); - it("returns true for a valid single hyphen option token", () => { - expect(isOption("-i")).toBe(true); + it('returns true for a valid single hyphen option token', () => { + expect(isOption('-i')).toBe(true); }); - it("returns false for an non-option token", () => { - expect(isOption("hello-world")).toBe(false); + it('returns false for an non-option token', () => { + expect(isOption('hello-world')).toBe(false); }); }); - describe("buildEditedCommand", () => { - it("returns the edited command", () => { + describe('buildEditedCommand', () => { + it('returns the edited command', () => { expect( buildEditedCommand({ - "--debug-id-1dfsj": "stdin", - "-p": "", - "-m": "nahhhh", + '--debug-id-1dfsj': 'stdin', + '-p': '', + '-m': 'nahhhh', }, { - "--debug-id-1dfsj": "stdin", - "-p": "", - "-m": "nahhhh", - }, "aws node --debug stdio -p -m okayyy") - ).toEqual("aws node --debug stdin -p -m nahhhh"); + '--debug-id-1dfsj': 'stdin', + '-p': '', + '-m': 'nahhhh', + }, 'aws node --debug stdio -p -m okayyy'), + ).toEqual('aws node --debug stdin -p -m nahhhh'); expect( buildEditedCommand({ - "-d-id-1dfsj": "", - "-p-id-fdsd": "4444:3333", - "-p-id-fddd": "3333:4444", - "--name-id-nnnn": "clickhouse-server", - "--ulimit-id-uuuu": "nofile=3333:4444", + '-d-id-1dfsj': '', + '-p-id-fdsd': '4444:3333', + '-p-id-fddd': '3333:4444', + '--name-id-nnnn': 'clickhouse-server', + '--ulimit-id-uuuu': 'nofile=3333:4444', }, { - "-d-id-1dfsj": "", - "-p-id-fdsd": "4444:3333", - "-p-id-fddd": "3333:4444", - "--name-id-nnnn": "clickhouse-server", - "--ulimit-id-uuuu": "nofile=3333:4444", - }, "docker run -d -p 18123:8123 -p 19000:9000 --name some-clickhouse-server --ulimit nofile=262144:262144 clickhouse/clickhouse-server") - ).toEqual("docker run -d -p 4444:3333 -p 3333:4444 --name clickhouse-server --ulimit nofile=3333:4444 clickhouse/clickhouse-server"); + '-d-id-1dfsj': '', + '-p-id-fdsd': '4444:3333', + '-p-id-fddd': '3333:4444', + '--name-id-nnnn': 'clickhouse-server', + '--ulimit-id-uuuu': 'nofile=3333:4444', + }, 'docker run -d -p 18123:8123 -p 19000:9000 --name some-clickhouse-server --ulimit nofile=262144:262144 clickhouse/clickhouse-server'), + ).toEqual('docker run -d -p 4444:3333 -p 3333:4444 --name clickhouse-server --ulimit nofile=3333:4444 clickhouse/clickhouse-server'); }); - it("returns the edited command when options object and CLI options order doesn't match", () => { + it('returns the edited command when options object and CLI options order doesn\'t match', () => { expect( buildEditedCommand({ - "-d-id-t1dd3": "true", - "--install-id-only123": "nodemon", + '-d-id-t1dd3': 'true', + '--install-id-only123': 'nodemon', }, { - "--install-id-only123": "nodem", - "-d-id-t1dd3": "false", - }, "npm --install nodem -d false") - ).toBe("npm --install nodemon -d true"); + '--install-id-only123': 'nodem', + '-d-id-t1dd3': 'false', + }, 'npm --install nodem -d false'), + ).toBe('npm --install nodemon -d true'); }); - it("returns the original command", () => { + it('returns the original command', () => { expect( - buildEditedCommand({}, {}, "npm install nodemon") - ).toBe("npm install nodemon"); + buildEditedCommand({}, {}, 'npm install nodemon'), + ).toBe('npm install nodemon'); expect( - buildEditedCommand({}, {}, "aws load-balancer describe-load-balancers all") - ).toBe("aws load-balancer describe-load-balancers all"); + buildEditedCommand({}, {}, 'aws load-balancer describe-load-balancers all'), + ).toBe('aws load-balancer describe-load-balancers all'); }); }); -}); \ No newline at end of file +}); diff --git a/src/tools/cli-command-editor/cli-command-editor.service.ts b/src/tools/cli-command-editor/cli-command-editor.service.ts index a4ec8c07..9793ac24 100644 --- a/src/tools/cli-command-editor/cli-command-editor.service.ts +++ b/src/tools/cli-command-editor/cli-command-editor.service.ts @@ -1,20 +1,17 @@ -import { generateRandomId } from "@/utils/random"; +import { generateRandomId } from '@/utils/random'; export function isOption(token: string): boolean { - return token?.startsWith("--") || token?.startsWith("-") + return token?.startsWith('--') || token?.startsWith('-'); } -export function extractOptions(command: string = ""): string[] { +export function extractOptions(command: string = ''): string[] { /* - aws elb describe-load-balancers --load-balancer-name my-load-balancer - npm i forever -g - docker run -d -p 18123:8123 -p 19000:9000 -e CLICKHOUSE_PASSWORD=changeme --name some-clickhouse-server --ulimit nofile=262144:262144 clickhouse/clickhouse-server - in a CLI, the options are either written with a hyphen or double hyphens, however, script names or package/library sometimes include a hyphen, too, for example 'describe-load-balancers' */ + // split into tokens first - const tokens = command.split(" "); + const tokens = command.split(' '); // map each token of the command to an option const options = tokens.map((token: string) => { @@ -24,7 +21,7 @@ export function extractOptions(command: string = ""): string[] { return `${token}-${randomId}`; } - return ""; + return ''; }).filter((option: string): boolean => !!option); return options; } @@ -33,20 +30,22 @@ export function buildOptionsObject(options: string[]): Record { const optionsObject: Record = {}; for (const option of options) { - optionsObject[option] = ""; + optionsObject[option] = ''; } return optionsObject; } export function sanitizeOption(option: string): string { - return option.split("-id")?.[0]; + return option.split('-id')?.[0]; } export function buildEditedCommand(options: Record, originalOptions: Record, command: string): string { - if (!Object.keys(options).length) return command; + if (!Object.keys(options).length) { + return command; + } - const tokens = command.split(" "); + const tokens = command.split(' '); const editedTokens = []; // user may input the option value in any order, from the form @@ -56,26 +55,26 @@ export function buildEditedCommand(options: Record, originalOpti // command originalOptions = Object.entries(options) .reduce((previousValue: Record, currentValue: string[]) => { - previousValue[currentValue[0]] = currentValue[1] + previousValue[currentValue[0]] = currentValue[1]; - return previousValue - }, originalOptions) + return previousValue; + }, originalOptions); const defaultValues: Record = {}; // replacing the options and their values (if any) with formatter ($i) to // help in interpolation of the command for (let i = 0, j = 0, n = tokens.length; i < n; ++i) { const token = tokens[i]; - const nextToken = tokens[i+1]; + const nextToken = tokens[i + 1]; if (isOption(token)) { - editedTokens.push(`$${j}`) + editedTokens.push(`$${j}`); if (!isOption(nextToken)) { ++i; defaultValues[`$${j}`] = nextToken; } - + ++j; continue; } @@ -83,17 +82,18 @@ export function buildEditedCommand(options: Record, originalOpti editedTokens.push(token); } - let editedCommand = editedTokens.join(" "); + let editedCommand = editedTokens.join(' '); const originalOptionKeys = Object.keys(originalOptions); for (let i = 0, n = originalOptionKeys.length; i < n; ++i) { const key = originalOptionKeys[i]; - const keyWithoutIdSuffix = key.split("-id-")[0] || key; - + const keyWithoutIdSuffix = key.split('-id-')[0] || key; + if (originalOptions[key]) { editedCommand = editedCommand.replace(`$${i}`, `${keyWithoutIdSuffix} ${originalOptions[key]}`); - } else { + } + else { const value = defaultValues[`$${i}`]; const replaceValue = value ? `${keyWithoutIdSuffix} ${value}` : keyWithoutIdSuffix; editedCommand = editedCommand.replace(`$${i}`, replaceValue); @@ -101,4 +101,4 @@ export function buildEditedCommand(options: Record, originalOpti } return editedCommand; -} \ No newline at end of file +} diff --git a/src/tools/cli-command-editor/cli-command-editor.vue b/src/tools/cli-command-editor/cli-command-editor.vue index 189384bb..8ed0b2c2 100644 --- a/src/tools/cli-command-editor/cli-command-editor.vue +++ b/src/tools/cli-command-editor/cli-command-editor.vue @@ -1,10 +1,11 @@ - - \ No newline at end of file diff --git a/src/tools/cli-command-editor/index.ts b/src/tools/cli-command-editor/index.ts index a47a70e8..32d6cdb9 100644 --- a/src/tools/cli-command-editor/index.ts +++ b/src/tools/cli-command-editor/index.ts @@ -9,4 +9,4 @@ export const tool = defineTool({ component: () => import('./cli-command-editor.vue'), icon: Terminal2, createdAt: new Date('2025-06-21'), -}); \ No newline at end of file +});