Skip to content

Commit

Permalink
extend: Add extend config key prefix to avoid
Browse files Browse the repository at this point in the history
  • Loading branch information
BenjD90 committed Oct 27, 2023
1 parent 5252bbf commit a5575ca
Show file tree
Hide file tree
Showing 14 changed files with 207 additions and 27 deletions.
88 changes: 64 additions & 24 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface N9ConfOptions {
key?: {
name?: string;
format?: ExtendConfigKeyFormat;
prefixToAvoid?: string;
};
mergeStrategy?: N9ConfMergeStrategy;
};
Expand Down Expand Up @@ -115,7 +116,9 @@ function loadExtendConfig(
extendConfigPath: string,
extension: string = Path.extname(extendConfigPath),
deep: number = 3,
): { metadata: { mergeStrategy: N9ConfMergeStrategy } } {
):
| { fileContent: { metadata: { mergeStrategy: N9ConfMergeStrategy } }; filePath: string }
| undefined {
let type: 'json' | 'yaml';

switch (extension) {
Expand All @@ -137,7 +140,10 @@ function loadExtendConfig(
const path = Path.join(dir, `${fileNameWithoutExtension}${extension}`);

if (fs.existsSync(path)) {
return readConfigFile(path, type);
return {
fileContent: readConfigFile(path, type),
filePath: path,
};
}

if (deep > 0) {
Expand All @@ -157,28 +163,58 @@ function loadExtendConfig(
}
}

function getConfigKeyWithFormat(
format: ExtendConfigKeyFormat,
app: { name: string; version: string },
): string {
function getConfigKeyWithFormat(format: ExtendConfigKeyFormat, appName: string): string {
switch (format) {
case ExtendConfigKeyFormat.DROMEDARY_CASE:
return _.chain(app.name).camelCase().lowerFirst().value();
return _.chain(appName).camelCase().lowerFirst().value();
case ExtendConfigKeyFormat.PASCAL_CASE:
return _.chain(app.name).camelCase().upperFirst().value();
return _.chain(appName).camelCase().upperFirst().value();
case ExtendConfigKeyFormat.KEBAB_CASE:
return _.chain(app.name).kebabCase().value();
return _.chain(appName).kebabCase().value();
case ExtendConfigKeyFormat.UPPER_KEBAB_CASE:
return _.chain(app.name).kebabCase().toUpper().value();
return _.chain(appName).kebabCase().toUpper().value();
case ExtendConfigKeyFormat.SNAKE_CASE:
return _.chain(app.name).snakeCase().value();
return _.chain(appName).snakeCase().value();
case ExtendConfigKeyFormat.UPPER_SNAKE_CASE:
return _.chain(app.name).snakeCase().toUpper().value();
return _.chain(appName).snakeCase().toUpper().value();
default:
throw new Error(`unknown-extend-config-key-format-${format}`);
}
}

function removePrefixFromString(prefixToAvoid: string, value: string): string {
if (value.startsWith(prefixToAvoid)) {
return value.slice(prefixToAvoid.length);
}
return value;
}

function getExtendCongigKey(appName: string, options: N9ConfOptions): string {
let extendConfigKey: string = appName;
if (options.extendConfig) {
if (options.extendConfig.key?.name) {
if (options.extendConfig.key?.prefixToAvoid) {
log(`Setting extendConfig.key.prefixToAvoid not used.`);
}
extendConfigKey = options.extendConfig.key.name;
} else if (options.extendConfig.key?.format) {
if (options.extendConfig.key.prefixToAvoid) {
const appNameWithoutPrefix = removePrefixFromString(
options.extendConfig.key.prefixToAvoid,
appName,
);
extendConfigKey = getConfigKeyWithFormat(
options.extendConfig.key.format,
appNameWithoutPrefix,
);
} else {
extendConfigKey = getConfigKeyWithFormat(options.extendConfig.key.format, appName);
}
}
}
return extendConfigKey;
}

export default (options: N9ConfOptions = {}): object | any => {
const rootDir = appRootDir.get();
const confPath: string = process.env.NODE_CONF_PATH || options.path || Path.join(rootDir, 'conf');
Expand All @@ -194,29 +230,27 @@ export default (options: N9ConfOptions = {}): object | any => {
// Fetch package.json of the app
/* eslint-disable-next-line import/no-dynamic-require, @typescript-eslint/no-var-requires, global-require */
const app: { name: string; version: string } = require(packageJsonDirPath);

let extendConfigKey: string = app.name;
if (options.extendConfig) {
if (options.extendConfig.key?.name) extendConfigKey = options.extendConfig.key.name;
else if (options.extendConfig.key?.format) {
extendConfigKey = getConfigKeyWithFormat(options.extendConfig.key.format, app);
}
}
const extendConfigKey = getExtendCongigKey(app.name, options);

const environments = ['application', `${currentEnvironment}`, 'local']; // Files to load
const sources: N9ConfBaseConf[] = []; // Sources of each config file
let extendConfig: Record<'application' | 'local' | string, any> & {
metadata: { mergeStrategy: N9ConfMergeStrategy };
};
let extendConfigFileLoadedPath: string;

if (extendConfigPath) {
try {
extendConfig = loadExtendConfig(extendConfigPath);
const loadExtendConfigResult = loadExtendConfig(extendConfigPath);
if (loadExtendConfigResult) {
extendConfig = loadExtendConfigResult.fileContent;
extendConfigFileLoadedPath = loadExtendConfigResult.filePath;
}
} catch (err) {
throw new Error(
`Error while loading extendable config (${
err.message
}) : ${extendConfigPath} ${JSON.stringify(err)}`,
}) : ${extendConfigPath} ${JSON.stringify(err)} ${err.stack}`,
);
}
}
Expand All @@ -237,7 +271,7 @@ export default (options: N9ConfOptions = {}): object | any => {
log(`Error while loading config file '${filePath}' : ${JSON.stringify(err)}`);
}
} catch (e) {
log(`Can't stringify error ${err && err.message}`);
log(`Can't stringify error ${err?.message}`);

Check warning on line 274 in src/index.ts

View check run for this annotation

Codecov / codecov/patch

src/index.ts#L274

Added line #L274 was not covered by tests
}
}

Expand All @@ -254,7 +288,13 @@ export default (options: N9ConfOptions = {}): object | any => {
}

// Load its source
log(`Loading ${environment} configuration`);
log(
`Loading ${environment} configuration${
extendConfig
? `extended with file ${extendConfigFileLoadedPath} key ${environment}.${extendConfigKey}`
: ''
}`,
);

/* eslint-disable-next-line import/no-dynamic-require, @typescript-eslint/no-var-requires, global-require */
const loadedSource = require(filePath);
Expand Down
83 changes: 80 additions & 3 deletions test/extend-conf-key-format.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/naming-convention */
import test, { ExecutionContext } from 'ava';
import { join } from 'path';

Expand All @@ -7,7 +8,7 @@ test.beforeEach(() => {
delete process.env.NODE_ENV;
});

const formatWithExpectedValues: Record<ExtendConfigKeyFormat, string> = {
const formatToExpectedValues: Record<ExtendConfigKeyFormat, string> = {
[ExtendConfigKeyFormat.DROMEDARY_CASE]: 'dromedaryCase',
[ExtendConfigKeyFormat.PASCAL_CASE]: 'PascalCase',
[ExtendConfigKeyFormat.KEBAB_CASE]: 'kebab-case',
Expand All @@ -16,7 +17,7 @@ const formatWithExpectedValues: Record<ExtendConfigKeyFormat, string> = {
[ExtendConfigKeyFormat.UPPER_SNAKE_CASE]: 'UPPER_SNAKE_CASE',
};

for (const [name, expectedSuffix] of Object.entries(formatWithExpectedValues)) {
for (const [name, expectedValue] of Object.entries(formatToExpectedValues)) {
test(`Extendable conf with key format : ${name}`, (t: ExecutionContext) => {
const conf: { textValue: string } = src({
path: join(__dirname, './fixtures/extend-conf-key-format'),
Expand All @@ -29,9 +30,85 @@ for (const [name, expectedSuffix] of Object.entries(formatWithExpectedValues)) {
overridePackageJsonDirPath: join(__dirname, './fixtures/extend-conf-key-format'),
});

t.is(conf.textValue, `text override ${expectedSuffix}`, `value is overridden`);
t.is(conf.textValue, `text override ${expectedValue}`, `value is overridden`);
});
}

const formatToExpectedValuesWithPrefix: Record<ExtendConfigKeyFormat, Record<string, string>> = {
[ExtendConfigKeyFormat.DROMEDARY_CASE]: {
'prefix1': 'dromedaryCase',
'prefix-': 'dromedaryCase',
'useless-prefix': 'dromedaryCase',
},
[ExtendConfigKeyFormat.PASCAL_CASE]: {
'prefix1': 'PascalCase',
'prefix-': 'PascalCase',
'useless-prefix': 'PascalCase',
},
[ExtendConfigKeyFormat.KEBAB_CASE]: {
'prefix1': 'kebab-case',
'prefix-': 'kebab-case',
'useless-prefix': 'kebab-case',
},
[ExtendConfigKeyFormat.UPPER_KEBAB_CASE]: {
'prefix1': 'UPPER-KEBAB-CASE',
'prefix-': 'UPPER-KEBAB-CASE',
'useless-prefix': 'UPPER-KEBAB-CASE',
},
[ExtendConfigKeyFormat.SNAKE_CASE]: {
'prefix1': 'snake_case',
'prefix-': 'snake_case',
'useless-prefix': 'snake_case',
},
[ExtendConfigKeyFormat.UPPER_SNAKE_CASE]: {
'prefix1': 'UPPER_SNAKE_CASE',
'prefix-': 'UPPER_SNAKE_CASE',
'useless-prefix': 'UPPER_SNAKE_CASE',
},
};

for (const [name, mapxOfPrefixToExpectedValue] of Object.entries(
formatToExpectedValuesWithPrefix,
)) {
for (const [prefix, expectedValue] of Object.entries(mapxOfPrefixToExpectedValue)) {
test(`Extendable conf with key format : ${name} and prefixToAvoid ${prefix}`, (t: ExecutionContext) => {
const conf: { textValue: string } = src({
path: join(__dirname, './fixtures/extend-conf-key-format'),
extendConfig: {
path: {
absolute: join(__dirname, `./fixtures/extend-conf-key-format/with-${prefix}/env.yaml`),
},
key: { format: name as ExtendConfigKeyFormat, prefixToAvoid: prefix },
},
overridePackageJsonDirPath: join(
__dirname,
`./fixtures/extend-conf-key-format/with-${prefix}`,
),
});

t.is(conf.textValue, `text override ${expectedValue}`, `value is overridden`);
});

test(`Extendable conf with key format : ${name} and prefixToAvoid ${prefix} without format`, (t: ExecutionContext) => {
const conf: { textValue: string } = src({
path: join(__dirname, './fixtures/extend-conf-key-format'),
extendConfig: {
path: {
absolute: join(__dirname, `./fixtures/extend-conf-key-format/with-${prefix}/env.yaml`),
},
key: { name: 'APP-NAME', prefixToAvoid: prefix },
},
overridePackageJsonDirPath: join(
__dirname,
`./fixtures/extend-conf-key-format/with-${prefix}`,
),
});

t.is(conf.textValue, `text override UPPER-KEBAB-CASE`, `value is overridden`);
});
}
}

test(`Extendable conf with key format : unknown format`, (t: ExecutionContext) => {
t.throws(
() =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
textValue: 'base value',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default {};
13 changes: 13 additions & 0 deletions test/fixtures/extend-conf-key-format/with-prefix-/env.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
application:
appName:
textValue: text override dromedaryCase
AppName:
textValue: text override PascalCase
app-name:
textValue: text override kebab-case
APP-NAME:
textValue: text override UPPER-KEBAB-CASE
app_name:
textValue: text override snake_case
APP_NAME:
textValue: text override UPPER_SNAKE_CASE
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "prefix-app-name",
"version": "0.0.4"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
textValue: 'base value',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default {};
13 changes: 13 additions & 0 deletions test/fixtures/extend-conf-key-format/with-prefix1/env.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
application:
appName:
textValue: text override dromedaryCase
AppName:
textValue: text override PascalCase
app-name:
textValue: text override kebab-case
APP-NAME:
textValue: text override UPPER-KEBAB-CASE
app_name:
textValue: text override snake_case
APP_NAME:
textValue: text override UPPER_SNAKE_CASE
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "prefix1app-name",
"version": "0.0.4"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
textValue: 'base value',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default {};
13 changes: 13 additions & 0 deletions test/fixtures/extend-conf-key-format/with-useless-prefix/env.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
application:
appName:
textValue: text override dromedaryCase
AppName:
textValue: text override PascalCase
app-name:
textValue: text override kebab-case
APP-NAME:
textValue: text override UPPER-KEBAB-CASE
app_name:
textValue: text override snake_case
APP_NAME:
textValue: text override UPPER_SNAKE_CASE
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "app-name",
"version": "0.0.4"
}

0 comments on commit a5575ca

Please sign in to comment.