Skip to content

Commit be934a0

Browse files
committed
fix(DryMongoBinary): resolve modulesCache relative to config options package.json
this should help locally installed binaries within a workspace instead of the current run package.
1 parent 4f0d342 commit be934a0

File tree

4 files changed

+139
-1
lines changed

4 files changed

+139
-1
lines changed

docs/api/config-options.md

+20
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,26 @@ Directory Priority:
2222
3. `projectRoot/node_modules/.cache/mongodb-binaries` (node-modules cache)
2323
4. `./mongodb-binaries` (relative to `process.cwd()`)
2424

25+
:::note
26+
Resolving the `node_modules/.cache` can be rather inconsistent depending on what package manager is used and from where the script is started.
27+
28+
A way to force a more specific `node_modules/.cache` to be used (like a workspace's) is to set the package.json config for mongodb-memory-server (there needs to be at least one key, it does not matter if it is a actual config option or not), see [How to use them in the package.json](#how-to-use-them-in-the-packagejson).
29+
Example:
30+
31+
```json
32+
{
33+
"name": "workspace",
34+
// along with your other workspace keys
35+
"config": {
36+
"mongodbMemoryServer": {
37+
"_": 0
38+
}
39+
}
40+
}
41+
```
42+
43+
:::
44+
2545
Format:
2646

2747
- `/path/to/binary/` (POSIX)

packages/mongodb-memory-server-core/src/util/DryMongoBinary.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import debug from 'debug';
2-
import { DEFAULT_VERSION, envToBool, resolveConfig, ResolveConfigVariables } from './resolveConfig';
2+
import {
3+
DEFAULT_VERSION,
4+
envToBool,
5+
packageJsonPath,
6+
resolveConfig,
7+
ResolveConfigVariables,
8+
} from './resolveConfig';
39
import {
410
assertion,
511
checkBinaryPermissions,
@@ -308,6 +314,13 @@ export class DryMongoBinary {
308314
nodeModulesDLDir = path.resolve(nodeModulesDLDir, '..', '..');
309315
}
310316

317+
const configPackagePath = packageJsonPath();
318+
319+
// use the same "node_modules/.cache" as the package.json that was found for config options, if available
320+
if (configPackagePath && (await pathExists(path.resolve(configPackagePath, 'node_modules')))) {
321+
nodeModulesDLDir = configPackagePath;
322+
}
323+
311324
const tmpModulesCache = findCacheDir({
312325
name: 'mongodb-memory-server',
313326
cwd: nodeModulesDLDir,

packages/mongodb-memory-server-core/src/util/__tests__/dryBinary.test.ts

+97
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { DryMongoBinary } from '../DryMongoBinary';
33
import * as path from 'path';
44
import { constants, promises as fspromises } from 'fs';
55
import { DEFAULT_VERSION, envName, ResolveConfigVariables } from '../resolveConfig';
6+
import * as resConfig from '../resolveConfig';
67
import * as utils from '../utils';
78
import * as getOs from '../getos';
89
import { LinuxOS, OtherOS } from '../getos';
@@ -140,6 +141,102 @@ describe('DryBinary', () => {
140141
modulesCache: '', // because not being in an project
141142
} as binary.DryMongoBinaryPaths);
142143
});
144+
145+
it('should resolve modulesCache relative to the package json that has config options', async () => {
146+
const workspacePackagePath = path.resolve(tmpDir, 'package.json');
147+
const packagePackagePath = path.resolve(tmpDir, 'packages/testy/package.json');
148+
await utils.mkdir(path.dirname(packagePackagePath));
149+
150+
// create the shared workspace package.json
151+
await fspromises.writeFile(
152+
workspacePackagePath,
153+
JSON.stringify({
154+
name: 'testw',
155+
private: true,
156+
devDependencies: {
157+
'mongodb-memory-server': '0.0.0',
158+
},
159+
config: {
160+
mongodbMemoryServer: {
161+
test: 1,
162+
},
163+
},
164+
})
165+
);
166+
// emulate having resolved the package.json files and found the above file
167+
jest.spyOn(resConfig, 'packageJsonPath').mockReturnValue(path.dirname(workspacePackagePath));
168+
// emulate having run "npm i" / "yarn install"
169+
await utils.mkdir(path.resolve(path.dirname(workspacePackagePath), 'node_modules'));
170+
171+
// create the package's package.json
172+
await fspromises.writeFile(
173+
packagePackagePath,
174+
JSON.stringify({
175+
name: 'testp',
176+
// no custom configuration
177+
})
178+
);
179+
180+
process.chdir(path.dirname(packagePackagePath));
181+
182+
const returnValue = await binary.DryMongoBinary.generatePaths(opts);
183+
expect(returnValue).toStrictEqual({
184+
resolveConfig: '', // empty because not having an extra config value
185+
relative: path.resolve(path.dirname(packagePackagePath), 'mongodb-binaries', binaryName),
186+
homeCache: path.resolve(tmpDir, 'homedir/.cache/mongodb-binaries', binaryName),
187+
modulesCache: path.resolve(
188+
path.dirname(workspacePackagePath),
189+
'node_modules/.cache/mongodb-memory-server',
190+
binaryName
191+
),
192+
} as binary.DryMongoBinaryPaths);
193+
});
194+
195+
it('should resolve modulesCache relative to cwd if no package.json with config options are found', async () => {
196+
const workspacePackagePath = path.resolve(tmpDir, 'package.json');
197+
const packagePackagePath = path.resolve(tmpDir, 'packages/testy/package.json');
198+
await utils.mkdir(path.dirname(packagePackagePath));
199+
200+
// create the shared workspace package.json
201+
await fspromises.writeFile(
202+
workspacePackagePath,
203+
JSON.stringify({
204+
name: 'testw',
205+
private: true,
206+
devDependencies: {
207+
'mongodb-memory-server': '0.0.0',
208+
},
209+
// no custom configuration
210+
})
211+
);
212+
// emulate having resolved the package.json files and found the above file
213+
jest.spyOn(resConfig, 'packageJsonPath').mockReturnValue(undefined);
214+
// emulate having run "npm i" / "yarn install"
215+
await utils.mkdir(path.resolve(path.dirname(workspacePackagePath), 'node_modules'));
216+
217+
// create the package's package.json
218+
await fspromises.writeFile(
219+
packagePackagePath,
220+
JSON.stringify({
221+
name: 'testp',
222+
// no custom configuration
223+
})
224+
);
225+
226+
process.chdir(path.dirname(packagePackagePath));
227+
228+
const returnValue = await binary.DryMongoBinary.generatePaths(opts);
229+
expect(returnValue).toStrictEqual({
230+
resolveConfig: '', // empty because not having an extra config value
231+
relative: path.resolve(path.dirname(packagePackagePath), 'mongodb-binaries', binaryName),
232+
homeCache: path.resolve(tmpDir, 'homedir/.cache/mongodb-binaries', binaryName),
233+
modulesCache: path.resolve(
234+
path.dirname(packagePackagePath),
235+
'node_modules/.cache/mongodb-memory-server',
236+
binaryName
237+
),
238+
} as binary.DryMongoBinaryPaths);
239+
});
143240
});
144241

145242
describe('getBinaryName', () => {

packages/mongodb-memory-server-core/src/util/resolveConfig.ts

+8
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ export function resolveConfig(variableName: ResolveConfigVariables): string | un
143143
)?.toString();
144144
}
145145

146+
/**
147+
* Get the directory path of the `package.json` with config options, if available
148+
* @returns The directory of the `package.json`, otherwise `undefined`
149+
*/
150+
export function packageJsonPath(): string | undefined {
151+
return packagejson?.filePath;
152+
}
153+
146154
export default resolveConfig;
147155

148156
/**

0 commit comments

Comments
 (0)