Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extend: Add extend config key prefix to avoid #27

Merged
merged 1 commit into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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}`);
}
}

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"
}