mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-08-06 14:05:18 +02:00
fix(lint): lint fixes
This commit is contained in:
parent
2e91373d6b
commit
e66702ec9f
5 changed files with 114 additions and 122 deletions
|
@ -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 }) => {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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<string, string> {
|
|||
const optionsObject: Record<string, string> = {};
|
||||
|
||||
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<string, string>, originalOptions: Record<string, string>, 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<string, string>, originalOpti
|
|||
// command
|
||||
originalOptions = Object.entries(options)
|
||||
.reduce((previousValue: Record<string, string>, currentValue: string[]) => {
|
||||
previousValue[currentValue[0]] = currentValue[1]
|
||||
previousValue[currentValue[0]] = currentValue[1];
|
||||
|
||||
return previousValue
|
||||
}, originalOptions)
|
||||
return previousValue;
|
||||
}, originalOptions);
|
||||
|
||||
const defaultValues: Record<string, string> = {};
|
||||
// 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<string, string>, 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<string, string>, originalOpti
|
|||
}
|
||||
|
||||
return editedCommand;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import * as service from "./cli-command-editor.service"
|
||||
const inputCommand = ref("");
|
||||
const options = computed(() => service.extractOptions(inputCommand.value));
|
||||
const optionsObject = computed(() => service.buildOptionsObject(options.value));
|
||||
const optionsInput = ref<{ [k: string]: string }>(optionsObject.value);
|
||||
let command = ref("");
|
||||
import * as service from './cli-command-editor.service';
|
||||
|
||||
const inputCommand = ref('');
|
||||
const options = computed(() => service.extractOptions(inputCommand.value));
|
||||
const optionsObject = computed(() => service.buildOptionsObject(options.value));
|
||||
const optionsInput = ref<{ [k: string]: string }>(optionsObject.value);
|
||||
const command = ref('');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -20,13 +21,11 @@
|
|||
:placeholder="$t('tools.cli-command-editor.placeholder')"
|
||||
:aria-placeholder="$t('tools.cli-command-editor.placeholder')"
|
||||
raw-text
|
||||
|
||||
@update:value="() => {command = inputCommand}"
|
||||
@update:value="() => { command = inputCommand }"
|
||||
/>
|
||||
<div v-for="option in options" flex justify-center>
|
||||
<div v-for="option in options" :key="option" flex justify-center>
|
||||
<c-input-text
|
||||
v-model:value="optionsInput[option]"
|
||||
:key="option"
|
||||
label-position="left"
|
||||
label-width="130px"
|
||||
label-align="left"
|
||||
|
@ -34,22 +33,19 @@
|
|||
:aria-label="service.sanitizeOption(option)"
|
||||
:placeholder="service.sanitizeOption(option)"
|
||||
:aria-placeholder="service.sanitizeOption(option)"
|
||||
@update:value="() => {command = service.buildEditedCommand(optionsInput, optionsObject, inputCommand)}"
|
||||
mt-6
|
||||
@update:value="() => { command = service.buildEditedCommand(optionsInput, optionsObject, inputCommand) }"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<c-text-copyable
|
||||
:value="command"
|
||||
v-if="command"
|
||||
:value="command"
|
||||
font-mono
|
||||
:show-icon="false"
|
||||
mt-6
|
||||
mt-6
|
||||
/>
|
||||
</n-gi>
|
||||
</n-grid>
|
||||
</c-card>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
</style>
|
|
@ -9,4 +9,4 @@ export const tool = defineTool({
|
|||
component: () => import('./cli-command-editor.vue'),
|
||||
icon: Terminal2,
|
||||
createdAt: new Date('2025-06-21'),
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue