{"id":26255352,"url":"https://github.com/nyxblabs/esmnxuts","last_synced_at":"2026-04-13T12:32:31.902Z","repository":{"id":163914046,"uuid":"639356495","full_name":"nyxblabs/esmnxuts","owner":"nyxblabs","description":"🛠️ Missing ESM utils for Node.js! Fill the gap with ease.","archived":false,"fork":false,"pushed_at":"2023-05-11T11:02:31.000Z","size":86,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-30T21:02:53.106Z","etag":null,"topics":["ease","esm","gap","nodejs","utils"],"latest_commit_sha":null,"homepage":"https://nyxb.xyz","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nyxblabs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["nyxb"]}},"created_at":"2023-05-11T09:56:46.000Z","updated_at":"2023-05-11T12:09:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"bd910677-5a89-4ff5-962e-aa0d1b824318","html_url":"https://github.com/nyxblabs/esmnxuts","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/nyxblabs/esmnxuts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nyxblabs%2Fesmnxuts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nyxblabs%2Fesmnxuts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nyxblabs%2Fesmnxuts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nyxblabs%2Fesmnxuts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nyxblabs","download_url":"https://codeload.github.com/nyxblabs/esmnxuts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nyxblabs%2Fesmnxuts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31753187,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T09:16:15.125Z","status":"ssl_error","status_checked_at":"2026-04-13T09:16:05.023Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ease","esm","gap","nodejs","utils"],"created_at":"2025-03-13T19:18:21.315Z","updated_at":"2026-04-13T12:32:31.893Z","avatar_url":"https://github.com/nyxblabs.png","language":"TypeScript","funding_links":["https://github.com/sponsors/nyxb"],"categories":[],"sub_categories":[],"readme":"[![cover][cover-src]][cover-href]\n[![npm version][npm-version-src]][npm-version-href]\n[![npm downloads][npm-downloads-src]][npm-downloads-href]\n[![JSDocs][jsdocs-src]][jsdocs-href]\n[![License][license-src]][license-href]\n\n\u003e Missing [ECMAScript module](https://nodejs.org/api/esm.html) utils for Node.js\n\u003e\n\u003e 📈 As the Node.js ecosystem continues to embrace ESM modules, many essential features are still in development, experimental, or not yet available. 💡 This package aims to address these gaps and provide the necessary support for ESM modules. 🔌 Enhance your Node.js development experience with features that are required for optimal ESM support. 🚀 Stay ahead of the curve with this package.\n\n## Usage\n\nInstall:\n\n```sh\n# nyxi\nnyxi esmnxuts\n\n#pnpm\npnpm add esmnxuts\n\n# using npm\nnpm install esmnxuts\n\n# using yarn\nyarn add esmnxuts\n```\n\n**Note:** Node.js 14+ is recommended.\n\nImport utils:\n\n```ts\n// ESM\nimport {} from \"esmnxuts\";\n\n// CommonJS\nconst {} = require(\"esmnxuts\");\n```\n\n## Resolving ESM modules\n\nSeveral utilities to make ESM resolution easier:\n\n- Respecting [ECMAScript Resolver algorithm](https://nodejs.org/dist/latest-v14.x/docs/api/esm.html#esm_resolver_algorithm)\n- Exposed from Node.js implementation\n- Windows paths normalized\n- Supporting custom `extensions` and `/index` resolution\n- Supporting custom `conditions`\n- Support resolving from multiple paths or urls\n\n### `resolve`\n\nResolve a module by respecting [ECMAScript Resolver algorithm](https://nodejs.org/dist/latest-v14.x/docs/api/esm.html#esm_resolver_algorithm)\n(using [wooorm/import-meta-resolve](https://github.com/wooorm/import-meta-resolve)).\n\nAdditionally supports resolving without extension and `/index` similar to CommonJS.\n\n```js\nimport { resolve } from \"esmnxuts\";\n\n// file:///home/user/project/module.mjs\nconsole.log(await resolve(\"./module.mjs\", { url: import.meta.url }));\n```\n\n**Resolve options:**\n\n- `url`: URL or string to resolve from (default is `pwd()`)\n- `conditions`: Array of conditions used for resolution algorithm (default is `['node', 'import']`)\n- `extensions`: Array of additional extensions to check if import failed (default is `['.mjs', '.cjs', '.js', '.json']`)\n\n### `resolvePath`\n\nSimilar to `resolve` but returns a path instead of URL using `fileURLToPath`.\n\n```ts\nimport { resolvePath } from \"esmnxuts\";\n\n// /home/user/project/module.mjs\nconsole.log(await resolvePath(\"./module.mjs\", { url: import.meta.url }));\n```\n\n### `createResolve`\n\nCreate a `resolve` function with defaults.\n\n```ts\nimport { createResolve } from \"esmnxuts\";\n\nconst _resolve = createResolve({ url: import.meta.url });\n\n// file:///home/user/project/module.mjs\nconsole.log(await _resolve(\"./module.mjs\"));\n```\n\n**Example:** Ponyfill [import.meta.resolve](https://nodejs.org/api/esm.html#esm_import_meta_resolve_specifier_parent):\n\n```ts\nimport { createResolve } from \"esmnxuts\";\n\nimport.meta.resolve = createResolve({ url: import.meta.url });\n```\n\n### `resolveImports`\n\nResolve all static and dynamic imports with relative paths to full resolved path.\n\n```ts\nimport { resolveImports } from \"esmnxuts\";\n\n// import foo from 'file:///home/user/project/bar.mjs'\nconsole.log(\n  await resolveImports(`import foo from './bar.mjs'`, { url: import.meta.url })\n);\n```\n\n## Syntax Analyzes\n\n### `isValidNodeImport`\n\nUsing 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!\n\nWhen result is `false`, we usually need a to create a CommonJS require context or add specific rules to the bundler to transform dependency.\n\n```ts\nimport { isValidNodeImport } from \"esmnxuts\";\n\n// If returns true, we are safe to use `import('some-lib')`\nawait isValidNodeImport(\"some-lib\", {});\n```\n\n**Algorithm:**\n\n- Check import protocol - If is `data:` return `true` (✅ valid) - If is not `node:`, `file:` or `data:`, return `false` (\n  ❌ invalid)\n- Resolve full path of import using Node.js [Resolution algorithm](https://nodejs.org/api/esm.html#resolution-algorithm)\n- Check full path extension\n  - If is `.mjs`, `.cjs`, `.node` or `.wasm`, return `true` (✅ valid)\n  - If is not `.js`, return `false` (❌ invalid)\n  - If is matching known mixed syntax (`.esm.js`, `.es.js`, etc) return `false` (\n    ❌ invalid)\n- Read closest `package.json` file to resolve path\n- If `type: 'module'` field is set, return `true` (✅ valid)\n- Read source code of resolved path\n- Try to detect CommonJS syntax usage\n  - If yes, return `true` (✅ valid)\n- Try to detect ESM syntax usage\n  - if yes, return `false` (\n    ❌ invalid)\n\n**Notes:**\n\n- There might be still edge cases algorithm cannot cover. It is designed with best-efforts.\n- This method also allows using dynamic import of CommonJS libraries considering\n  Node.js has [Interoperability with CommonJS](https://nodejs.org/api/esm.html#interoperability-with-commonjs).\n\n### `hasESMSyntax`\n\nDetect if code, has usage of ESM syntax (Static `import`, ESM `export` and `import.meta` usage)\n\n```ts\nimport { hasESMSyntax } from \"esmnxuts\";\n\nhasESMSyntax(\"export default foo = 123\"); // true\n```\n\n### `hasCJSSyntax`\n\nDetect if code, has usage of CommonJS syntax (`exports`, `module.exports`, `require` and `global` usage)\n\n```ts\nimport { hasCJSSyntax } from \"esmnxuts\";\n\nhasCJSSyntax(\"export default foo = 123\"); // false\n```\n\n### `detectSyntax`\n\nTests code against both CJS and ESM.\n\n`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.\n\n```ts\nimport { detectSyntax } from \"esmnxuts\";\n\n// { hasESM: true, hasCJS: true, isMixed: true }\ndetectSyntax('export default require(\"lodash\")');\n```\n\n## CommonJS Context\n\n### `createCommonJS`\n\nThis utility creates a compatible CommonJS context that is missing in ECMAScript modules.\n\n```ts\nimport { createCommonJS } from \"esmnxuts\";\n\nconst { __dirname, __filename, require } = createCommonJS(import.meta.url);\n```\n\nNote: `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.\n\n## Import/Export Analyzes\n\nTools to quickly analyze ESM syntax and extract static `import`/`export`\n\n- Super fast Regex based implementation\n- Handle most edge cases\n- Find all static ESM imports\n- Find all dynamic ESM imports\n- Parse static import statement\n- Find all named, declared and default exports\n\n### `findStaticImports`\n\nFind all static ESM imports.\n\nExample:\n\n```ts\nimport { findStaticImports } from \"esmnxuts\";\n\nconsole.log(\n  findStaticImports(`\n// Empty line\nimport foo, { bar /* foo */ } from 'baz'\n`)\n);\n```\n\nOutputs:\n\n```ts\n[\n  {\n    type: \"static\",\n    imports: \"foo, { bar /* foo */ } \",\n    specifier: \"baz\",\n    code: \"import foo, { bar /* foo */ } from 'baz'\",\n    start: 15,\n    end: 55,\n  },\n];\n```\n\n### `parseStaticImport`\n\nParse a dynamic ESM import statement previously matched by `findStaticImports`.\n\nExample:\n\n```ts\nimport { findStaticImports, parseStaticImport } from \"esmnxuts\";\n\nconst [match0] = findStaticImports(`import baz, { x, y as z } from 'baz'`);\nconsole.log(parseStaticImport(match0));\n```\n\nOutputs:\n\n```ts\n{\n  type: 'static',\n  imports: 'baz, { x, y as z } ',\n  specifier: 'baz',\n  code: \"import baz, { x, y as z } from 'baz'\",\n  start: 0,\n  end: 36,\n  defaultImport: 'baz',\n  namespacedImport: undefined,\n  namedImports: { x: 'x', y: 'z' }\n}\n```\n\n### `findDynamicImports`\n\nFind all dynamic ESM imports.\n\nExample:\n\n```ts\nimport { findDynamicImports } from \"esmnxuts\";\n\nconsole.log(\n  findDynamicImports(`\nconst foo = await import('bar')\n`)\n);\n```\n\n### `findExports`\n\n```ts\nimport { findExports } from \"esmnxuts\";\n\nconsole.log(\n  findExports(`\nexport const foo = 'bar'\nexport { bar, baz }\nexport default something\n`)\n);\n```\n\nOutputs:\n\n```ts\n[\n  {\n    type: \"declaration\",\n    declaration: \"const\",\n    name: \"foo\",\n    code: \"export const foo\",\n    start: 1,\n    end: 17,\n  },\n  {\n    type: \"named\",\n    exports: \" bar, baz \",\n    code: \"export { bar, baz }\",\n    start: 26,\n    end: 45,\n    names: [\"bar\", \"baz\"],\n  },\n  { type: \"default\", code: \"export default \", start: 46, end: 61 },\n];\n```\n\n### `findExportNames`\n\nSame as `findExports` but returns array of export names.\n\n```ts\nimport { findExportNames } from \"esmnxuts\";\n\n// [ \"foo\", \"bar\", \"baz\", \"default\" ]\nconsole.log(\n  findExportNames(`\nexport const foo = 'bar'\nexport { bar, baz }\nexport default something\n`)\n);\n```\n\n## `resolveModuleExportNames`\n\nResolves module and reads its contents to extract possible export names using static analyzes.\n\n```ts\nimport { resolveModuleExportNames } from \"esmnxuts\";\n\n// [\"basename\", \"dirname\", ... ]\nconsole.log(await resolveModuleExportNames(\"nyxpath\"));\n```\n\n## Evaluating Modules\n\nSet of utilities to evaluate ESM modules using `data:` imports\n\n- Automatic import rewrite to resolved path using static analyzes\n- Allow bypass ESM Cache\n- Stack-trace support\n- `.json` loader\n\n### `evalModule`\n\nTransform and evaluates module code using dynamic imports.\n\n```ts\nimport { evalModule } from \"esmnxuts\";\n\nawait evalModule(`console.log(\"Hello World!\")`);\n\nawait evalModule(\n  `\n  import { reverse } from './utils.mjs'\n  console.log(reverse('!emosewa si sj'))\n`,\n  { url: import.meta.url }\n);\n```\n\n**Options:**\n\n- all `resolve` options\n- `url`: File URL\n\n### `loadModule`\n\nDynamically loads a module by evaluating source code.\n\n```ts\nimport { loadModule } from \"esmnxuts\";\n\nawait loadModule(\"./hello.mjs\", { url: import.meta.url });\n```\n\nOptions are same as `evalModule`.\n\n### `transformModule`\n\n- Resolves all relative imports will be resolved\n- All usages of `import.meta.url` will be replaced with `url` or `from` option\n\n```ts\nimport { transformModule } from \"esmnxuts\";\nconsole.log(transformModule(`console.log(import.meta.url)`), {\n  url: \"test.mjs\",\n});\n```\n\nOptions are same as `evalModule`.\n\n## Other Utils\n\n### `fileURLToPath`\n\nSimilar 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.\n\n```ts\nimport { fileURLToPath } from \"esmnxuts\";\n\n// /foo/bar.js\nconsole.log(fileURLToPath(\"file:///foo/bar.js\"));\n\n// C:/path\nconsole.log(fileURLToPath(\"file:///C:/path/\"));\n```\n\n### `normalizeid`\n\nEnsures id has either of `node:`, `data:`, `http:`, `https:` or `file:` protocols.\n\n```ts\nimport { ensureProtocol } from \"esmnxuts\";\n\n// file:///foo/bar.js\nconsole.log(normalizeid(\"/foo/bar.js\"));\n```\n\n### `loadURL`\n\nRead source contents of a URL. (currently only file protocol supported)\n\n```ts\nimport { resolve, loadURL } from \"esmnxuts\";\n\nconst url = await resolve(\"./index.mjs\", { url: import.meta.url });\nconsole.log(await loadURL(url));\n```\n\n### `toDataURL`\n\nConvert code to [`data:`](https://nodejs.org/api/esm.html#esm_data_imports) URL using base64 encoding.\n\n```ts\nimport { toDataURL } from \"esmnxuts\";\n\nconsole.log(\n  toDataURL(`\n  // This is an example\n  console.log('Hello world')\n`)\n);\n```\n\n### `interopDefault`\n\nReturn the default export of a module at the top-level, alongside any other named exports.\n\n```ts\n// Assuming the shape { default: { foo: 'bar' }, baz: 'qux' }\nimport myModule from \"my-module\";\n\n// Returns { foo: 'bar', baz: 'qux' }\nconsole.log(interopDefault(myModule));\n```\n\n### `sanitizeURIComponent`\n\nReplace reserved characters from a segment of URI to make it compatible with [rfc2396](https://datatracker.ietf.org/doc/html/rfc2396).\n\n```ts\nimport { sanitizeURIComponent } from \"esmnxuts\";\n\n// foo_bar\nconsole.log(sanitizeURIComponent(`foo:bar`));\n```\n\n### `sanitizeFilePath`\n\nSanitize each path of a file name or path with `sanitizeURIComponent` for URI compatibility.\n\n```ts\nimport { sanitizeFilePath } from \"esmnxuts\";\n\n// C:/te_st/_...slug_.jsx'\nconsole.log(sanitizeFilePath(\"C:\\\\te#st\\\\[...slug].jsx\"));\n```\n\n## License\n\n[MIT](./LICENSE) - Made with 💞\n\n\u003c!-- Badges --\u003e\n\n[npm-version-src]: https://img.shields.io/npm/v/esmnxuts?style=flat\u0026colorA=18181B\u0026colorB=14F195\n[npm-version-href]: https://npmjs.com/package/esmnxuts\n[npm-downloads-src]: https://img.shields.io/npm/dm/esmnxuts?style=flat\u0026colorA=18181B\u0026colorB=14F195\n[npm-downloads-href]: https://npmjs.com/package/esmnxuts\n[license-src]: https://img.shields.io/github/license/nyxblabs/CodeBoost.svg?style=flat\u0026colorA=18181B\u0026colorB=14F195\n[license-href]: https://github.com/nyxblabs/CodeBoost/blob/main/LICENSE\n[jsdocs-src]: https://img.shields.io/badge/jsDocs.io-reference-18181B?style=flat\u0026colorA=18181B\u0026colorB=14F195\n[jsdocs-href]: https://www.jsdocs.io/package/esmnxuts\n\n\u003c!-- Covers --\u003e\n[cover-src]: https://raw.githubusercontent.com/nyxblabs/utilities/main/.github/assets/cover-github-esmnxuts.png\n[cover-href]: https://💻nyxb.ws\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnyxblabs%2Fesmnxuts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnyxblabs%2Fesmnxuts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnyxblabs%2Fesmnxuts/lists"}