awilix
awilix copied to clipboard
Rename `awilix.module.js` to `awilix.module.mjs` (better Vitest support)
According to Vitest, it seems like the current export of the ESM build is not quite correct.
When using Awilix with Vitest, I get informed of the following:
Module /Users/.../node_modules/awilix/lib/awilix.module.js:1 seems to be an ES Module but shipped in a CommonJS package. You might want to create an issue to the package "awilix" asking them to ship the file in .mjs extension or add "type": "module" in their package.json.
As a temporary workaround you can try to inline the package by updating your config:
// vitest.config.js
export default {
test: {
deps: {
inline: [
"awilix"
]
}
}
}
The proposed workaround works fine, but it would be nice if it wasn't needed.
I also tested native ESM loading in Node.js, which worked fine with the current setup. So I'm not sure if the package really is wrong or if it's a Vitest/Vite issue.
I'm happy to contribute a PR to make the adjustment if you like.
I have yet to actually use ESM myself so I don’t know much about it; would doing this be considered a breaking change?
I don't think so, unless somebody explicitly imported awilix/lib/awilix.module.js, in that case their code would be broken.
But I'm also not entirely sure.
I know some people use Awilix with Webpack, but if renaming that file won't break anything, then I have no problem doing this.
I'll send a PR and test it with Webpack beforehand. Will just take a few days before I get to it. 🙂
To consume a package as an ES module, the package.json needs to be either have "type": "module"or a .mjs extension so I think that's the key issue here.
Not sure if it's related but whenever I try to add awilix to deps.inline, I get the following error:
Error: Cannot find module './errors'
Require stack:
- /Users/jclaessens/proj/packages/api-next/awilix
at Module._resolveFilename (node:internal/modules/cjs/loader:985:15)
at Module._load (node:internal/modules/cjs/loader:833:27)
at Module.require (node:internal/modules/cjs/loader:1051:19)
at require (node:internal/modules/cjs/helpers:103:18)
at awilix:13:14
at ViteNodeRunner.directRequest (file:///Users/jclaessens/proj/node_modules/.pnpm/[email protected]/node_modules/vitest/dist/chunk-vite-node-client.4dd32c96.js:250:11)
at async ViteNodeRunner.cachedRequest (file:///Users/jclaessens/proj/node_modules/.pnpm/[email protected]/node_modules/vitest/dist/chunk-vite-node-client.4dd32c96.js:127:12)
at async request (file:///Users/jclaessens/proj/node_modules/.pnpm/[email protected]/node_modules/vitest/dist/chunk-vite-node-client.4dd32c96.js:150:16)
at async /Users/jclaessens/proj/packages/api-next/src/diContainer.ts:3:31
at async ViteNodeRunner.directRequest (file:///Users/jclaessens/proj/node_modules/.pnpm/[email protected]/node_modules/vitest/dist/chunk-vite-node-client.4dd32c96.js:250:5) {
code: 'MODULE_NOT_FOUND',
requireStack: [ '/Users/jclaessens/proj/packages/api-next/awilix' ]
}
If I don't add awilix to deps.inline, I get the following error for every .ts file I try to load when initializing the DI container.
TypeError: Unknown file extension ".ts" for /Users/jclaessens/proj/packages/api-next/src/modules/equipment/equipment.service.ts
ELIFECYCLE Test failed. See above for more details.
I load my modules like this:
import { diContainer } from '@fastify/awilix';
import { InjectionMode, Lifetime, asClass, asValue } from 'awilix';
import { getManagementClient } from './modules/auth0/managementClient';
import { prisma } from './db';
export async function registerDiContainer() {
const container = await diContainer
.loadModules(
[
['src/modules/**/*.service.ts', { register: asClass }],
['src/modules/**/*.repository.ts', { register: asClass }],
],
{
formatName: 'camelCase',
resolverOptions: {
lifetime: Lifetime.SCOPED,
injectionMode: InjectionMode.PROXY,
},
esModules: true,
},
);
return container.register({
auth0ManagementClient: asValue(getManagementClient()),
prisma: asValue(prisma),
});
}
tsconfig:
{
"extends": "fastify-tsconfig",
"compilerOptions": {
"esModuleInterop": true,
"lib": ["ESNext"],
"outDir": "build",
"paths": {
"@/*": ["./src/*"],
"~/*": ["./*"]
},
"strict": true,
"target": "ESNext"
}
}
All of this is only happening with vitest. No issues when building (esbuild) or running in dev mode (tsx).
I'm also using @fastify/awilix. Any idea?
My issue is solved by not using loadModules but by just importing all services and use register instead like so:
import { diContainer } from '@fastify/awilix';
import { Lifetime, asClass, asValue } from 'awilix';
import managementClient from './modules/auth0/managementClient';
import { prisma } from './db';
import Auth0Service from './modules/auth0/auth0.service';
import OrganisationService from './modules/organisation/organisation.service';
import OrganisationRepository from './modules/organisation/organisation.repository';
import EquipmentRepository from './modules/equipment/equipment.repository';
import EquipmentService from './modules/equipment/equipment.service';
export function registerDiContainer() {
return diContainer.register({
auth0ManagementClient: asValue(managementClient),
prisma: asValue(prisma),
auth0Service: asClass(Auth0Service, { lifetime: Lifetime.SINGLETON }),
organisationRepository: asClass(OrganisationRepository, { lifetime: Lifetime.SCOPED }),
organisationService: asClass(OrganisationService, { lifetime: Lifetime.SCOPED }),
equipmentRepository: asClass(EquipmentRepository, { lifetime: Lifetime.SCOPED }),
equipmentService: asClass(EquipmentService, { lifetime: Lifetime.SCOPED }),
});
}
Is there some way to not have to import any service individually?
So it appears not to be related to the original issue at all, I'm sorry for that 😅
I just released Awilix v8 which renames awilix.module.js to awilix.module.mjs.
@jclaessens97 your issue seems to be due to trying to load .ts files in tests and your runner isn't configured to transpile them.