diff --git a/src/deps.ts b/src/deps.ts index a3bb5c6044..235b8963a8 100644 --- a/src/deps.ts +++ b/src/deps.ts @@ -94,8 +94,10 @@ const importRe = [ /\brequire\(['"](?[^'"]+)['"]\)/, /\bfrom\s+['"](?[^'"]+)['"]/, ] -const nameRe = /^(?(@[a-z0-9-]+\/)?[a-z0-9-.]+)\/?.*$/i -const versionRe = /(\/\/|\/\*)\s*@(?[~^]?([\dvx*]+([-.][\dx*]+)*))/i +const nameRe = + /^(?(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*)\/?.*$/i +const versionRe = + /(\/\/|\/\*)\s*@(?[~^]?(v?[\dx*]+([-.][\d*a-z-]+)*))/i export function parseDeps(content: Buffer): Record { const deps: Record = {} diff --git a/test/deps.test.js b/test/deps.test.js index c03aec18f7..c0e75b6a05 100644 --- a/test/deps.test.js +++ b/test/deps.test.js @@ -37,11 +37,35 @@ test('installDeps() loader works via CLI', async () => { }) test('parseDeps(): import or require', async () => { - assert.equal(parseDeps(`import "foo"`), { foo: 'latest' }) - assert.equal(parseDeps(`import * as bar from "foo"`), { foo: 'latest' }) - assert.equal(parseDeps(`import('foo')`), { foo: 'latest' }) - assert.equal(parseDeps(`require('foo')`), { foo: 'latest' }) - assert.equal(parseDeps(`require('foo.js')`), { 'foo.js': 'latest' }) + ;[ + [`import "foo"`, { foo: 'latest' }], + [`import "foo"`, { foo: 'latest' }], + [`import * as bar from "foo"`, { foo: 'latest' }], + [`import('foo')`, { foo: 'latest' }], + [`require('foo')`, { foo: 'latest' }], + [`require('foo/bar')`, { foo: 'latest' }], + [`require('foo/bar.js')`, { foo: 'latest' }], + [`require('foo-bar')`, { 'foo-bar': 'latest' }], + [`require('foo_bar')`, { foo_bar: 'latest' }], + [`require('@foo/bar')`, { '@foo/bar': 'latest' }], + [`require('@foo/bar/baz')`, { '@foo/bar': 'latest' }], + [`require('foo.js')`, { 'foo.js': 'latest' }], + + // ignores local deps + [`import '.'`, {}], + [`require('.')`, {}], + [`require('..')`, {}], + [`require('../foo.js')`, {}], + [`require('./foo.js')`, {}], + + // ignores invalid pkg names + [`require('_foo')`, {}], + [`require('@')`, {}], + [`require('@/_foo')`, {}], + [`require('@foo')`, {}], + ].forEach(([input, result]) => { + assert.equal(parseDeps(input), result) + }) }) test('parseDeps(): import with org and filename', async () => { @@ -74,6 +98,8 @@ test('parseDeps(): multiline', () => { import foo from "foo" import bar from "bar" /* @1.0.0 */ import baz from "baz" // @^2.0 + import qux from "@qux/pkg/entry" // @^3.0 + import {api as alias} from "qux/entry/index.js" // @^4.0.0-beta.0 const cpy = await import('cpy') const { pick } = require("lodash") // @4.17.15 @@ -93,6 +119,8 @@ test('parseDeps(): multiline', () => { foo: 'latest', bar: '1.0.0', baz: '^2.0', + '@qux/pkg': '^3.0', + qux: '^4.0.0-beta.0', cpy: 'latest', lodash: '4.17.15', })