Skip to content

[WIP] Feat: add which-config #92

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

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ This will check all commits and will fail if your commits do not meet the define
$ sgc check --start 84a1abd
```

### which-config

This command shows which configs gets applied to `sgc`

```sh
$ sgc which-config
```

## Config

> Just create a `.sgcrc` in your project root or you can add everything in your `package.json` with the value `sgc`
Expand Down
37 changes: 34 additions & 3 deletions __tests__/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,37 @@ it('read global config', () => {
const sgcrc = json.readToObjSync(path.join(fixtures, '.sgcrc'));

fs.writeFileSync(path.join(homedir, '.sgcrc'), JSON.stringify(sgcrc));
expect(new Config().config).toEqual(sgcrc);

const { config } = new Config();

fs.removeSync(path.join(homedir, '.sgcrc'));

expect(homedir).toBe('test');
expect(config).toEqual(sgcrc);
});

it('read local config from `sgc.config.js`', () => {
const sgcrc = json.readToObjSync(path.join(fixtures, '.sgcrc'));

fs.writeFileSync(path.join(cwd, 'sgc.config.js'), `module.exports = (${JSON.stringify(sgcrc)})`);
expect(new Config().config).toEqual(sgcrc);

const { config } = new Config();

fs.removeSync(path.join(cwd, 'sgc.config.js'));

expect(config).toEqual(sgcrc);
});

it('read global config from `sgc.config.js`', () => {
const sgcrc = json.readToObjSync(path.join(fixtures, '.sgcrc'));

fs.writeFileSync(path.join(homedir, 'sgc.config.js'), `module.exports = (${JSON.stringify(sgcrc)})`);
expect(new Config().config).toEqual(sgcrc);

const { config } = new Config();

fs.removeSync(path.join(homedir, 'sgc.config.js'));

expect(config).toEqual(sgcrc);
});

it('read a .sgcrc_default from a deep nested cwd', () => {
Expand All @@ -95,3 +108,21 @@ it('read a .sgcrc_default from a deep nested cwd', () => {

expect(new Config(deepCwd).config).toEqual(fixturesConfig);
});

it('should get the right config path', () => {
const sgcrc = json.readToObjSync(path.join(fixtures, '.sgcrc'));

fs.writeFileSync(path.join(homedir, 'sgc.config.js'), `module.exports = (${JSON.stringify(sgcrc)})`);

const { configPath } = new Config();

fs.removeSync(path.join(homedir, 'sgc.config.js'));

expect(path.basename(configPath)).toBe('sgc.config.js');
});

it('should get the right config path', () => {
const { configPath } = new Config();

expect(path.basename(configPath)).toBe('package.json');
});
118 changes: 90 additions & 28 deletions lib/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,36 +33,43 @@ export interface SgcConfig {
};
}

const safeRequire = (jsPath: string | null): SgcConfig | false => (
// eslint-disable-next-line global-require, import/no-dynamic-require
jsPath && fs.existsSync(jsPath) && require(jsPath)
);

class Config {
altPath: string | null;
alternativeCwd: string | null;

fileName: string;
sgcConfigName: string;

constructor(altPath: string | null = null, fileName = '.sgcrc') {
this.altPath = altPath;
this.fileName = fileName;
constructor(alternativeCwd: string | null = null, sgcConfigName = '.sgcrc') {
this.alternativeCwd = alternativeCwd;
this.sgcConfigName = sgcConfigName;

this.setConfig();
}

private setConfig(): SgcConfig {
const pathString = findup(this.fileName, { cwd: this.altPath || cwd });
const localeConfigJS = safeRequire(findup('sgc.config.js', { cwd }));
const localeConfig = pathString ? json.readToObjSync<SgcConfig>(pathString) : false;
const globalConfigJS = safeRequire(path.join(homedir, 'sgc.config.js'));
const globalConfig = json.readToObjSync<SgcConfig>(path.join(homedir, '.sgcrc'));
const packageJson = findup('package.json', { cwd });
const packageConfig = packageJson
? (json.readToObjSync<{ sgc?: SgcConfig }>(packageJson) || {}).sgc
: false;
const sgcrcDefaultConfig = json.readToObjSync<SgcConfig>(path.join(__dirname, '..', '.sgcrc')) as SgcConfig;
const sgcrcTestDefaultConfig = json.readToObjSync<SgcConfig>(path.join(__dirname, '..', '.sgcrc_default')) as SgcConfig;
const sgcrcDefault = sgcrcDefaultConfig || sgcrcTestDefaultConfig;
static safeRequire = (jsPath: string | null): SgcConfig | false => (
// eslint-disable-next-line global-require, import/no-dynamic-require
jsPath && require(jsPath)
)

static safeRead = (configPath: string | null): SgcConfig | false => (
!!configPath && json.readToObjSync<SgcConfig>(configPath)
)

static getPath = (configPath: string | null): string | null => (
!!configPath && fs.existsSync(configPath) ? configPath : null
)

private getConfigPath(): { path: string; defaultPath: string; type: 'rc' | 'js' | 'pkg' } {
// paths
const localPath = Config.getPath((
findup(this.sgcConfigName, { cwd: this.alternativeCwd || cwd })
));
const localJsPath = Config.getPath(findup('sgc.config.js', { cwd }));
const globalPath = Config.getPath(path.join(homedir, this.sgcConfigName));
const globalJsPath = Config.getPath(path.join(homedir, 'sgc.config.js'));
const packageJson = Config.getPath(findup('package.json', { cwd }));
const defaultPath = Config.getPath(path.join(__dirname, '..', '.sgcrc')) as string;
const testDefaultPath = Config.getPath(path.join(__dirname, '..', '.sgcrc_default')) as string;
const sgcrcDefault = defaultPath || testDefaultPath;

// priority order (1. highest priority):
// 1. local config
Expand All @@ -73,13 +80,64 @@ class Config {
// 3. default config
// - 1. from ../.sgcrc
// - 2. test case ../.sgcrc is renamed to ../.sgcrc_default
const config = localeConfigJS
|| localeConfig
|| packageConfig
|| globalConfigJS
|| globalConfig
const configPath = localJsPath
|| localPath
|| packageJson
|| globalJsPath
|| globalPath
|| sgcrcDefault;

let type: 'rc' | 'js' | 'pkg';

switch (path.extname(configPath)) {
case '.json':
type = 'pkg';
break;

case '.js':
type = 'js';
break;

default:
type = 'rc';
break;
}

return {
path: configPath,
defaultPath: sgcrcDefault,
type,
};
}

private setConfig(): SgcConfig {
const configPath = this.getConfigPath();
const sgcrcDefault: SgcConfig = Config.safeRead(configPath.defaultPath) as SgcConfig;

let config: SgcConfig = sgcrcDefault;
let readConfig: SgcConfig | false;

switch (configPath.type) {
case 'js':
readConfig = Config.safeRequire(configPath.path);
break;

case 'pkg':
readConfig = (
json.readToObjSync<{ sgc: SgcConfig }>(configPath.path)
|| { sgc: false as false }
).sgc;
break;

default:
case 'rc':
readConfig = Config.safeRead(configPath.path);
}

if (readConfig) {
config = readConfig;
}

// set defaults which are necessary
const modifiedConfig = merge({}, sgcrcDefault, config);

Expand All @@ -99,6 +157,10 @@ class Config {
public get config(): SgcConfig {
return this.setConfig();
}

public get configPath(): string {
return this.getConfigPath().path;
}
}

export default Config;
7 changes: 7 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#!/usr/bin/env node

import updateNotifier from 'update-notifier';
import chalk from 'chalk';
import yargs from 'yargs';

import pkg from '../package.json';
import cli from './cli';
import check from './check';
import Config from './Config';

const { argv } = yargs
.usage('Usage: $0')
Expand All @@ -31,6 +33,11 @@ const { argv } = yargs
},
},
check,
)
.command(
'which-config',
'Check which config got applied',
() => console.log('Following config gets used:\n', chalk.bold(new Config().configPath)),
);

updateNotifier({ pkg }).notify();
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
],
"homepage": "https://github.com/JPeer264/node-semantic-git-commit-cli#readme",
"devDependencies": {
"@types/chalk": "^2.2.0",
"@types/findup-sync": "^2.0.2",
"@types/jest": "^25.2.3",
"@types/lodash.merge": "^4.6.6",
Expand Down
9 changes: 5 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "dest",
"rootDir": "lib"
"rootDir": "lib",
"typeRoots": [
"./node_modules/@types",
"./typings"
]
},
"include": [
"lib"
],
"files": [
"./global.d.ts"
]
}
1 change: 1 addition & 0 deletions typings/chalk/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module 'chalk';
1 change: 0 additions & 1 deletion global.d.ts → typings/git-commit-range/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
declare module 'git-commit-range';
declare module 'chalk';