diff --git a/docs/api/config-options.md b/docs/api/config-options.md index 8d6f5487f..c85e1c3e5 100644 --- a/docs/api/config-options.md +++ b/docs/api/config-options.md @@ -22,6 +22,26 @@ Directory Priority: 3. `projectRoot/node_modules/.cache/mongodb-binaries` (node-modules cache) 4. `./mongodb-binaries` (relative to `process.cwd()`) +:::note +Resolving the `node_modules/.cache` can be rather inconsistent depending on what package manager is used and from where the script is started. + +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). +Example: + +```json +{ + "name": "workspace", + // along with your other workspace keys + "config": { + "mongodbMemoryServer": { + "_": 0 + } + } +} +``` + +::: + Format: - `/path/to/binary/` (POSIX) diff --git a/packages/mongodb-memory-server-core/src/util/DryMongoBinary.ts b/packages/mongodb-memory-server-core/src/util/DryMongoBinary.ts index ba1bc2e2c..52db1fcf3 100644 --- a/packages/mongodb-memory-server-core/src/util/DryMongoBinary.ts +++ b/packages/mongodb-memory-server-core/src/util/DryMongoBinary.ts @@ -1,5 +1,11 @@ import debug from 'debug'; -import { DEFAULT_VERSION, envToBool, resolveConfig, ResolveConfigVariables } from './resolveConfig'; +import { + DEFAULT_VERSION, + envToBool, + packageJsonPath, + resolveConfig, + ResolveConfigVariables, +} from './resolveConfig'; import { assertion, checkBinaryPermissions, @@ -308,6 +314,13 @@ export class DryMongoBinary { nodeModulesDLDir = path.resolve(nodeModulesDLDir, '..', '..'); } + const configPackagePath = packageJsonPath(); + + // use the same "node_modules/.cache" as the package.json that was found for config options, if available + if (configPackagePath && (await pathExists(path.resolve(configPackagePath, 'node_modules')))) { + nodeModulesDLDir = configPackagePath; + } + const tmpModulesCache = findCacheDir({ name: 'mongodb-memory-server', cwd: nodeModulesDLDir, diff --git a/packages/mongodb-memory-server-core/src/util/__tests__/dryBinary.test.ts b/packages/mongodb-memory-server-core/src/util/__tests__/dryBinary.test.ts index c3af0239f..67ba58323 100644 --- a/packages/mongodb-memory-server-core/src/util/__tests__/dryBinary.test.ts +++ b/packages/mongodb-memory-server-core/src/util/__tests__/dryBinary.test.ts @@ -3,6 +3,7 @@ import { DryMongoBinary } from '../DryMongoBinary'; import * as path from 'path'; import { constants, promises as fspromises } from 'fs'; import { DEFAULT_VERSION, envName, ResolveConfigVariables } from '../resolveConfig'; +import * as resConfig from '../resolveConfig'; import * as utils from '../utils'; import * as getOs from '../getos'; import { LinuxOS, OtherOS } from '../getos'; @@ -140,6 +141,102 @@ describe('DryBinary', () => { modulesCache: '', // because not being in an project } as binary.DryMongoBinaryPaths); }); + + it('should resolve modulesCache relative to the package json that has config options', async () => { + const workspacePackagePath = path.resolve(tmpDir, 'package.json'); + const packagePackagePath = path.resolve(tmpDir, 'packages/testy/package.json'); + await utils.mkdir(path.dirname(packagePackagePath)); + + // create the shared workspace package.json + await fspromises.writeFile( + workspacePackagePath, + JSON.stringify({ + name: 'testw', + private: true, + devDependencies: { + 'mongodb-memory-server': '0.0.0', + }, + config: { + mongodbMemoryServer: { + test: 1, + }, + }, + }) + ); + // emulate having resolved the package.json files and found the above file + jest.spyOn(resConfig, 'packageJsonPath').mockReturnValue(path.dirname(workspacePackagePath)); + // emulate having run "npm i" / "yarn install" + await utils.mkdir(path.resolve(path.dirname(workspacePackagePath), 'node_modules')); + + // create the package's package.json + await fspromises.writeFile( + packagePackagePath, + JSON.stringify({ + name: 'testp', + // no custom configuration + }) + ); + + process.chdir(path.dirname(packagePackagePath)); + + const returnValue = await binary.DryMongoBinary.generatePaths(opts); + expect(returnValue).toStrictEqual({ + resolveConfig: '', // empty because not having an extra config value + relative: path.resolve(path.dirname(packagePackagePath), 'mongodb-binaries', binaryName), + homeCache: path.resolve(tmpDir, 'homedir/.cache/mongodb-binaries', binaryName), + modulesCache: path.resolve( + path.dirname(workspacePackagePath), + 'node_modules/.cache/mongodb-memory-server', + binaryName + ), + } as binary.DryMongoBinaryPaths); + }); + + it('should resolve modulesCache relative to cwd if no package.json with config options are found', async () => { + const workspacePackagePath = path.resolve(tmpDir, 'package.json'); + const packagePackagePath = path.resolve(tmpDir, 'packages/testy/package.json'); + await utils.mkdir(path.dirname(packagePackagePath)); + + // create the shared workspace package.json + await fspromises.writeFile( + workspacePackagePath, + JSON.stringify({ + name: 'testw', + private: true, + devDependencies: { + 'mongodb-memory-server': '0.0.0', + }, + // no custom configuration + }) + ); + // emulate having resolved the package.json files and found the above file + jest.spyOn(resConfig, 'packageJsonPath').mockReturnValue(undefined); + // emulate having run "npm i" / "yarn install" + await utils.mkdir(path.resolve(path.dirname(workspacePackagePath), 'node_modules')); + + // create the package's package.json + await fspromises.writeFile( + packagePackagePath, + JSON.stringify({ + name: 'testp', + // no custom configuration + }) + ); + + process.chdir(path.dirname(packagePackagePath)); + + const returnValue = await binary.DryMongoBinary.generatePaths(opts); + expect(returnValue).toStrictEqual({ + resolveConfig: '', // empty because not having an extra config value + relative: path.resolve(path.dirname(packagePackagePath), 'mongodb-binaries', binaryName), + homeCache: path.resolve(tmpDir, 'homedir/.cache/mongodb-binaries', binaryName), + modulesCache: path.resolve( + path.dirname(packagePackagePath), + 'node_modules/.cache/mongodb-memory-server', + binaryName + ), + } as binary.DryMongoBinaryPaths); + }); }); describe('getBinaryName', () => { diff --git a/packages/mongodb-memory-server-core/src/util/resolveConfig.ts b/packages/mongodb-memory-server-core/src/util/resolveConfig.ts index 69a46a7ae..b150f402e 100644 --- a/packages/mongodb-memory-server-core/src/util/resolveConfig.ts +++ b/packages/mongodb-memory-server-core/src/util/resolveConfig.ts @@ -143,6 +143,14 @@ export function resolveConfig(variableName: ResolveConfigVariables): string | un )?.toString(); } +/** + * Get the directory path of the `package.json` with config options, if available + * @returns The directory of the `package.json`, otherwise `undefined` + */ +export function packageJsonPath(): string | undefined { + return packagejson?.filePath; +} + export default resolveConfig; /**