0
# mlly
1
2
mlly provides essential ECMAScript Module (ESM) utilities for Node.js that fill gaps in the evolving ESM ecosystem. It offers comprehensive module resolution capabilities respecting the ECMAScript Resolver algorithm with support for custom extensions and conditions, syntax analysis tools to detect ESM/CommonJS usage and validate Node.js imports, import/export parsing with regex-based static analysis for finding and parsing import/export statements, CommonJS context creation for missing utilities like __dirname and require in ESM, module evaluation capabilities using data: imports with automatic import rewriting and stack-trace support, and various utility functions for path/URL conversion, protocol normalization, and URI sanitization.
3
4
## Package Information
5
6
- **Package Name**: mlly
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install mlly`
10
11
## Core Imports
12
13
```typescript
14
import {
15
resolve,
16
findStaticImports,
17
findExports,
18
hasESMSyntax,
19
isValidNodeImport,
20
createCommonJS,
21
loadModule,
22
fileURLToPath
23
} from "mlly";
24
```
25
26
For CommonJS:
27
28
```javascript
29
const {
30
resolve,
31
findStaticImports,
32
findExports,
33
hasESMSyntax,
34
isValidNodeImport,
35
createCommonJS,
36
loadModule,
37
fileURLToPath
38
} = require("mlly");
39
```
40
41
## Basic Usage
42
43
```typescript
44
import {
45
resolve,
46
findStaticImports,
47
findExports,
48
hasESMSyntax,
49
isValidNodeImport,
50
createCommonJS,
51
loadModule
52
} from "mlly";
53
54
// Module resolution
55
const moduleUrl = await resolve("./utils.mjs", { url: import.meta.url });
56
57
// Import analysis
58
const imports = findStaticImports(`import { foo } from "./bar.mjs"`);
59
console.log(imports[0].specifier); // "./bar.mjs"
60
61
// Export analysis
62
const exports = findExports(`export const hello = "world"; export default 42;`);
63
console.log(exports.map(exp => exp.names).flat()); // ["hello", "default"]
64
65
// Syntax detection
66
const isESM = hasESMSyntax(`export const hello = "world"`); // true
67
const canImport = await isValidNodeImport("some-package");
68
69
// CommonJS context in ESM
70
const { __dirname, __filename, require } = createCommonJS(import.meta.url);
71
72
// Module evaluation
73
const module = await loadModule("./config.json", { url: import.meta.url });
74
```
75
76
## Architecture
77
78
mlly is built around several key components:
79
80
- **Module Resolution**: ECMAScript-compliant resolver with Node.js extensions support
81
- **Static Analysis**: Regex-based parsing engine for imports/exports without AST overhead
82
- **Syntax Detection**: Heuristic-based identification of ESM vs CommonJS patterns
83
- **Module Evaluation**: Safe code execution using data: URLs with import rewriting
84
- **CommonJS Bridge**: Compatibility layer providing Node.js CommonJS utilities in ESM
85
- **Path/URL Utilities**: Cross-platform normalization and protocol handling
86
87
## Capabilities
88
89
### Module Resolution
90
91
ESM-compliant module resolution with support for custom conditions, extensions, and multiple search paths. Handles Node.js built-ins, file system paths, and various URL protocols.
92
93
```typescript { .api }
94
function resolve(id: string, options?: ResolveOptions): Promise<string>;
95
function resolveSync(id: string, options?: ResolveOptions): string;
96
97
interface ResolveOptions {
98
url?: string | URL | (string | URL)[];
99
extensions?: string[];
100
conditions?: string[];
101
}
102
```
103
104
[Module Resolution](./module-resolution.md)
105
106
### Import/Export Analysis
107
108
Fast regex-based static analysis for finding and parsing ECMAScript import and export statements. Supports static imports, dynamic imports, type imports, and all export patterns.
109
110
```typescript { .api }
111
function findStaticImports(code: string): StaticImport[];
112
function findDynamicImports(code: string): DynamicImport[];
113
function findExports(code: string): ESMExport[];
114
function parseStaticImport(matched: StaticImport | TypeImport): ParsedStaticImport;
115
function findExportNames(code: string): string[];
116
function resolveModuleExportNames(id: string, options?: ResolveOptions): Promise<string[]>;
117
118
interface StaticImport {
119
type: "static";
120
code: string;
121
start: number;
122
end: number;
123
imports: string;
124
specifier: string;
125
}
126
```
127
128
[Import/Export Analysis](./import-export-analysis.md)
129
130
### Syntax Detection
131
132
Utilities for detecting ECMAScript module syntax, CommonJS syntax, and validating whether imports are safe for dynamic import() calls in Node.js.
133
134
```typescript { .api }
135
function hasESMSyntax(code: string, opts?: DetectSyntaxOptions): boolean;
136
function hasCJSSyntax(code: string, opts?: DetectSyntaxOptions): boolean;
137
function detectSyntax(code: string, opts?: DetectSyntaxOptions): { hasESM: boolean; hasCJS: boolean; isMixed: boolean };
138
function isValidNodeImport(id: string, options?: ValidNodeImportOptions): Promise<boolean>;
139
140
interface DetectSyntaxOptions {
141
stripComments?: boolean;
142
}
143
```
144
145
[Syntax Detection](./syntax-detection.md)
146
147
### Module Evaluation
148
149
Safe module evaluation using data: URLs with automatic import resolution and stack trace preservation. Includes transformation utilities for JSON modules and import.meta.url rewriting.
150
151
```typescript { .api }
152
function loadModule(id: string, options?: EvaluateOptions): Promise<any>;
153
function evalModule(code: string, options?: EvaluateOptions): Promise<any>;
154
function transformModule(code: string, options?: EvaluateOptions): Promise<string>;
155
function resolveImports(code: string, options?: EvaluateOptions): Promise<string>;
156
157
interface EvaluateOptions extends ResolveOptions {
158
url?: string;
159
}
160
```
161
162
[Module Evaluation](./module-evaluation.md)
163
164
### CommonJS Context
165
166
Utilities for creating CommonJS-compatible context within ECMAScript modules, providing __dirname, __filename, and require functionality.
167
168
```typescript { .api }
169
function createCommonJS(url: string): CommonjsContext;
170
function interopDefault(sourceModule: any, opts?: { preferNamespace?: boolean }): any;
171
172
interface CommonjsContext {
173
__filename: string;
174
__dirname: string;
175
require: NodeRequire;
176
}
177
```
178
179
[CommonJS Context](./commonjs-context.md)
180
181
### Utility Functions
182
183
Core utilities for path/URL conversion, protocol handling, URI sanitization, and Node.js built-in detection. Cross-platform file system path normalization.
184
185
```typescript { .api }
186
function fileURLToPath(id: string | URL): string;
187
function pathToFileURL(id: string | URL): string;
188
function isNodeBuiltin(id?: string): boolean;
189
function loadURL(url: string): Promise<string>;
190
function toDataURL(code: string): string;
191
function normalizeid(id: string): string;
192
function sanitizeURIComponent(name?: string, replacement?: string): string;
193
function sanitizeFilePath(filePath?: string): string;
194
function getProtocol(id: string): string | undefined;
195
```
196
197
[Utility Functions](./utility-functions.md)
198
199
## Core Types
200
201
```typescript { .api }
202
interface ResolveOptions {
203
url?: string | URL | (string | URL)[];
204
extensions?: string[];
205
conditions?: string[];
206
}
207
208
interface ESMImport {
209
type: "static" | "dynamic";
210
code: string;
211
start: number;
212
end: number;
213
}
214
215
interface StaticImport extends ESMImport {
216
type: "static";
217
imports: string;
218
specifier: string;
219
}
220
221
interface ParsedStaticImport extends StaticImport {
222
defaultImport?: string;
223
namespacedImport?: string;
224
namedImports?: { [name: string]: string };
225
}
226
227
interface DynamicImport extends ESMImport {
228
type: "dynamic";
229
expression: string;
230
}
231
232
interface TypeImport extends Omit<ESMImport, "type"> {
233
type: "type";
234
imports: string;
235
specifier: string;
236
}
237
238
interface ESMExport {
239
type: "declaration" | "named" | "default" | "star";
240
code: string;
241
start: number;
242
end: number;
243
name?: string;
244
names: string[];
245
specifier?: string;
246
}
247
248
interface ValidNodeImportOptions extends ResolveOptions {
249
code?: string;
250
allowedProtocols?: Array<string>;
251
stripComments?: boolean;
252
}
253
```