From c802a0c0b775cfabc5ace3e7fb6655540c6c4d84 Mon Sep 17 00:00:00 2001 From: Jan Nicklas Date: Tue, 6 Dec 2022 19:12:17 +0100 Subject: [PATCH] improve life cycle hooks typings (#8652) * simpler hook types * add changeset * Update .changeset/plenty-bottles-prove.md Co-authored-by: Saihajpreet Singh * only type changes Co-authored-by: Saihajpreet Singh --- .changeset/plenty-bottles-prove.md | 6 +++ packages/graphql-codegen-cli/src/hooks.ts | 56 +++++++++++---------- packages/utils/plugins-helpers/src/types.ts | 20 ++++---- 3 files changed, 47 insertions(+), 35 deletions(-) create mode 100644 .changeset/plenty-bottles-prove.md diff --git a/.changeset/plenty-bottles-prove.md b/.changeset/plenty-bottles-prove.md new file mode 100644 index 00000000000..d68850499de --- /dev/null +++ b/.changeset/plenty-bottles-prove.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/cli': patch +'@graphql-codegen/plugin-helpers': major +--- + +improve typings for life cycle hooks diff --git a/packages/graphql-codegen-cli/src/hooks.ts b/packages/graphql-codegen-cli/src/hooks.ts index ae303ba945e..e31ee965b5f 100644 --- a/packages/graphql-codegen-cli/src/hooks.ts +++ b/packages/graphql-codegen-cli/src/hooks.ts @@ -4,7 +4,7 @@ import { exec } from 'child_process'; import { delimiter, sep } from 'path'; import { quote } from 'shell-quote'; -const DEFAULT_HOOKS: Types.LifecycleHooksDefinition = { +const DEFAULT_HOOKS: Types.LifecycleHooksDefinition = { afterStart: [], beforeDone: [], onWatchTriggered: [], @@ -15,35 +15,38 @@ const DEFAULT_HOOKS: Types.LifecycleHooksDefinition = { beforeAllFileWrite: [], }; -function normalizeHooks( - _hooks: Partial -): Types.LifecycleHooksDefinition<(string | Types.HookFunction)[]> { +function normalizeHooks(_hooks: Partial): { + [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 { @@ -72,10 +75,11 @@ function execShellCommand(cmd: string): Promise { async function executeHooks( hookName: string, - scripts: (string | Types.HookFunction)[] = [], + _scripts: Types.LifeCycleHookValue = [], args: string[] = [] ): Promise { debugLog(`Running lifecycle hook "${hookName}" scripts...`); + const scripts = Array.isArray(_scripts) ? _scripts : [_scripts]; const quotedArgs = quote(args); for (const script of scripts) { diff --git a/packages/utils/plugins-helpers/src/types.ts b/packages/utils/plugins-helpers/src/types.ts index 8ec12e84a0a..74e90c61707 100644 --- a/packages/utils/plugins-helpers/src/types.ts +++ b/packages/utils/plugins-helpers/src/types.ts @@ -524,50 +524,52 @@ export namespace Types { export type PluginOutput = string | ComplexPluginOutput; export type HookFunction = (...args: any[]) => void | Promise; + export type LifeCycleHookValue = string | HookFunction | (string | HookFunction)[]; + /** * @description All available lifecycle hooks * @additionalProperties false */ - export type LifecycleHooksDefinition = { + 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. * @@ -575,7 +577,7 @@ export namespace Types { * * > 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 =