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

feat(load): accept functions as parser presets #2982

Merged
merged 1 commit into from Jan 20, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -56,6 +56,7 @@ exports[`validation should fail for parserPreset 1`] = `
"Commitlint configuration in parserPreset.js is invalid:
- Property \\"parserPreset\\" has the wrong type - should be string.
- Property \\"parserPreset\\" has the wrong type - should be object.
- \\"parserPreset\\" should be a function. Value: [].
- \\"parserPreset\\" should match exactly one schema in oneOf. Value: [].
"
`;
Expand Down
3 changes: 2 additions & 1 deletion @commitlint/config-validator/src/commitlint.schema.json
Expand Up @@ -57,7 +57,8 @@
"parserOpts": {}
},
"additionalProperties": true
}
},
{"typeof": "function"}
]
},
"helpUrl": {
Expand Down
55 changes: 55 additions & 0 deletions @commitlint/load/src/utils/load-parser-opts.test.ts
@@ -0,0 +1,55 @@
import {loadParserOpts} from './load-parser-opts';

test('handles a plain preset', async () => {
const preset = {
parserOpts: {},
};

expect(await loadParserOpts(preset)).toEqual(preset);
});

test('handles primitive values', async () => {
expect(await loadParserOpts('')).toEqual(undefined);
expect(await loadParserOpts(undefined)).toEqual(undefined);
});

test('handles an object without any parserOpts', async () => {
const preset = {};
expect(await loadParserOpts(preset)).toEqual(preset);
});

test('handles nested parserOpts', async () => {
const opts = {a: 4};

// plain nested parserOpts
let loaded = await loadParserOpts({
parserOpts: {
parserOpts: opts,
},
});
expect(loaded).toHaveProperty('parserOpts', opts);

// async nested parserOpts
loaded = await loadParserOpts({
parserOpts: Promise.resolve({
parserOpts: opts,
}),
});
expect(loaded).toHaveProperty('parserOpts', opts);
});

test('runs a sync function which returns the preset', async () => {
const preset = {};
const fn = () => preset;
const opts = await loadParserOpts(fn);

expect(opts).toEqual(preset);
});

test('runs an async function which returns the preset', async () => {
const preset = {};
const fn = async () => preset;
const opts = await loadParserOpts(fn);

expect(opts).toEqual(preset);
});
12 changes: 11 additions & 1 deletion @commitlint/load/src/utils/load-parser-opts.ts
@@ -1,5 +1,7 @@
import {ParserPreset} from '@commitlint/types';

type Awaitable<T> = T | PromiseLike<T>;

function isObjectLike(obj: unknown): obj is Record<string, unknown> {
return Boolean(obj) && typeof obj === 'object'; // typeof null === 'object'
}
Expand All @@ -15,8 +17,16 @@ function isParserOptsFunction<T extends ParserPreset>(
}

export async function loadParserOpts(
pendingParser: string | ParserPreset | Promise<ParserPreset> | undefined
pendingParser:
| string
| Awaitable<ParserPreset>
| (() => Awaitable<ParserPreset>)
| undefined
): Promise<ParserPreset | undefined> {
if (typeof pendingParser === 'function') {
return loadParserOpts(pendingParser());
}

if (!pendingParser || typeof pendingParser !== 'object') {
return undefined;
}
Expand Down