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

Easier to use option type #51

Merged
merged 2 commits into from
Apr 9, 2020
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
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,42 @@ gitlog(options)
.catch((err) => console.log(err));
```

`gitlog` comes with full typescript support!

```ts
import gitlog, { GitlogOptions } from "gitlog";

// Option 1: Just use the function, returned commit type has specified fields
gitlog({
repo: "foo",
fields: ["subject", "authorName", "authorDate"],
});

// Option 2: Use Options type to create options
const options: GitlogOptions<"subject" | "authorName" | "authorDate"> = {
repo: "foo",
fields: ["subject", "authorName", "authorDate"],
};

gitlog(options);

// Option 3: Typescript Magic
const options = {
repo: "foo",
fields: ["subject", "authorName", "authorDate"] as const,
};

gitlog(options);

// NOT SUPPORTED: Without "as const" gitlog can't create a good return type
const options = {
repo: "foo",
fields: ["subject", "authorName", "authorDate"],
};

gitlog(options);
```

## Options

See [git log](http://git-scm.com/docs/git-log)
Expand Down Expand Up @@ -203,6 +239,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d

<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
95 changes: 44 additions & 51 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ const defaultFields = [
] as const;
type DefaultField = typeof defaultFields[number];

export interface GitlogOptions<
Fields extends readonly CommitField[] = DefaultField[]
> {
export interface GitlogOptions<Fields extends string = DefaultField> {
/** The location of the repo */
repo: string;
/**
Expand Down Expand Up @@ -68,7 +66,7 @@ export interface GitlogOptions<
*/
number?: number;
/** An array of fields to return from the log */
fields?: Fields;
fields?: readonly Fields[];
/**
* Below fields was returned from the log:
*
Expand Down Expand Up @@ -104,17 +102,17 @@ export interface GitlogOptions<

const defaultOptions = {
number: 10,
fields: (defaultFields as unknown) as readonly CommitField[],
fields: defaultFields,
nameStatus: true,
includeMergeCommitFiles: false,
findCopiesHarder: false,
all: false,
};

/** Add optional parameter to command */
function addOptional<Fields extends readonly CommitField[] = DefaultField[]>(
function addOptional<Field extends string = DefaultField>(
command: string,
options: GitlogOptions<Fields>
options: GitlogOptions<Field>
) {
let commandWithOptions = command;
const cmdOptional = [
Expand Down Expand Up @@ -220,8 +218,8 @@ const parseCommits = <T extends string>(
};

/** Run "git log" and return the result as JSON */
function createCommand<T extends readonly CommitField[] = DefaultField[]>(
options: GitlogOptions<T> & typeof defaultOptions
function createCommand<T extends CommitField | DefaultField = DefaultField>(
options: GitlogOptions<T>
) {
// Start constructing command
let command = "git log ";
Expand All @@ -246,13 +244,15 @@ function createCommand<T extends readonly CommitField[] = DefaultField[]>(
command += ' --pretty="@begin@';

// Iterating through the fields and adding them to the custom format
options.fields.forEach((field) => {
if (!fieldMap[field] && notOptFields.indexOf(field as NotOptField) === -1) {
throw new Error(`Unknown field: ${field}`);
}
if (options.fields) {
options.fields.forEach((field) => {
if (!fieldMap[field] && !notOptFields.includes(field as any)) {
throw new Error(`Unknown field: ${field}`);
}

command += delimiter + fieldMap[field];
});
command += delimiter + fieldMap[field];
});
}

// Close custom format
command += '@end@"';
Expand Down Expand Up @@ -284,33 +284,30 @@ type CommitBaseWithFiles<Field extends string> = Record<
string
> & { files: string[] };

function gitlog<Fields extends readonly CommitField[] = DefaultField[]>(
userOptions: GitlogOptions<Fields> & { nameStatus: false },
cb: (err: GitlogError, commits: CommitBase<Fields[number]>[]) => void
function gitlog<Field extends CommitField = DefaultField>(
userOptions: GitlogOptions<Field> & { nameStatus: false },
cb: (err: GitlogError, commits: CommitBase<Field>[]) => void
): void;

function gitlog<Fields extends readonly CommitField[] = DefaultField[]>(
userOptions: GitlogOptions<Fields>,
cb: (err: GitlogError, commits: CommitBaseWithFiles<Fields[number]>[]) => void
function gitlog<Field extends CommitField = DefaultField>(
userOptions: GitlogOptions<Field>,
cb: (err: GitlogError, commits: CommitBaseWithFiles<Field>[]) => void
): void;

function gitlog<Fields extends readonly CommitField[] = DefaultField[]>(
userOptions: GitlogOptions<Fields> & { nameStatus: false }
): CommitBase<Fields[number]>[];
function gitlog<Field extends CommitField = DefaultField>(
userOptions: GitlogOptions<Field> & { nameStatus: false }
): CommitBase<Field>[];

function gitlog<Fields extends readonly CommitField[] = DefaultField[]>(
userOptions: GitlogOptions<Fields>
): CommitBaseWithFiles<Fields[number]>[];
function gitlog<Field extends CommitField = DefaultField>(
userOptions: GitlogOptions<Field>
): CommitBaseWithFiles<Field>[];

function gitlog<Fields extends readonly CommitField[] = DefaultField[]>(
userOptions: GitlogOptions<Fields>,
function gitlog<Field extends CommitField = DefaultField>(
userOptions: GitlogOptions<Field>,
cb?:
| ((err: GitlogError, commits: CommitBase<Fields[number]>[]) => void)
| ((
err: GitlogError,
commits: CommitBaseWithFiles<Fields[number]>[]
) => void)
): CommitBase<Fields[number]>[] | CommitBaseWithFiles<Fields[number]>[] | void {
| ((err: GitlogError, commits: CommitBase<Field>[]) => void)
| ((err: GitlogError, commits: CommitBaseWithFiles<Field>[]) => void)
): CommitBase<Field>[] | CommitBaseWithFiles<Field>[] | void {
if (!userOptions.repo) {
throw new Error("Repo required!");
}
Expand All @@ -321,7 +318,7 @@ function gitlog<Fields extends readonly CommitField[] = DefaultField[]>(

// Set defaults
const options = {
...defaultOptions,
...(defaultOptions as any),
...userOptions,
};
const execOptions = { cwd: userOptions.repo, ...userOptions.execOptions };
Expand Down Expand Up @@ -356,21 +353,17 @@ function gitlog<Fields extends readonly CommitField[] = DefaultField[]>(
});
}

export function gitlogPromise<
Fields extends readonly CommitField[] = DefaultField[]
>(
options: GitlogOptions<Fields> & { nameStatus: false }
): Promise<CommitBase<Fields[number]>[]>;

export function gitlogPromise<
Fields extends readonly CommitField[] = DefaultField[]
>(
options: GitlogOptions<Fields>
): Promise<CommitBaseWithFiles<Fields[number]>[]>;

export function gitlogPromise<
Fields extends readonly CommitField[] = DefaultField[]
>(options: GitlogOptions<Fields>): Promise<CommitBase<Fields[number]>[]> {
export function gitlogPromise<Field extends CommitField = DefaultField>(
options: GitlogOptions<Field> & { nameStatus: false }
): Promise<CommitBase<Field>[]>;

export function gitlogPromise<Field extends CommitField = DefaultField>(
options: GitlogOptions<Field>
): Promise<CommitBaseWithFiles<Field>[]>;

export function gitlogPromise<Field extends CommitField = DefaultField>(
options: GitlogOptions<Field>
): Promise<CommitBase<Field>[]> {
return new Promise((resolve, reject) => {
gitlog(options, (err, commits) => {
if (err) {
Expand Down