Using various syntax detection and heuristics, this method can determine if import is a valid import or not to be imported using dynamic `import()` before hitting an error!
When result is `false`, we usually need a to create a CommonJS require context or add specific rules to the bundler to transform dependency.
```js
import { isValidNodeImport } from "mlly";
// If returns true, we are safe to use `import('some-lib')`
await isValidNodeImport("some-lib", {});
```
**Algorithm:**
- Check import protocol - If is `data:` return `true` (✅ valid) - If is not `node:`, `file:` or `data:`, return `false` (
❌ invalid)
- Resolve full path of import using Node.js [Resolution algorithm](https://nodejs.org/api/esm.html#resolution-algorithm)
- Check full path extension
- If is `.mjs`, `.cjs`, `.node` or `.wasm`, return `true` (✅ valid)
- If is not `.js`, return `false` (❌ invalid)
- If is matching known mixed syntax (`.esm.js`, `.es.js`, etc) return `false` (
❌ invalid)
- Read closest `package.json` file to resolve path
- If `type: 'module'` field is set, return `true` (✅ valid)
- Read source code of resolved path
- Try to detect CommonJS syntax usage
- If yes, return `true` (✅ valid)
- Try to detect ESM syntax usage
- if yes, return `false` (
❌ invalid)
**Notes:**
- There might be still edge cases algorithm cannot cover. It is designed with best-efforts.
- This method also allows using dynamic import of CommonJS libraries considering
Node.js has [Interoperability with CommonJS](https://nodejs.org/api/esm.html#interoperability-with-commonjs).
### `hasESMSyntax`
Detect if code, has usage of ESM syntax (Static `import`, ESM `export` and `import.meta` usage)
```js
import { hasESMSyntax } from "mlly";
hasESMSyntax("export default foo = 123"); // true
```
### `hasCJSSyntax`
Detect if code, has usage of CommonJS syntax (`exports`, `module.exports`, `require` and `global` usage)
`isMixed` indicates if both are detected! This is a common case with legacy packages exporting semi-compatible ESM syntax meant to be used by bundlers.
```js
import { detectSyntax } from "mlly";
// { hasESM: true, hasCJS: true, isMixed: true }
detectSyntax('export default require("lodash")');
```
## CommonJS Context
### `createCommonJS`
This utility creates a compatible CommonJS context that is missing in ECMAScript modules.
Note: `require` and `require.resolve` implementation are lazy functions. [`createRequire`](https://nodejs.org/api/module.html#module_module_createrequire_filename) will be called on first usage.
## Import/Export Analyzes
Tools to quickly analyze ESM syntax and extract static `import`/`export`
Similar to [url.fileURLToPath](https://nodejs.org/api/url.html#url_url_fileurltopath_url) but also converts windows backslash `\` to unix slash `/` and handles if input is already a path.
```js
import { fileURLToPath } from "mlly";
// /foo/bar.js
console.log(fileURLToPath("file:///foo/bar.js"));
// C:/path
console.log(fileURLToPath("file:///C:/path/"));
```
### `normalizeid`
Ensures id has either of `node:`, `data:`, `http:`, `https:` or `file:` protocols.
```js
import { ensureProtocol } from "mlly";
// file:///foo/bar.js
console.log(normalizeid("/foo/bar.js"));
```
### `loadURL`
Read source contents of a URL. (currently only file protocol supported)