From 223164983d1b3338dcca8b67dc3b54f1e6995151 Mon Sep 17 00:00:00 2001 From: Sam Evans Date: Thu, 16 Apr 2026 15:02:02 -0600 Subject: [PATCH] fix(esm): emit Node-resolvable ESM by switching to nodenext Compiled output under `lib/` previously contained extensionless relative imports (e.g. `import { Client } from './client'`), because tsconfig used `moduleResolution: bundler`. Pure-Node ESM consumers hit `ERR_MODULE_NOT_FOUND` since Node's ESM resolver requires explicit file extensions; only bundler-based consumers worked. - Switch tsconfig `module` and `moduleResolution` to `nodenext`. - Add explicit `.js` extensions to every relative import/export under src/. - Add `with { type: 'json' }` to the package.json import in http.ts (now required by nodenext; supported in Node 18.20+, 20.10+, 22+). - Switch eventemitter3 to a named import in client.ts; nodenext's stricter ESM resolution otherwise treats the .mjs default as a namespace (TS2507). Repro before fix: `node --input-type=module -e "import * as soap from './lib/soap.js'"` failed. After fix it loads cleanly, as do all subpath exports declared in package.json. --- src/client.ts | 12 ++++++------ src/http.ts | 6 +++--- src/security/BasicAuthSecurity.ts | 4 ++-- src/security/BearerSecurity.ts | 2 +- src/security/WSSecurity.ts | 4 ++-- src/security/index.ts | 6 +++--- src/soap.ts | 22 +++++++++++----------- src/types.ts | 4 ++-- src/utils.ts | 4 ++-- src/wsdl/elements.ts | 4 ++-- src/wsdl/index.ts | 10 +++++----- tsconfig.json | 4 ++-- 12 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/client.ts b/src/client.ts index ed9d3be..77339c4 100644 --- a/src/client.ts +++ b/src/client.ts @@ -4,13 +4,13 @@ */ import debugBuilder from 'debug'; -import EventEmitter from 'eventemitter3'; +import { EventEmitter } from 'eventemitter3'; import * as _ from 'lodash'; -import { HttpClient } from './http'; -import { IHeaders, IHttpClient, IMTOMAttachments, IOptions, ISecurity, SoapMethod, SoapMethodAsync } from './types'; -import { assert, findPrefix } from './utils'; -import { WSDL } from './wsdl'; -import { IPort, OperationElement, ServiceElement } from './wsdl/elements'; +import { HttpClient } from './http.js'; +import { IHeaders, IHttpClient, IMTOMAttachments, IOptions, ISecurity, SoapMethod, SoapMethodAsync } from './types.js'; +import { assert, findPrefix } from './utils.js'; +import { WSDL } from './wsdl/index.js'; +import { IPort, OperationElement, ServiceElement } from './wsdl/elements.js'; /** * Read a ReadableStream to string diff --git a/src/http.ts b/src/http.ts index 7335801..1184046 100644 --- a/src/http.ts +++ b/src/http.ts @@ -5,13 +5,13 @@ import debugBuilder from 'debug'; import MIMEType from 'whatwg-mimetype'; -import { IExOptions, IHeaders, IHttpClient, IOptions } from './types'; -import { parseMTOMResp } from './utils'; +import { IExOptions, IHeaders, IHttpClient, IOptions } from './types.js'; +import { parseMTOMResp } from './utils.js'; const debug = debugBuilder('fetch-soap'); // Use default import for bundler compatibility (named imports from JSON don't work in webpack/Next.js) -import pkg from '../package.json'; +import pkg from '../package.json' with { type: 'json' }; const version = pkg.version; const textEncoder = new TextEncoder(); diff --git a/src/security/BasicAuthSecurity.ts b/src/security/BasicAuthSecurity.ts index 50d61a2..ce7eae0 100644 --- a/src/security/BasicAuthSecurity.ts +++ b/src/security/BasicAuthSecurity.ts @@ -1,6 +1,6 @@ import * as _ from 'lodash'; -import { IHeaders, ISecurity } from '../types'; -import { stringToBase64 } from '../utils'; +import { IHeaders, ISecurity } from '../types.js'; +import { stringToBase64 } from '../utils.js'; export class BasicAuthSecurity implements ISecurity { private _username: string; diff --git a/src/security/BearerSecurity.ts b/src/security/BearerSecurity.ts index 8a12dde..e6ec0ef 100644 --- a/src/security/BearerSecurity.ts +++ b/src/security/BearerSecurity.ts @@ -1,5 +1,5 @@ import * as _ from 'lodash'; -import { IHeaders, ISecurity } from '../types'; +import { IHeaders, ISecurity } from '../types.js'; export class BearerSecurity implements ISecurity { private defaults; diff --git a/src/security/WSSecurity.ts b/src/security/WSSecurity.ts index b10ac16..15d9665 100644 --- a/src/security/WSSecurity.ts +++ b/src/security/WSSecurity.ts @@ -1,5 +1,5 @@ -import { ISecurity } from '../types'; -import { generateNonce, passwordDigest, xmlEscape } from '../utils'; +import { ISecurity } from '../types.js'; +import { generateNonce, passwordDigest, xmlEscape } from '../utils.js'; const validPasswordTypes = ['PasswordDigest', 'PasswordText']; diff --git a/src/security/index.ts b/src/security/index.ts index 1d6287e..744edc7 100644 --- a/src/security/index.ts +++ b/src/security/index.ts @@ -1,3 +1,3 @@ -export * from './BasicAuthSecurity'; -export * from './BearerSecurity'; -export * from './WSSecurity'; +export * from './BasicAuthSecurity.js'; +export * from './BearerSecurity.js'; +export * from './WSSecurity.js'; diff --git a/src/soap.ts b/src/soap.ts index 519c16c..78d0946 100644 --- a/src/soap.ts +++ b/src/soap.ts @@ -3,19 +3,19 @@ * MIT Licensed */ -import { Client } from './client'; -import * as _security from './security'; -import { IOptions, IWSDLCache } from './types'; -import { wsdlCacheSingleton } from './utils'; -import { open_wsdl, WSDL } from './wsdl'; +import { Client } from './client.js'; +import * as _security from './security/index.js'; +import { IOptions, IWSDLCache } from './types.js'; +import { wsdlCacheSingleton } from './utils.js'; +import { open_wsdl, WSDL } from './wsdl/index.js'; export const security = _security; -export { Client } from './client'; -export { HttpClient } from './http'; -export { BasicAuthSecurity, BearerSecurity, WSSecurity } from './security'; -export { passwordDigest } from './utils'; -export * from './types'; -export { WSDL } from './wsdl'; +export { Client } from './client.js'; +export { HttpClient } from './http.js'; +export { BasicAuthSecurity, BearerSecurity, WSSecurity } from './security/index.js'; +export { passwordDigest } from './utils.js'; +export * from './types.js'; +export { WSDL } from './wsdl/index.js'; type WSDLCallback = (error: any, result?: WSDL) => any; diff --git a/src/types.ts b/src/types.ts index b96744d..b9ca7c7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,5 @@ -import { WSDL } from './wsdl'; -import type { IHttpResponse } from './http'; +import { WSDL } from './wsdl/index.js'; +import type { IHttpResponse } from './http.js'; export interface IHeaders { [k: string]: any; diff --git a/src/utils.ts b/src/utils.ts index 51cc080..ba917f8 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,5 +1,5 @@ -import { IMTOMAttachments, IWSDLCache } from './types'; -import { WSDL } from './wsdl'; +import { IMTOMAttachments, IWSDLCache } from './types.js'; +import { WSDL } from './wsdl/index.js'; /** * Simple assertion function (replaces Node.js assert module) diff --git a/src/wsdl/elements.ts b/src/wsdl/elements.ts index 06f3d23..9456415 100644 --- a/src/wsdl/elements.ts +++ b/src/wsdl/elements.ts @@ -1,7 +1,7 @@ import debugBuilder from 'debug'; import * as _ from 'lodash'; -import { IWsdlBaseOptions } from '../types'; -import { assert, splitQName, TNS_PREFIX } from '../utils'; +import { IWsdlBaseOptions } from '../types.js'; +import { assert, splitQName, TNS_PREFIX } from '../utils.js'; const debug = debugBuilder('fetch-soap'); diff --git a/src/wsdl/index.ts b/src/wsdl/index.ts index de8095c..cc5aff5 100644 --- a/src/wsdl/index.ts +++ b/src/wsdl/index.ts @@ -9,11 +9,11 @@ import debugBuilder from 'debug'; import * as _ from 'lodash'; import * as sax from 'sax'; import stripBom from 'strip-bom'; -import { HttpClient } from '../http'; -import { NamespaceContext } from '../nscontext'; -import { IOptions } from '../types'; -import { assert, findPrefix, splitQName, TNS_PREFIX, xmlEscape } from '../utils'; -import * as elements from './elements'; +import { HttpClient } from '../http.js'; +import { NamespaceContext } from '../nscontext.js'; +import { IOptions } from '../types.js'; +import { assert, findPrefix, splitQName, TNS_PREFIX, xmlEscape } from '../utils.js'; +import * as elements from './elements.js'; const debug = debugBuilder('fetch-soap'); diff --git a/tsconfig.json b/tsconfig.json index 0932ebc..2974be4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,8 +2,8 @@ "compileOnSave": true, "compilerOptions": { "target": "ES2020", - "module": "ESNext", - "moduleResolution": "bundler", + "module": "nodenext", + "moduleResolution": "nodenext", "lib": ["ES2020", "DOM"], "outDir": "lib", "rootDir": "src",