postRenderHooks
In Kanel, "rendering" means translating a bunch of declarations into arrays of strings that will ultimately become files. You can apply hooks before and after this step if you want to make some custom modifications or additions to the final output.
Post-render hooks run after files have been rendered to strings, just before they're written to disk. This is useful for making low-level string manipulations that would be difficult to express at the declaration level.
Signature
A post-render hook has the following signature:
export type PostRenderHook = (
path: string,
lines: string[],
) => Awaitable<string[]>;For every file that is about to be written, this function will be called. The lines parameter is the raw strings that will comprise the file. You should return the entire array of lines that you want the file to contain.
Built-in Hooks
Mark Files as Generated
The markAsGenerated hook adds a @generated comment to the top of each file:
import { makePgTsGenerator, markAsGenerated } from 'kanel';
const config = {
generators: [makePgTsGenerator()],
postRenderHooks: [markAsGenerated],
};This adds:
// @generated
// This file is automatically generated by Kanel. Do not modify manually.Format with Prettier
The formatWithPrettier hook automatically formats all TypeScript files using Prettier:
import { makePgTsGenerator, formatWithPrettier } from 'kanel';
const config = {
generators: [makePgTsGenerator()],
postRenderHooks: [formatWithPrettier],
};This hook:
- Only formats TypeScript files (
.tsand.tsx) - Automatically finds and respects your Prettier configuration (
.prettierrc, etc.) - Gracefully handles cases where Prettier is not installed
- Requires Prettier as an optional peer dependency
TIP
You can combine multiple hooks:
postRenderHooks: [markAsGenerated, formatWithPrettier]WARNING
Make sure Prettier is installed in your project:
npm install --save-dev prettierAccessing Context
To access the Kanel context (configuration, schemas, etc.) in a post-render hook, use useKanelContext():
import { useKanelContext } from 'kanel';
const myPostRenderHook = (path, lines) => {
const context = useKanelContext();
// Access context.config, context.schemas, context.typescriptConfig
return lines;
};See useKanelContext for complete documentation.
Example: Custom Header
const addCustomHeader = (path, lines) => {
return [
'// Custom header',
`// Generated from: ${path}`,
'// Do not edit manually',
'',
...lines,
];
};
const config = {
generators: [makePgTsGenerator()],
postRenderHooks: [addCustomHeader],
};Example: Add Prettier Disable Comments
const disablePrettier = (path, lines) => {
return [
'/* prettier-ignore-start */',
...lines,
'/* prettier-ignore-end */',
];
};V3 to V4 Migration
In V3, post-render hooks received InstantiatedConfig as the third parameter. In V4, hooks no longer receive config as a parameter — use useKanelContext() instead if you need access to configuration.
V3 pattern (deprecated):
module.exports = {
postRenderHooks: [
(path, lines, instantiatedConfig) => {
// Access instantiatedConfig.outputPath, etc.
return lines;
},
],
};V4 pattern:
import { useKanelContext } from 'kanel';
module.exports = {
generators: [makePgTsGenerator()],
postRenderHooks: [
(path, lines) => {
const context = useKanelContext();
// Access context.config.outputPath, etc.
return lines;
},
],
};When to Use Post-Render Hooks vs Pre-Render Hooks
Use pre-render hooks when you want to:
- Add/modify/remove TypeScript declarations
- Generate additional types or interfaces
- Work with the semantic structure of the code
Use post-render hooks when you want to:
- Add file headers or footers
- Make string-based transformations
- Add linter/formatter directives
- Perform simple line-based modifications
Pre-render hooks are generally more powerful and type-safe, but post-render hooks are simpler for basic string operations.