Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
}

function isJsFile(str) {
return !!str.match(/\.c?js$/);
return !!str.match(/\.(?:c?js|ts)$/);
}

function defaultLogger(params) {
console.log(

Check warning on line 20 in index.js

View workflow job for this annotation

GitHub Actions / release

Unexpected console statement
`${chalk.bgYellow.black('api-mocker')} ${
chalk.green(params.req.method.toUpperCase())} ${
chalk.blue(params.req.originalUrl)} => ${
Expand Down Expand Up @@ -107,6 +107,35 @@
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) {

Check failure on line 117 in index.js

View workflow job for this annotation

GitHub Actions / release

Unexpected dangling '_' in '__esModule'
return mod.default;
}

// 3. Native ESM via Symbol.toStringTag
if (
mod &&

Check failure on line 123 in index.js

View workflow job for this annotation

GitHub Actions / release

'&&' should be placed at the beginning of the line
typeof mod === 'object' &&

Check failure on line 124 in index.js

View workflow job for this annotation

GitHub Actions / release

'&&' should be placed at the beginning of the line
mod[Symbol.toStringTag] === 'Module' &&

Check failure on line 125 in index.js

View workflow job for this annotation

GitHub Actions / release

'&&' should be placed at the beginning of the line
'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
Expand Down Expand Up @@ -170,10 +199,10 @@
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;
}
Expand Down Expand Up @@ -222,7 +251,7 @@
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];
Expand Down
13 changes: 13 additions & 0 deletions test/api-mocker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions test/mocks/users/4/GET.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default function (req: any, res: any) {
res.json({
result: 'ts works'
});
};
Loading