Skip to content

Commit

Permalink
improve life cycle hooks typings (#8652)
Browse files Browse the repository at this point in the history
* simpler hook types

* add changeset

* Update .changeset/plenty-bottles-prove.md

Co-authored-by: Saihajpreet Singh <saihajpreet.singh@gmail.com>

* only type changes

Co-authored-by: Saihajpreet Singh <saihajpreet.singh@gmail.com>
  • Loading branch information
jantimon and saihaj committed Dec 6, 2022
1 parent 94e382f commit c802a0c
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 35 deletions.
6 changes: 6 additions & 0 deletions .changeset/plenty-bottles-prove.md
@@ -0,0 +1,6 @@
---
'@graphql-codegen/cli': patch
'@graphql-codegen/plugin-helpers': major
---

improve typings for life cycle hooks
56 changes: 30 additions & 26 deletions packages/graphql-codegen-cli/src/hooks.ts
Expand Up @@ -4,7 +4,7 @@ import { exec } from 'child_process';
import { delimiter, sep } from 'path';
import { quote } from 'shell-quote';

const DEFAULT_HOOKS: Types.LifecycleHooksDefinition<string[]> = {
const DEFAULT_HOOKS: Types.LifecycleHooksDefinition = {
afterStart: [],
beforeDone: [],
onWatchTriggered: [],
Expand All @@ -15,35 +15,38 @@ const DEFAULT_HOOKS: Types.LifecycleHooksDefinition<string[]> = {
beforeAllFileWrite: [],
};

function normalizeHooks(
_hooks: Partial<Types.LifecycleHooksDefinition>
): Types.LifecycleHooksDefinition<(string | Types.HookFunction)[]> {
function normalizeHooks(_hooks: Partial<Types.LifecycleHooksDefinition>): {
[key in keyof Types.LifecycleHooksDefinition]: (string | Types.HookFunction)[];
} {
const keys = Object.keys({
...DEFAULT_HOOKS,
..._hooks,
});

return keys.reduce((prev: Types.LifecycleHooksDefinition<(string | Types.HookFunction)[]>, hookName: string) => {
if (typeof _hooks[hookName] === 'string') {
return {
...prev,
[hookName]: [_hooks[hookName]] as string[],
};
}
if (typeof _hooks[hookName] === 'function') {
return {
...prev,
[hookName]: [_hooks[hookName]],
};
}
if (Array.isArray(_hooks[hookName])) {
return {
...prev,
[hookName]: _hooks[hookName] as string[],
};
}
return prev;
}, {} as Types.LifecycleHooksDefinition<(string | Types.HookFunction)[]>);
return keys.reduce(
(prev: { [key in keyof Types.LifecycleHooksDefinition]: (string | Types.HookFunction)[] }, hookName: string) => {
if (typeof _hooks[hookName] === 'string') {
return {
...prev,
[hookName]: [_hooks[hookName]] as string[],
};
}
if (typeof _hooks[hookName] === 'function') {
return {
...prev,
[hookName]: [_hooks[hookName]],
};
}
if (Array.isArray(_hooks[hookName])) {
return {
...prev,
[hookName]: _hooks[hookName] as string[],
};
}
return prev;
},
{} as { [key in keyof Types.LifecycleHooksDefinition]: (string | Types.HookFunction)[] }
);
}

function execShellCommand(cmd: string): Promise<string> {
Expand Down Expand Up @@ -72,10 +75,11 @@ function execShellCommand(cmd: string): Promise<string> {

async function executeHooks(
hookName: string,
scripts: (string | Types.HookFunction)[] = [],
_scripts: Types.LifeCycleHookValue = [],
args: string[] = []
): Promise<void> {
debugLog(`Running lifecycle hook "${hookName}" scripts...`);
const scripts = Array.isArray(_scripts) ? _scripts : [_scripts];

const quotedArgs = quote(args);
for (const script of scripts) {
Expand Down
20 changes: 11 additions & 9 deletions packages/utils/plugins-helpers/src/types.ts
Expand Up @@ -524,58 +524,60 @@ export namespace Types {
export type PluginOutput = string | ComplexPluginOutput;
export type HookFunction = (...args: any[]) => void | Promise<void>;

export type LifeCycleHookValue = string | HookFunction | (string | HookFunction)[];

/**
* @description All available lifecycle hooks
* @additionalProperties false
*/
export type LifecycleHooksDefinition<T = string | HookFunction | (string | HookFunction)[]> = {
export type LifecycleHooksDefinition = {
/**
* @description Triggered with no arguments when the codegen starts (after the `codegen.yml` has beed parsed).
*
* Specify a shell command to run.
*/
afterStart: T;
afterStart: LifeCycleHookValue;
/**
* @description Triggered with no arguments, right before the codegen closes, or when watch mode is stopped.
*
* Specify a shell command to run.
*/
beforeDone: T;
beforeDone: LifeCycleHookValue;
/**
* @description Triggered every time a file changes when using watch mode.
* Triggered with two arguments: the type of the event (for example, `changed`) and the path of the file.
*/
onWatchTriggered: T;
onWatchTriggered: LifeCycleHookValue;
/**
* @description Triggered in case of a general error in the codegen. The argument is a string containing the error.
*/
onError: T;
onError: LifeCycleHookValue;
/**
* @description Triggered after a file is written to the file-system. Executed with the path for the file.
* If the content of the file hasn't changed since last execution - this hooks won't be triggered.
*
* > This is a very useful hook, you can use it for integration with Prettier or other linters.
*/
afterOneFileWrite: T;
afterOneFileWrite: LifeCycleHookValue;
/**
* @description Executed after writing all the files to the file-system.
* Triggered with multiple arguments - paths for all files.
*/
afterAllFileWrite: T;
afterAllFileWrite: LifeCycleHookValue;
/**
* @description Triggered before a file is written to the file-system. Executed with the path for the file.
*
* If the content of the file hasn't changed since last execution - this hooks won't be triggered.
*/
beforeOneFileWrite: T;
beforeOneFileWrite: LifeCycleHookValue;
/**
* @description Executed after the codegen has done creating the output and before writing the files to the file-system.
*
* Triggered with multiple arguments - paths for all relevant files.
*
* > Not all the files will be actually written to the file-system, because this is triggered before checking if the file has changed since last execution.
*/
beforeAllFileWrite: T;
beforeAllFileWrite: LifeCycleHookValue;
};

export type SkipDocumentsValidationOptions =
Expand Down

0 comments on commit c802a0c

Please sign in to comment.