Skip to content

Commit

Permalink
Merge pull request #219 from chouchouji/feat-delete-multiple-registry
Browse files Browse the repository at this point in the history
feat: support deleting multiple custom registries
  • Loading branch information
iosh authored Dec 15, 2024
2 parents e1774b8 + b224d76 commit b449962
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .changeset/grumpy-bags-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"nrm": patch
---

Added delete multiple registry. Thanks @chouchouji
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Usage: nrm [options] [command]
set <registryName> Set custom registry attribute
-a --attr <attr> Set custom registry attribute
-v --value <value> Set custom registry value
del <registry> Delete one custom registry
del [registry] Delete one custom registry
rename <registryName> <newName> Set custom registry name
home <registry> [browser] Open the homepage of registry with optional browser
publish [<tarball>|<folder>] Publish package to current registry if current registry is a custom registry. The field 'repository' of current custom registry is required running this command. If you're not using custom registry, this command will run npm publish directly
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
},
"homepage": "https://github.com/Pana/nrm",
"dependencies": {
"@inquirer/checkbox": "^4.0.3",
"@inquirer/select": "^4.0.2",
"chalk": "4.1.2",
"commander": "^8.3.0",
Expand Down
36 changes: 36 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 49 additions & 18 deletions src/actions.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import checkbox from '@inquirer/checkbox';
import select from '@inquirer/select';
import chalk from 'chalk';
import open from 'open';
Expand Down Expand Up @@ -56,14 +57,18 @@ export async function onCurrent({ showUrl }: { showUrl: boolean }) {
if (!matchedRegistry) {
printMessages([
`Your current registry(${currentRegistry}) is not included in the nrm registries.`,
`Use the ${chalk.green('nrm add <registry> <url> [home]')} command to add your registry.`,
`Use the ${chalk.green(
'nrm add <registry> <url> [home]',
)} command to add your registry.`,
]);
return;
}

const [name, registry] = matchedRegistry;
printMessages([
`You are using ${chalk.green(showUrl ? registry[REGISTRY] : name)} registry.`,
`You are using ${chalk.green(
showUrl ? registry[REGISTRY] : name,
)} registry.`,
]);
}

Expand All @@ -73,7 +78,7 @@ export async function onUse(name: string) {

// if alias is undefined, select the registry alias from list
if (alias === undefined) {
alias = await select({
alias = await select<string>({
message: 'Please select the registry you want to use',
choices: Object.keys(registries),
pageSize: 10,
Expand All @@ -91,23 +96,45 @@ export async function onUse(name: string) {
printSuccess(`The registry has been changed to '${alias}'.`);
}

export async function onDelete(name: string) {
if (
(await isRegistryNotFound(name)) ||
(await isInternalRegistry(name, 'delete'))
) {
export async function onDelete(name: string | undefined) {
const customRegistries = await readFile(NRMRC);

const deleteKeys: string[] = [];
if (name) {
deleteKeys.push(name);
}

const choices = Object.keys(customRegistries);
if (name === undefined && !choices.length) {
printMessages(['No any custom registries can be deleted.']);
return;
}

const customRegistries = await readFile(NRMRC);
const registry = customRegistries[name];
delete customRegistries[name];
await writeFile(NRMRC, customRegistries);
printSuccess(`The registry '${name}' has been deleted successfully.`);
if (name === undefined) {
const selectedKeys = await checkbox<string>({
message: 'Please select the registries you want to delete',
choices,
});
deleteKeys.push(...selectedKeys);
}

const currentRegistry = await getCurrentRegistry();
if (currentRegistry === registry[REGISTRY]) {
await onUse('npm');
for (const key of deleteKeys) {
if (
(await isRegistryNotFound(key)) ||
(await isInternalRegistry(key, 'delete'))
) {
continue;
}

const registry = customRegistries[key];
delete customRegistries[key];
await writeFile(NRMRC, customRegistries);
printSuccess(`The registry '${key}' has been deleted successfully.`);

const currentRegistry = await getCurrentRegistry();
if (currentRegistry === registry[REGISTRY]) {
await onUse('npm');
}
}
}

Expand Down Expand Up @@ -135,7 +162,9 @@ export async function onAdd(name: string, url: string, home?: string) {
});
await writeFile(NRMRC, newCustomRegistries);
printSuccess(
`Add registry ${name} success, run ${chalk.green(`nrm use ${name}`)} command to use ${name} registry.`,
`Add registry ${name} success, run ${chalk.green(
`nrm use ${name}`,
)} command to use ${name} registry.`,
);
}

Expand Down Expand Up @@ -250,7 +279,9 @@ export async function onSetAttribute(

if (REPOSITORY === attr) {
return exit(
`Use the ${chalk.green('nrm set-hosted-repo <name> <repo>')} command to set repository.`,
`Use the ${chalk.green(
'nrm set-hosted-repo <name> <repo>',
)} command to set repository.`,
);
}
const customRegistries = await readFile(NRMRC);
Expand Down
21 changes: 18 additions & 3 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,7 @@ export function printError(error: string) {
}

export function printMessages(messages: string[]) {
for (const message of messages) {
console.log(message);
}
console.log(messages.join('\n'));
}

export function geneDashLine(message: string, length: number) {
Expand Down Expand Up @@ -105,3 +103,20 @@ export function exit(error?: string) {
error && printError(error);
process.exit(1);
}

export function isUnicodeSupported() {
if (process.platform !== 'win32') {
return process.env.TERM !== 'linux';
}

return (
Boolean(process.env.WT_SESSION) ||
Boolean(process.env.TERMINUS_SUBLIME) ||
process.env.ConEmuTask === '{cmd::Cmder}' ||
process.env.TERM_PROGRAM === 'Terminus-Sublime' ||
process.env.TERM_PROGRAM === 'vscode' ||
process.env.TERM === 'xterm-256color' ||
process.env.TERM === 'alacritty' ||
process.env.TERMINAL_EMULATOR === 'JetBrains-JediTerm'
);
}
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ program
.action(onRename);

program
.command('del <name>')
.command('del [name]')
.description('Delete custom registry')
.action(onDelete);

Expand Down
79 changes: 76 additions & 3 deletions tests/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,20 @@ import {
vi,
} from 'vitest';

import { unlink } from 'node:fs/promises';
import { onHome, onTest } from '../src/actions';
import { NPMRC, REGISTRIES } from '../src/constants';
import { readFile, writeFile } from '../src/helpers';
import { NPMRC, NRMRC, REGISTRIES } from '../src/constants';
import { isUnicodeSupported, readFile, writeFile } from '../src/helpers';


const isWin = process.platform === 'win32';

const shouldUseMain = isUnicodeSupported();

const pointer = shouldUseMain ? '❯' : '>';
const radioOff = shouldUseMain ? '◯' : '( )';
const radioOn = shouldUseMain ? '◉' : '(*)';

vi.setConfig({
testTimeout: 20000,
});
Expand Down Expand Up @@ -138,7 +146,7 @@ it('nrm use without argument', async () => {
expect(
message,
).toBe(`? Please select the registry you want to use (Use arrow keys)
${isWin ? '>' : '❯'} npm
${pointer} npm
yarn
tencent
cnpm
Expand Down Expand Up @@ -281,3 +289,68 @@ it('nrm home <registry> [browser]', async () => {
await onHome('cnpm');
expect(open).toHaveBeenCalled();
});

describe('nrm delete without argument (use keyword to select delete)', () => {
const registries = [
{ name: 'test', url: 'http://localhost:3000' },
{ name: 'test1', url: 'http://localhost:3001' },
{ name: 'test2', url: 'http://localhost:3002' },
];
beforeEach(async () => {
for (const registry of registries) {
await coffee
.spawn('nrm', ['add', `${registry.name}`, `${registry.url}`], {
shell: isWin,
})
.expect('stdout', /success/g)
.expect('code', 0)
.end();
}
});

afterEach(async () => {
await unlink(NRMRC);
});

it('nrm delete', async () => {
const { stdout } = spawn('nrm', ['del'], { shell: isWin });

const message = await new Promise((resolve) => {
stdout.on('data', (data) => {
resolve(stripAnsi(data.toString()).trim());
});
});

expect(message).toMatchInlineSnapshot(`
"? Please select the registries you want to delete (Press <space> to select, <a>
to toggle all, <i> to invert selection, and <enter> to proceed)
${pointer}${radioOff} test
${radioOff} test1
${radioOff} test2"
`);
});

it('nrm delete (with keyword input)', async () => {
const { stdout, stdin } = spawn('nrm', ['del'], { shell: isWin });
stdin.write('\u001b[B');

const message = await new Promise((resolve) => {
const m: string[] = [];
stdout.on('data', (data) => {
m.push(stripAnsi(data.toString()).trim());
// get the last output
if (m.length === 2) {
resolve(m[m.length - 1]);
}
});
});

expect(message).toMatchInlineSnapshot(`
"? Please select the registries you want to delete (Press <space> to select, <a>
to toggle all, <i> to invert selection, and <enter> to proceed)
${radioOff} test
${pointer}${radioOff} test1
${radioOff} test2"
`);
});
});

0 comments on commit b449962

Please sign in to comment.