Skip to content

Commit

Permalink
Require Node.js 18 and update dependencies (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
springcomp committed Feb 10, 2024
1 parent 9a84fe9 commit 6dd7c4c
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 27 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Expand Up @@ -10,8 +10,8 @@ jobs:
fail-fast: false
matrix:
node-version:
- 14
- 12
- 18
- 20
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
Expand Down
4 changes: 2 additions & 2 deletions index.d.ts
@@ -1,13 +1,13 @@
export class InvalidNameError extends Error {}

export interface Options {
export type Options = {
/**
Registry URL to check name availability against.
Default: User's configured npm registry URL.
*/
readonly registryUrl: string;
}
};

/**
Check whether a package/organization name is available (not registered) on npm.
Expand Down
21 changes: 10 additions & 11 deletions index.js
@@ -1,5 +1,5 @@
import isUrl from 'is-url-superb';
import got from 'got';
import ky from 'ky';
import isScoped from 'is-scoped';
import registryUrl from 'registry-url';
import registryAuthToken from 'registry-auth-token';
Expand All @@ -22,7 +22,7 @@ const request = async (name, options) => {

const isOrganization = organizationRegex.test(name);
if (isOrganization) {
name = name.replace(/[@/]/g, '');
name = name.replaceAll(/[@/]/g, '');
}

const isValid = validate(name);
Expand All @@ -38,26 +38,25 @@ const request = async (name, options) => {
let urlName = name;
const isScopedPackage = isScoped(name);
if (isScopedPackage) {
urlName = name.replace(/\//g, '%2f');
urlName = name.replaceAll('/', '%2f');
}

const authInfo = registryAuthToken(registryUrl, {recursive: true});
const headers = {};
if (authInfo) {
if (authInfo && !isOrganization) {
headers.authorization = `${authInfo.type} ${authInfo.token}`;
}

try {
// eslint-disable-next-line unicorn/prefer-ternary
let packageUrl = registryUrl + urlName.toLowerCase();
if (isOrganization) {
await got.head(npmOrganizationUrl + urlName.toLowerCase(), {timeout: 10000});
} else {
await got.head(registryUrl + urlName.toLowerCase(), {timeout: 10000, headers});
packageUrl = npmOrganizationUrl + urlName.toLowerCase();
}

await ky.head(packageUrl, {timeout: 10_000, headers});
return false;
} catch (error) {
const {statusCode} = error.response || {};
const statusCode = (error.response || {status: 500}).status;

if (statusCode === 404) {
// Disabled as it's often way too slow: https://github.com/sindresorhus/npm-name-cli/issues/30
Expand All @@ -82,7 +81,7 @@ export default async function npmName(name, options = {}) {
throw new Error('Package name required');
}

if (typeof options.registryUrl !== 'undefined' && !(typeof options.registryUrl === 'string' && isUrl(options.registryUrl))) {
if (options.registryUrl !== undefined && !(typeof options.registryUrl === 'string' && isUrl(options.registryUrl))) {
throw new Error('The `registryUrl` option must be a valid string URL');
}

Expand All @@ -94,7 +93,7 @@ export async function npmNameMany(names, options = {}) {
throw new TypeError(`Expected an array of names, got ${typeof names}`);
}

if (typeof options.registryUrl !== 'undefined' && !(typeof options.registryUrl === 'string' && isUrl(options.registryUrl))) {
if (options.registryUrl !== undefined && !(typeof options.registryUrl === 'string' && isUrl(options.registryUrl))) {
throw new Error('The `registryUrl` option must be a valid string URL');
}

Expand Down
8 changes: 5 additions & 3 deletions index.test-d.ts
Expand Up @@ -3,13 +3,15 @@ import npmName, {npmNameMany, InvalidNameError} from './index.js';

expectType<Promise<boolean>>(npmName('chalk'));
expectType<Promise<boolean>>(npmName('got', {
registryUrl: 'https://registry.yarnpkg.com/'
registryUrl: 'https://registry.yarnpkg.com/',
}));

const manyResult = npmNameMany(['chalk', '@sindresorhus/is', 'abc123']);
expectType<Promise<Map<'chalk' | '@sindresorhus/is' | 'abc123', boolean>>>(
manyResult
manyResult,
);
expectType<boolean | undefined>((await manyResult).get('chalk'));
const results = await manyResult;
const chalk = results.get('chalk');
expectType<boolean | undefined>(chalk);

expectType<InvalidNameError>(new InvalidNameError('foo'));
11 changes: 5 additions & 6 deletions package.json
Expand Up @@ -13,7 +13,7 @@
"type": "module",
"exports": "./index.js",
"engines": {
"node": ">=12"
"node": ">=18"
},
"scripts": {
"test": "xo && ava && tsd"
Expand All @@ -34,10 +34,9 @@
"taken"
],
"dependencies": {
"got": "^11.8.5",
"is-name-taken": "^2.0.0",
"is-scoped": "^3.0.0",
"is-url-superb": "^6.1.0",
"ky": "^1.2.0",
"lodash.zip": "^4.2.0",
"org-regex": "^1.0.0",
"p-map": "^5.5.0",
Expand All @@ -47,9 +46,9 @@
},
"devDependencies": {
"aggregate-error": "^4.0.0",
"ava": "^3.15.0",
"tsd": "^0.14.0",
"ava": "^6.1.1",
"tsd": "^0.30.4",
"unique-string": "^3.0.0",
"xo": "^0.38.2"
"xo": "^0.57.0"
}
}
6 changes: 3 additions & 3 deletions test.js
Expand Up @@ -43,7 +43,7 @@ test('registry url is normalized', async t => {

t.true(await npmName(moduleName, options));
t.true(await npmName(moduleName, {
registryUrl: registryUrl.slice(0, -1) // The `.slice()` removes the trailing `/` from the URL
registryUrl: registryUrl.slice(0, -1), // The `.slice()` removes the trailing `/` from the URL
}));
});

Expand All @@ -70,7 +70,7 @@ test('throws when package name is invalid', async t => {
instanceOf: InvalidNameError,
message: `Invalid package name: _ABC
- name can no longer contain capital letters
- name cannot start with an underscore`
- name cannot start with an underscore`,
});
});

Expand All @@ -81,7 +81,7 @@ test('should return an iterable error capturing multiple errors when appropriate
const name4 = 'CapitalsAreBad'; // Error

const aggregateError = await t.throwsAsync(npmNameMany([name1, name2, name3, name4]), {
instanceOf: AggregateError
instanceOf: AggregateError,
});

const errors = [...aggregateError.errors];
Expand Down

0 comments on commit 6dd7c4c

Please sign in to comment.