Getting started
Install
npm i generated-signaturepnpm add generated-signatureyarn add generated-signatureTIP
generated-signature requires Node.js 24 or later, and is ESM only. From CommonJS, load it with a dynamic import: const { verify } = await import('generated-signature');.
Using populate-files? It signs and merges for you with signed: true. You only need this package's manualSection(), and the ESLint rule.
Sign a file
sign() adds a signature line at the top, in the file's comment syntax:
import { sign } from 'generated-signature';
const text = sign("export const version = '1.2.3';\n", { filePath: 'version.ts' });// @generated-signature v1:… Generated file. Do not edit outside of manual sections.
export const version = '1.2.3';The hash covers everything else in the file. Pass message to change the text after the token, or comment instead of filePath to give the comment syntax yourself:
import { sign } from 'generated-signature';
sign('name = "x"\n', { comment: { start: '#' }, message: 'Generated by my-tool.' });Signing is idempotent, and keeps \r\n line breaks.
Add manual sections
A manual section is a region a person may edit. Render it with manualSection():
import { manualSection, sign } from 'generated-signature';
const filePath = 'client.ts';
const generated = `export class Client {
${manualSection({ id: 'methods', indent: ' ', filePath, body: '// Add your own methods here' })}
}
`;
const text = sign(generated, { filePath });// @generated-signature v1:… Generated file. Do not edit outside of manual sections.
export class Client {
// @manual-start methods
// Add your own methods here
// @manual-end methods
}The content between the markers is left out of the hash, so editing it keeps the signature valid. The marker lines are hashed, so adding, removing or renaming a section is an edit.
Regenerate
When writing over an existing file, verify it first, then carry its manual sections into the new output with mergeSections(), and sign the result:
if (verify(existing).status !== 'valid') {
throw new Error('Edited by hand, not overwriting it');
}
const { text, orphans } = mergeSections({ generated, existing });
if (orphans.length > 0) {
throw new Error(`Manual sections would be lost: ${orphans.join(', ')}`);
}
const signed = sign(text, { filePath: 'client.ts' });Sections are matched by id. orphans lists sections that only the existing file has, and that someone wrote something in.
Verify
const result = verify(text);status | Meaning |
|---|---|
'valid' | Signed, and unchanged outside manual sections. |
'invalid' | Signed, but changed outside manual sections. |
'unsigned' | No signature token. |
'malformed' | The token or markers can't be read. error says why, and on which line. |
verify() never throws, so it is safe to run over any file. To check files while editing them, use the ESLint rule.
Next steps
- ESLint: report hand-edited files in the editor and in lint.
- File format: the token, markers, hash and manifest.
- API reference: every function and error.