Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support switching registry locally #203

Merged
merged 2 commits into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/slow-crabs-collect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'nrm': minor
---

Added set registry locally. Thanks @chouchouji
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Usage: nrm [options] [command]
current Show current registry name
-u --show-url Show the registry URL instead of the name
use [registry] Change registry to registry
-l --local Switch local registry
add <registry> <url> [home] Add one custom registry
login <registry> [value] Set authorize information for a registry with a base64 encoded string or username and password
-a --always-auth Set is always auth
Expand Down
17 changes: 14 additions & 3 deletions actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const open = require('open');
const chalk = require('chalk');
const select = require('@inquirer/select').default;
const { fetch } = require('undici');
const path = require('path');
const {
exit,
readFile,
Expand All @@ -15,6 +16,7 @@ const {
isRegistryNotFound,
isInternalRegistry,
} = require('./helpers');
const process = require('./process');

const { NRMRC, NPMRC, AUTH, EMAIL, ALWAYS_AUTH, REPOSITORY, REGISTRY, HOME } = require('./constants');

Expand Down Expand Up @@ -54,7 +56,7 @@ async function onCurrent({ showUrl }) {
printMessages([`You are using ${chalk.green(showUrl ? registry[REGISTRY] : name)} registry.`]);
}

async function onUse(name) {
async function onUse(name, { local }) {
const registries = await getRegistries();

// if name is undefined, select the registry alias from list
Expand All @@ -70,8 +72,17 @@ async function onUse(name) {
}

const registry = registries[name];
const npmrc = await readFile(NPMRC);
await writeFile(NPMRC, Object.assign(npmrc, registry));

if (local) {
// switch local registry
const localNPMRCPath = path.resolve(process.cwd(), '.npmrc');
const npmrc = await readFile(localNPMRCPath);
await writeFile(localNPMRCPath, Object.assign(npmrc, registry));
} else {
// switch global registry
const npmrc = await readFile(NPMRC);
await writeFile(NPMRC, Object.assign(npmrc, registry));
}

printSuccess(`The registry has been changed to '${name}'.`);
}
Expand Down
6 changes: 5 additions & 1 deletion cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ program
.description('Show current registry name or URL')
.action(actions.onCurrent);

program.command('use [name]').description('Change current registry').action(actions.onUse);
program
.command('use [name]')
.description('Change current registry')
.option('-l, --local', 'Switch local registry')
.action(actions.onUse);

program.command('add <name> <url> [home]').description('Add custom registry').action(actions.onAdd);

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"@changesets/cli": "^2.27.8",
"coffee": "^5.4.0",
"jest": "^27.4.0",
"mock-fs": "^5.4.1",
"prettier": "^3.3.3"
},
"engines": {
Expand Down
33 changes: 33 additions & 0 deletions tests/cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const chalk = require('chalk');
const { onHome, onTest } = require('.././actions.js');
const { spawn } = require('node:child_process');
const stripAnsi = require('strip-ansi');
const { readFile, writeFile } = require('.././helpers');
const { NPMRC, REGISTRIES } = require('.././constants');
const isWin = process.platform === 'win32';

jest.setTimeout(20000);
Expand Down Expand Up @@ -58,6 +60,37 @@ it('nrm use <registry>', async () => {
.end();
});

it('nrm use <registry> local', async () => {
await coffee
.spawn('nrm', ['use', 'cnpm', 'local'], { shell: isWin })
.expect('stdout', /The registry has been changed to 'cnpm'/g)
.expect('code', 0)
.end();

const npmrc = await readFile(NPMRC, { encoding: 'utf-8' });

expect(npmrc.registry).toBe(REGISTRIES.cnpm.registry);

await coffee.spawn('nrm', ['current'], { shell: isWin }).expect('stdout', /cnpm/g).expect('code', 0).end();
});

it('nrm use <registry> local with user config', async () => {
await writeFile(NPMRC, { abc: '123' });

await coffee
.spawn('nrm', ['use', 'cnpm', 'local'], { shell: isWin })
.expect('stdout', /The registry has been changed to 'cnpm'/g)
.expect('code', 0)
.end();

const npmrc = await readFile(NPMRC, { encoding: 'utf-8' });

expect(npmrc.registry).toBe(REGISTRIES.cnpm.registry);
expect(npmrc.abc).toBe('123');

await coffee.spawn('nrm', ['current'], { shell: isWin }).expect('stdout', /cnpm/g).expect('code', 0).end();
});

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

Expand Down
55 changes: 14 additions & 41 deletions tests/helpers.test.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,21 @@
const ini = require('ini');
const chalk = require('chalk');
const fs = require('fs');
const mockFs = require('mock-fs');

const helpers = require('.././helpers');

const { NPMRC, NRMRC, REGISTRY } = require('.././constants');

// ========== mock `fs` within helpers.js ==========

let mockedFiles = Object.create(null);

function writeFileSync(path, content) {
mockedFiles[path] = content;
}

jest.mock('fs', () => {
const originalModule = jest.requireActual('fs');

function readFileSync(path) {
return mockedFiles[path];
}

/* for jest scope, so same to above */
function writeFileSync(path, content) {
mockedFiles[path] = content;
}

function existsSync(path) {
return path in mockedFiles;
}

return {
...originalModule,
existsSync: jest.fn(existsSync),
readFileSync: jest.fn(readFileSync),
writeFileSync: jest.fn(writeFileSync),
};
beforeEach(() => {
mockFs({
[NPMRC]: '',
[NRMRC]: '',
});
});

// ========== test cases ==========

beforeEach(() => {
mockedFiles = Object.create(null);
mockedFiles[NPMRC] = '';
mockedFiles[NRMRC] = '';
afterEach(() => {
mockFs.restore();
});

it('geneDashLine', () => {
Expand All @@ -54,22 +27,22 @@ it('geneDashLine', () => {

it('getCurrentRegistry', async () => {
const registry = ' https://registry.npmjs.org/';
writeFileSync(NPMRC, ini.stringify({ [REGISTRY]: registry }));
fs.writeFileSync(NPMRC, ini.stringify({ [REGISTRY]: registry }));
const currentRegistry = await helpers.getCurrentRegistry();
expect(currentRegistry).toBe(registry);
});

it('getRegistries', async () => {
const name = 'fake name';
const registry = 'https://registry.example.com/';
writeFileSync(NRMRC, ini.stringify({ [name]: { registry } }));
fs.writeFileSync(NRMRC, ini.stringify({ [name]: { registry } }));
const registries = await helpers.getRegistries();
expect(Object.keys(registries).includes(name)).toBe(true);
});

it('readFile', async () => {
const content = 'hello nrm';
writeFileSync(NRMRC, ini.stringify({ content: content }));
fs.writeFileSync(NRMRC, ini.stringify({ content: content }));
const result1 = await helpers.readFile(NRMRC);
const result2 = await helpers.readFile('file not exist');
expect(result1.content).toBe(content);
Expand Down Expand Up @@ -98,7 +71,7 @@ it('isRegistryNotFound', async () => {
const unknown = 'unknown';
const name = 'custom name';
const registry = 'https://registry.example.com/';
writeFileSync(NRMRC, ini.stringify({ [name]: registry }));
fs.writeFileSync(NRMRC, ini.stringify({ [name]: registry }));
const result1 = await helpers.isRegistryNotFound(unknown, false);
const result2 = await helpers.isRegistryNotFound(name, false);
expect(result1).toBe(true);
Expand All @@ -108,7 +81,7 @@ it('isRegistryNotFound', async () => {
it('isInternalRegistry', async () => {
const name = 'custom name';
const registry = 'https://registry.example.com/';
writeFileSync(NRMRC, ini.stringify({ [name]: registry }));
fs.writeFileSync(NRMRC, ini.stringify({ [name]: registry }));
const result1 = await helpers.isInternalRegistry(name);
const result2 = await helpers.isInternalRegistry('npm');
expect(result1).toBe(false);
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2465,6 +2465,11 @@ minimatch@^3.0.4, minimatch@^3.1.1:
dependencies:
brace-expansion "^1.1.7"

mock-fs@^5.4.1:
version "5.4.1"
resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-5.4.1.tgz#b00abc658cb19dbbf282fde2f05bb751cd1e12a5"
integrity sha512-sz/Q8K1gXXXHR+qr0GZg2ysxCRr323kuN10O7CtQjraJsFDJ4SJ+0I5MzALz7aRp9lHk8Cc/YdsT95h9Ka1aFw==

mri@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
Expand Down