From 206e496e54e3a39fc076da9a03ba7b3c81d5d827 Mon Sep 17 00:00:00 2001 From: Velten Heyn Date: Tue, 23 Dec 2025 16:55:18 +0100 Subject: [PATCH 1/2] Add support for ts --- index.js | 37 +++++++++++++++++++++++++++++++++---- test/api-mocker.spec.js | 13 +++++++++++++ test/mocks/users/4/GET.ts | 5 +++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 test/mocks/users/4/GET.ts diff --git a/index.js b/index.js index 57460bf..d11f7c1 100644 --- a/index.js +++ b/index.js @@ -13,7 +13,7 @@ function escapeRegExp(str) { } function isJsFile(str) { - return !!str.match(/\.c?js$/); + return !!str.match(/\.(?:c?js|ts)$/); } function defaultLogger(params) { @@ -107,6 +107,35 @@ function findMatchingPath(requestPath, requestMethodFiles) { return result; } +function normalizeMiddleware(mod) { + // 1. Already a function or array → OK + if (typeof mod === 'function' || Array.isArray(mod)) { + return mod; + } + + // 2. Babel / TS interop + if (mod && mod.__esModule && 'default' in mod) { + return mod.default; + } + + // 3. Native ESM via Symbol.toStringTag + if ( + mod && + typeof mod === 'object' && + mod[Symbol.toStringTag] === 'Module' && + 'default' in mod + ) { + return mod.default; + } + + // 4. Node ESM interop fallback (safe) + if (mod && typeof mod === 'object' && 'default' in mod) { + return mod.default; + } + + return mod; +} + /** * @param {string|object} urlRoot Base path for API url or full config object * @param {string|object} pathRoot Base path of API mock files. eg: ./mock/api or @@ -170,10 +199,10 @@ module.exports = function (urlRoot, pathRoot) { const returnForPath = function (filePath, requestParams) { if (isJsFile(filePath)) { logger({ - req, filePath, fileType: 'js', config + req, filePath, config }); delete require.cache[require.resolve(path.resolve(filePath))]; - let customMiddleware = require(path.resolve(filePath)); + let customMiddleware = normalizeMiddleware(require(path.resolve(filePath))); if (requestParams) { req.params = requestParams; } @@ -222,7 +251,7 @@ module.exports = function (urlRoot, pathRoot) { methodFileExtension = req.accepts(['json', 'xml']); } - const fileExtensions = [methodFileExtension, 'cjs', 'js']; + const fileExtensions = [methodFileExtension, 'ts', 'cjs', 'js']; const jsMockFiles = fileExtensions.map((ext) => `${req.method}.${ext}`); const wildcardJsMockFiles = fileExtensions.map((ext) => `ANY.${ext}`); const methodFiles = [...jsMockFiles, ...wildcardJsMockFiles]; diff --git a/test/api-mocker.spec.js b/test/api-mocker.spec.js index 0ad2bd4..13d5454 100644 --- a/test/api-mocker.spec.js +++ b/test/api-mocker.spec.js @@ -115,6 +115,19 @@ describe('cjs extensions for custom middlewares', () => { }); }); +describe('ts extensions for custom middlewares', () => { + it('responds by simple ts middleware', (done) => { + request(app) + + .get('/api/users/4') + .expect('Content-Type', /json/) + .expect(200) + .expect({ + result: 'ts works' + }, done); + }); +}); + describe('nextOnNotFound setting', () => { it('returns correct response when mock is exits', (done) => { request(app) diff --git a/test/mocks/users/4/GET.ts b/test/mocks/users/4/GET.ts new file mode 100644 index 0000000..1086ec7 --- /dev/null +++ b/test/mocks/users/4/GET.ts @@ -0,0 +1,5 @@ +export default function (req: any, res: any) { + res.json({ + result: 'cjs works' + }); +}; From 4450181e63cbac4fd6cbfcc6fe8b611ab51552f1 Mon Sep 17 00:00:00 2001 From: Velten Heyn Date: Tue, 23 Dec 2025 16:57:35 +0100 Subject: [PATCH 2/2] Correct typo --- test/mocks/users/4/GET.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/mocks/users/4/GET.ts b/test/mocks/users/4/GET.ts index 1086ec7..6b59f72 100644 --- a/test/mocks/users/4/GET.ts +++ b/test/mocks/users/4/GET.ts @@ -1,5 +1,5 @@ export default function (req: any, res: any) { res.json({ - result: 'cjs works' + result: 'ts works' }); };