Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

module-alias

Package Overview
Dependencies
Maintainers
2
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

module-alias - npm Package Compare versions

Comparing version
2.2.3
to
2.3.0
+148
esm-loader.mjs
// ESM loader for module-alias
// Provides resolve hooks for ES modules
import { readFileSync, existsSync, statSync } from 'node:fs'
import { join, resolve as pathResolve, dirname } from 'node:path'
import { fileURLToPath, pathToFileURL } from 'node:url'
let aliases = {}
let moduleDirectories = []
let base = process.cwd()
let initialized = false
export function init (options = {}) {
if (initialized) return
const thisDir = dirname(fileURLToPath(import.meta.url))
const candidatePaths = options.base
? [pathResolve(options.base)]
: [join(thisDir, '../..'), process.cwd()]
let pkg
for (const candidate of candidatePaths) {
try {
pkg = JSON.parse(readFileSync(join(candidate, 'package.json'), 'utf8'))
base = candidate
break
} catch (e) {
// Continue to next candidate
}
}
if (!pkg) {
console.warn('[module-alias] Unable to find package.json in:', candidatePaths.join(', '))
initialized = true
return
}
// Load _moduleAliases
const pkgAliases = pkg._moduleAliases || {}
for (const alias in pkgAliases) {
const target = pkgAliases[alias]
aliases[alias] = target.startsWith('/') ? target : join(base, target)
}
// Load _moduleDirectories
if (Array.isArray(pkg._moduleDirectories)) {
moduleDirectories = pkg._moduleDirectories
.filter(d => d !== 'node_modules')
.map(d => join(base, d))
}
initialized = true
}
export function isPathMatchesAlias (path, alias) {
// Matching /^alias(\/|$)/
if (path.indexOf(alias) === 0) {
if (path.length === alias.length) return true
if (path[alias.length] === '/') return true
}
return false
}
export function resolveAlias (specifier, parentURL) {
init() // Ensure initialized
// Sort aliases by length (longest first) for correct matching
const sortedAliases = Object.keys(aliases).sort((a, b) => b.length - a.length)
for (const alias of sortedAliases) {
if (isPathMatchesAlias(specifier, alias)) {
const target = aliases[alias]
// Function-based resolver
if (typeof target === 'function') {
const parentPath = parentURL ? fileURLToPath(parentURL) : process.cwd()
const result = target(parentPath, specifier, alias)
if (!result || typeof result !== 'string') {
throw new Error('[module-alias] Custom handler must return path')
}
return result
}
// String path - join target with remainder of specifier
return join(target, specifier.slice(alias.length))
}
}
// Check moduleDirectories
for (const dir of moduleDirectories) {
const modulePath = join(dir, specifier)
// Check for directory with index.mjs/index.js
if (existsSync(join(modulePath, 'index.mjs'))) {
return join(modulePath, 'index.mjs')
}
if (existsSync(join(modulePath, 'index.js'))) {
return join(modulePath, 'index.js')
}
// Check for file with extension
if (existsSync(modulePath + '.mjs')) {
return modulePath + '.mjs'
}
if (existsSync(modulePath + '.js')) {
return modulePath + '.js'
}
// Check for exact file
if (existsSync(modulePath) && !statSync(modulePath).isDirectory()) {
return modulePath
}
}
return null
}
export function addAlias (alias, target) {
aliases[alias] = target
}
export function addAliases (aliasMap) {
for (const alias in aliasMap) {
addAlias(alias, aliasMap[alias])
}
}
export function reset () {
aliases = {}
moduleDirectories = []
base = process.cwd()
initialized = false
}
// For Node 18-21: async loader hooks
export async function resolve (specifier, context, nextResolve) {
const resolved = resolveAlias(specifier, context.parentURL)
if (resolved) {
// If absolute path, convert to file URL
if (resolved.startsWith('/')) {
return { url: pathToFileURL(resolved).href, shortCircuit: true }
}
// Otherwise let Node resolve it (could be npm package)
return nextResolve(resolved, context)
}
return nextResolve(specifier, context)
}
export async function initialize (data) {
init(data || {})
}
// ESM entry point for module-alias
// Usage: node --import module-alias/register ./app.mjs
import { register } from 'node:module'
// Check Node version for registerHooks support (22.15+)
const [major, minor] = process.versions.node.split('.').map(Number)
const hasRegisterHooks = major > 22 || (major === 22 && minor >= 15)
if (hasRegisterHooks) {
// Node 22.15+ - use synchronous hooks on main thread
const { registerHooks } = await import('node:module')
const { resolveAlias, init } = await import('./esm-loader.mjs')
init()
registerHooks({
resolve (specifier, context, nextResolve) {
const resolved = resolveAlias(specifier, context.parentURL)
if (resolved) {
return nextResolve(resolved, context)
}
return nextResolve(specifier, context)
}
})
} else {
// Node 18.19 - 22.14 - use async hooks via worker thread
register('./esm-loader.mjs', {
parentURL: import.meta.url
})
}
+15
-1
{
"name": "module-alias",
"description": "Create aliases of directories and register custom module paths",
"version": "2.2.3",
"version": "2.3.0",
"author": {

@@ -13,2 +13,4 @@ "name": "Nick Gavrilov",

"testonly-watch": "NODE_ENV=test mocha -w test/specs.js",
"test:esm": "NODE_ENV=test mocha test/esm/unit.mjs test/esm/integration.js",
"test:all": "npm run testonly && npm run test:esm",
"lint": "standard"

@@ -29,5 +31,17 @@ },

"main": "index.js",
"exports": {
".": {
"require": "./index.js",
"import": "./index.js"
},
"./register": {
"require": "./register.js",
"import": "./register.mjs"
}
},
"files": [
"index.js",
"register.js",
"register.mjs",
"esm-loader.mjs",
"README.md",

@@ -34,0 +48,0 @@ "LICENSE"

@@ -47,2 +47,4 @@ # module-alias

### CommonJS (require)
Add your custom configuration to your `package.json` (in your application's root)

@@ -84,2 +86,41 @@

### ES Modules (import) - Node 18+
For native ES modules, use the `--import` flag:
```bash
node --import module-alias/register ./app.mjs
```
Your `package.json` configuration works the same way:
```json
{
"_moduleAliases": {
"@lib": "src/lib",
"@utils": "src/utils"
}
}
```
Then in your ES module:
```js
import { something } from '@lib/something.js'
```
**Node Version Support:**
| Node Version | API Used |
|--------------|----------|
| 22.15+ | `module.registerHooks()` (sync, recommended) |
| 18.19 - 22.14 | `module.register()` (async) |
| < 18.19 | Not supported for ESM |
**ESM Limitations:**
- Requires `--import` flag - cannot be imported at runtime like CJS
- Programmatic `addAlias()` not available before app starts
- Function-based resolvers must be configured via the loader API
## Advanced usage

@@ -86,0 +127,0 @@