Skip to content

Commit

Permalink
Add support for --import with register()
Browse files Browse the repository at this point in the history
  • Loading branch information
barhun committed Oct 16, 2023
1 parent cd19109 commit f6b5de0
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 29 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 19
node-version: 20.6
- run: npm ci
- run: npm test

Expand All @@ -26,7 +26,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 19
node-version: 20.6
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm publish
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ npm i extensionless

 

Start `node` with the following flag added:
Start `node` with one of the following flags added. If you're running on a version of node older than `20.6.0`, use:

```
--experimental-loader=extensionless
```

or else, use the newer one instead:

```
--import=extensionless/register
```

 

You can now use import specifiers as file paths without extensions or as directory paths:
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{
"name": "extensionless",
"version": "1.4.5",
"version": "1.5.6",
"type": "module",
"main": "src/index.js",
"exports": {
".": "./src/index.js",
"./register": "./src/register.js"
},
"license": "MIT",
"description": "Node.js loader for import specifiers as file paths without extensions or as directory paths",
"keywords": [
Expand All @@ -17,6 +20,6 @@
"url": "git+https://github.com/barhun/extensionless.git"
},
"scripts": {
"test": "node --experimental-loader=./src/index.js test"
"test": "node --import=./src/register.js test"
}
}
40 changes: 22 additions & 18 deletions src/config.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
import {readFile} from 'fs/promises'
import {dirname, isAbsolute, join} from 'path'
import {argv, cwd} from 'process'
import {cwd} from 'process'

let pkgJson = await (async () => {
let curDir, upDir = isAbsolute(argv[1] ?? '') ? argv[1] : cwd()
let warn = (field, desc) => console.warn('⚠️ \x1b[33m%s\x1b[0m',
`Warning: The package.json field 'extensionless.${field}' must be ${desc}! Using the default value instead...`
)

let getPkgJson = async argv1 => {
let path = isAbsolute(argv1 ?? '') ? argv1 : cwd()

do {
try {
return JSON.parse(await readFile(join(curDir = upDir, 'package.json'), 'utf8'))
return JSON.parse(await readFile(join(path, 'package.json'), 'utf8'))
} catch (e) {
if (!['ENOTDIR', 'ENOENT', 'EISDIR'].includes(e.code)) {
throw new Error('Cannot retrieve package.json', {cause: e})
}
}
} while (curDir !== (upDir = dirname(curDir)))
})()

let warn = (field, desc) => console.warn('⚠️ \x1b[33m%s\x1b[0m', `Warning: The package.json field 'extensionless.${field}' must be ${desc}! Using the default value instead...`)
} while (path !== (path = dirname(path)))
}

let defaults = {
lookFor: ['js']
}, {
lookFor
} = {...defaults, ...pkgJson?.extensionless}
export async function getConfig({argv1} = {}) {
let defaults = {
lookFor: ['js']
}, {
lookFor
} = {...defaults, ...(await getPkgJson(argv1))?.extensionless}

Array.isArray(lookFor) && lookFor.length && lookFor.every(a => typeof a === 'string' && /^[a-z]+\w*$/i.test(a)) || (
lookFor = defaults.lookFor, warn('lookFor', 'an array of alphanumeric strings')
)
Array.isArray(lookFor) && lookFor.length && lookFor.every(a => typeof a === 'string' && /^[a-z]+\w*$/i.test(a)) || (
lookFor = defaults.lookFor, warn('lookFor', 'an array of alphanumeric strings')
)

export {
lookFor
return {
lookFor
}
}
19 changes: 16 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import {extname, isAbsolute} from 'path'
import {lookFor} from './config.js'
import {getConfig} from './config.js'

let indexFiles = [lookFor.map(e => `index.${e}`), ['index.json']]
let candidates = indexFiles.map(i => i.map(f => extname(f)).concat(i.map(f => `/${f}`)))
let initPromise
export function globalPreload({port}) {
port.onmessage = e => initPromise = initialize({argv1: e.data})

return 'port.postMessage(process.argv[1])'
}

let indexFiles, candidates
export async function initialize(data) {
let {lookFor} = await getConfig(data)

indexFiles = [lookFor.map(e => `index.${e}`), ['index.json']]
candidates = indexFiles.map(i => i.map(f => extname(f)).concat(i.map(f => `/${f}`)))
}

let relSpecs = ['.', '..'], prefixes = ['./', '../', 'file://', '.\\', '..\\']
let extToSkip = ['.js', '.cjs', '.mjs', '.json', '.node', '.wasm'], empty = [[], []]
Expand All @@ -14,6 +26,7 @@ export async function resolve(specifier, {importAssertions, parentURL}, nextReso
return await nextResolve(specifier)
}

await initPromise
let selfURL = new URL((isAbs ? 'file://' : '') + specifier, parentURL).href
let postfixes = selfURL.endsWith('/') ? indexFiles : extToSkip.includes(extname(selfURL)) ? empty : candidates

Expand Down
4 changes: 4 additions & 0 deletions src/register.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {register} from 'module'
import {argv} from 'process'

register('./index.js', import.meta.url, {data: {argv1: argv[1]}})
File renamed without changes.

0 comments on commit f6b5de0

Please sign in to comment.