Skip to content

Commit 8f16a2a

Browse files
committed
feat(resolveConfig::findPackageJson): re-write internals to be more maintainable
1 parent abd4278 commit 8f16a2a

File tree

2 files changed

+63
-31
lines changed

2 files changed

+63
-31
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { promises as fspromises } from 'fs';
22
import * as tmp from 'tmp';
33
import resolveConfig, { findPackageJson, ResolveConfigVariables } from '../resolveConfig';
4+
import { assertion, isNullOrUndefined } from '../utils';
45

56
tmp.setGracefulCleanup();
67

@@ -25,7 +26,7 @@ describe('resolveConfig', () => {
2526
const originalDir = process.cwd();
2627
let tmpObj: tmp.DirResult;
2728

28-
describe('configuration from closest package.json', () => {
29+
describe('findPackageJson', () => {
2930
beforeAll(async () => {
3031
// Set up test project/subproject structure in a temporary directory:
3132
//
@@ -62,24 +63,27 @@ describe('resolveConfig', () => {
6263
// expect to get the outer package.json
6364
process.chdir(`${tmpObj.name}/project`);
6465
const out = findPackageJson();
66+
assertion(!isNullOrUndefined(out));
6567
expect(resolveConfig(ResolveConfigVariables.VERSION)).toBe('3.0.0');
66-
expect(out.inner).toBe(false);
68+
expect(out.config.inner).toBe(false);
6769
});
6870

6971
test('in subproject', () => {
7072
// expect to get the inner package.json
7173
process.chdir(`${tmpObj.name}/project/subproject`);
7274
const out = findPackageJson();
75+
assertion(!isNullOrUndefined(out));
7376
expect(resolveConfig(ResolveConfigVariables.VERSION)).toBe('4.0.0');
74-
expect(out.inner).toBe(true);
77+
expect(out.config.inner).toBe(true);
7578
});
7679

7780
test('with explicit directory in reInitializePackageJson', () => {
7881
// expect to get the inner package.json
7982
process.chdir(`${tmpObj.name}/project`);
8083
const out = findPackageJson(`${tmpObj.name}/project/subproject`);
84+
assertion(!isNullOrUndefined(out));
8185
expect(resolveConfig(ResolveConfigVariables.VERSION)).toBe('4.0.0');
82-
expect(out.inner).toBe(true);
86+
expect(out.config.inner).toBe(true);
8387
});
8488
});
8589
});

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

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { findSync } from 'new-find-package-json';
33
import debug from 'debug';
44
import * as path from 'path';
55
import { readFileSync } from 'fs';
6+
import { isNullOrUndefined } from './utils';
67

78
const log = debug('MongoMS:ResolveConfig');
89

@@ -34,6 +35,13 @@ export const defaultValues = new Map<ResolveConfigVariables, string>([
3435
[ResolveConfigVariables.SYSTEM_BINARY_VERSION_CHECK, 'true'],
3536
]);
3637

38+
interface PackageJSON {
39+
/** The Path where the package.json was found (directory, not the file) */
40+
filePath: string;
41+
/** The Options that were parsed from the package.json */
42+
config: Record<string, string>;
43+
}
44+
3745
/**
3846
* Set an Default value for an specific key
3947
* Mostly only used internally (for the "global-x.x" packages)
@@ -44,49 +52,69 @@ export function setDefaultValue(key: ResolveConfigVariables, value: string): voi
4452
defaultValues.set(key, value);
4553
}
4654

47-
let packageJsonConfig: Record<string, string> = {};
55+
// let packageJsonConfig: Record<string, string> = {};
56+
let packagejson: PackageJSON | undefined = undefined;
4857
/**
4958
* Find the nearest package.json (that has an non-empty config field) for the provided directory
5059
* @param directory Set an custom directory to search the config in (default: process.cwd())
60+
* @returns what "packagejson" variable is
5161
*/
52-
export function findPackageJson(directory?: string): Record<string, string> {
53-
let filename: string | undefined;
62+
export function findPackageJson(directory?: string): PackageJSON | undefined {
5463
for (const filename of findSync(directory || process.cwd())) {
5564
log(`findPackageJson: Found package.json at "${filename}"`);
5665
const readout: Record<string, any> = JSON.parse(readFileSync(filename).toString());
5766

58-
if (Object.keys(readout?.config?.mongodbMemoryServer ?? {}).length > 0) {
67+
/** Shorthand for the long path */
68+
const config = readout?.config?.mongodbMemoryServer;
69+
70+
if (!isNullOrUndefined(config) && Object.keys(config ?? {}).length > 0) {
5971
log(`findPackageJson: Found package with non-empty config field at "${filename}"`);
6072

61-
// the optional chaining is needed, because typescript wont accept an "isNullOrUndefined" in the if with "&& Object.keys"
62-
packageJsonConfig = readout?.config?.mongodbMemoryServer;
73+
const filepath = path.dirname(filename);
74+
75+
packagejson = {
76+
filePath: filepath,
77+
config: processConfigOption(config, filepath),
78+
};
6379
break;
6480
}
6581
}
6682

67-
// block for all file-path resolving
68-
if (filename) {
69-
// These are so that "camelCase" doesnt get executed much & de-duplicate code
70-
// "cc*" means "camelcase"
71-
const ccDownloadDir = camelCase(ResolveConfigVariables.DOWNLOAD_DIR);
72-
const ccSystemBinary = camelCase(ResolveConfigVariables.SYSTEM_BINARY);
73-
74-
if (ccDownloadDir in packageJsonConfig) {
75-
packageJsonConfig[ccDownloadDir] = path.resolve(
76-
path.dirname(filename),
77-
packageJsonConfig[ccDownloadDir]
78-
);
79-
}
83+
return packagejson;
84+
}
8085

81-
if (ccSystemBinary in packageJsonConfig) {
82-
packageJsonConfig[ccSystemBinary] = path.resolve(
83-
path.dirname(filename),
84-
packageJsonConfig[ccSystemBinary]
85-
);
86-
}
86+
/**
87+
* Apply Proccessing to input options (like resolving paths)
88+
* @param input The input to process
89+
* @param filepath The FilePath for the input to resolve relative paths to (needs to be a dirname and absolute)
90+
* @returns always returns a object
91+
*/
92+
export function processConfigOption(input: unknown, filepath: string): Record<string, string> {
93+
log('processConfigOption', input, filepath);
94+
95+
if (typeof input !== 'object') {
96+
log('processConfigOptions: input was not a object');
97+
98+
return {};
99+
}
100+
101+
// cast because it was tested before that "input" is a object and the key can only be a string in a package.json
102+
const returnobj = input as Record<string, string>;
103+
104+
// These are so that "camelCase" doesnt get executed much & de-duplicate code
105+
// "cc*" means "camelcase"
106+
const ccDownloadDir = camelCase(ResolveConfigVariables.DOWNLOAD_DIR);
107+
const ccSystemBinary = camelCase(ResolveConfigVariables.SYSTEM_BINARY);
108+
109+
if (ccDownloadDir in returnobj) {
110+
returnobj[ccDownloadDir] = path.resolve(filepath, returnobj[ccDownloadDir]);
111+
}
112+
113+
if (ccSystemBinary in returnobj) {
114+
returnobj[ccSystemBinary] = path.resolve(filepath, returnobj[ccSystemBinary]);
87115
}
88116

89-
return packageJsonConfig;
117+
return returnobj;
90118
}
91119

92120
/**
@@ -96,7 +124,7 @@ export function findPackageJson(directory?: string): Record<string, string> {
96124
export function resolveConfig(variableName: ResolveConfigVariables): string | undefined {
97125
return (
98126
process.env[envName(variableName)] ??
99-
packageJsonConfig[camelCase(variableName)] ??
127+
packagejson?.config[camelCase(variableName)] ??
100128
defaultValues.get(variableName)
101129
)?.toString();
102130
}

0 commit comments

Comments
 (0)