Skip to content

API ​

generated-signature is ESM only. From CommonJS, load it with a dynamic import: const { verify } = await import('generated-signature');. The ESLint plugin is the separate generated-signature/eslint entry point.

sign(text, options?) ​

Fills in the signature token's hash, inserting a signature line first if the text has no token.

OptionTypeDefaultDescription
filePathstring—Comment syntax for the inserted line, looked up from the file name with commentStyle.
commentCommentStyle—Comment syntax, given directly. Pass this or filePath.
messagestring'Generated file. Do not edit outside of manual sections.'Text after the token on the inserted line.

options is only needed when text has no token yet.

Returns string: the signed text. Signing is idempotent, and keeps \r\n line breaks.

Throws GeneratedSignatureMalformedError for a duplicate or unsupported token, or malformed sections. GeneratedSignatureCommentStyleError when a line must be inserted and filePath has no known comment syntax. TypeError when a line must be inserted and there are no options.

signatureToken() ​

Returns string: a token with a placeholder hash. A generator with its own header puts it there, and sign() fills in the hash instead of inserting a line:

ts
import { 
sign
,
signatureToken
} from 'generated-signature';
sign
(`// Generated by my-tool. ${
signatureToken
()}\nexport const a = 1;\n`);

verify(text) ​

Checks the file's signature. Never throws.

Returns VerifyResult, discriminated on status:

statusMeaning
'valid'Signed, and unchanged outside manual sections.
'invalid'Signed, but changed outside manual sections.
'unsigned'No signature token.
'malformed'error is a GeneratedSignatureMalformedError explaining what can't be read.
ts
const 
result
=
verify
(
text
);
if (
result
.
status
=== 'malformed') {
console
.
error
(`line ${
result
.
error
.
line
}: ${
result
.
error
.
reason
}`);
GeneratedSignatureMalformedError.reason: MalformedReason
}

manualSection(options) ​

Renders a manual section for a generator to embed.

OptionTypeDefaultDescription
idstring—Required. Section id: letters, digits, _, . and -.
bodystring''Content until someone edits it. A trailing line break is ignored.
indentstring''Prefixed to both markers and every non-blank body line.
filePath / commentstring / CommentStyle—Required. Comment syntax, as for sign.

Returns string: the start marker, body and end marker lines, without a trailing line break.

Throws GeneratedSignatureSectionIdError for an invalid id. GeneratedSignatureCommentStyleError for a filePath with no known comment syntax.

mergeSections(params) ​

Carries the manual sections of an existing file into freshly generated text, matched by id.

ParamTypeDescription
generatedstringRequired. New generator output, with default section bodies.
existingstringRequired. The file as it is now.

Returns MergeResult, { text: string, orphans: readonly string[] }. text is generated, with each section's body taken from existing when it has a section with the same id. orphans lists the ids of sections only existing has, and whose body isn't blank: dropping them would lose someone's edits, so callers should usually fail on them.

Throws GeneratedSignatureMalformedError if either text's sections are malformed.

parseSections(text) ​

Returns ReadonlyMap<string, ManualSection> by id, in file order. A ManualSection is { id, body, startLine, endLine }: body is everything between the marker lines, including its final line break, and lines are 1-indexed.

Throws GeneratedSignatureMalformedError if markers are unbalanced, nested or duplicated, or have an invalid id.

commentStyle(filePath) ​

Returns the line comment syntax for a file, as a CommentStyle ({ start: string, end?: string }), or null if it is unknown or the format has no comments, like .json.

CommentStyleFiles
//.c, .cc, .cjs, .cpp, .cs, .cts, .go, .h, .hpp, .java, .js, .json5, .jsonc, .jsx, .kt, .less, .mjs, .mts, .rs, .scss, .swift, .ts, .tsx
#.bash, .cfg, .conf, .env, .ini, .pl, .properties, .py, .r, .rb, .sh, .toml, .yaml, .yml, .zsh, and .gitattributes, .gitignore, .npmignore, Dockerfile, Makefile
/* */.css
<!-- -->.htm, .html, .md, .mdx, .svg, .vue, .xml
--.hs, .lua, .sql

For any other file, pass comment instead of filePath.

Manifest ​

Helpers for the manifest format.

FunctionDescription
contentHash(content: string | Uint8Array): stringv1: and 32 hex characters of SHA-256. \r\n counts as \n, also in bytes. Manual sections are not left out.
verifyManifestEntry(content, entry): VerifyResult'valid' or 'invalid' for a hash entry, and verify()'s result for an inline entry. content is a string or Uint8Array.
parseManifest(text): ManifestParses and validates a manifest. Throws GeneratedSignatureManifestError if it isn't one.
serializeManifest(files): stringManifest text for a Record<string, ManifestEntry>, with paths and inputs sorted so the output doesn't depend on write order.
ts
import { 
readFile
} from 'node:fs/promises';
import {
parseManifest
,
verifyManifestEntry
} from 'generated-signature';
const {
files
} =
parseManifest
(await
readFile
('out/.generated.json', 'utf8'));
for (const [
path
,
entry
] of
Object
.
entries
(
files
)) {
if (
verifyManifestEntry
(await
readFile
(`out/${
path
}`),
entry
).
status
!== 'valid') {
console
.
error
(`${
path
} was edited`);
} }

Errors ​

Every error extends the abstract GeneratedSignatureError.

ErrorPropertiesThrown when
GeneratedSignatureMalformedErrorreason: MalformedReason, line: numberA token or manual section can't be read. reason is one of 'duplicate-section', 'duplicate-signature', 'invalid-section-id', 'nested-section', 'unclosed-section', 'unopened-section', 'unsupported-version', and line is 1-indexed.
GeneratedSignatureCommentStyleErrorfilePath: stringNo comment syntax is known for a file.
GeneratedSignatureSectionIdErrorid: stringmanualSection() gets an invalid id.
GeneratedSignatureManifestErrorparseManifest() gets text that isn't a valid manifest.