Skip to content

feat: tighten TypeScript type declarations — replace any with concrete types#669

Open
mttrbrts wants to merge 6 commits into
mainfrom
feat/tighten-typescript-types
Open

feat: tighten TypeScript type declarations — replace any with concrete types#669
mttrbrts wants to merge 6 commits into
mainfrom
feat/tighten-typescript-types

Conversation

@mttrbrts
Copy link
Copy Markdown
Member

@mttrbrts mttrbrts commented May 9, 2026

Summary

Closes #668

This PR tightens TypeScript declarations across the public API in two phases:

Phase 1 (previous commits): Replace any with object, object[], and Serializer on priority public API methods.

Phase 2 (this commit): Generate TypeScript interfaces directly from the CTO schema files and use them in all public API signatures — replacing the remaining object types with specific model types.

Phase 2 detail

A new codegen script (packages/markdown-common/scripts/generate-model-types.js) runs @accordproject/concerto-codegen's TypescriptVisitor over all four CTO models (CommonMark, CiceroMark, ConcertoMeta, TemplateMark) and writes .d.ts files to packages/markdown-common/types/model/. The build:types script now runs codegen before tsc.

All generated interfaces are published from @accordproject/markdown-common — other packages reference them via package-qualified paths so generated declarations resolve correctly from any consumer.

Before (Phase 1 result):

// CommonMarkTransformer.d.ts
fromMarkdown(markdown: string): object;
toMarkdown(input: object): string;

// CiceroMarkTransformer.d.ts
fromMarkdown(markdown: string): object;
fromCommonMark(input: object): object;
getClauseText(input: object): string;

After (Phase 2 result):

// CommonMarkTransformer.d.ts
fromMarkdown(markdown: string): IDocument;
fromTokens(tokenStream: object[]): IDocument;
toMarkdown(input: INode): string;
removeFormatting(input: IDocument): IDocument;

// CiceroMarkTransformer.d.ts
fromMarkdown(markdown: string): ICiceroDocument;
fromCommonMark(input: IDocument): ICiceroDocument;
toCommonMark(input: ICiceroDocument, options?: {...}): IDocument;
getClauseText(input: IClause): string;

Consumers can import model types directly:

import type { IDocument, INode } from '@accordproject/markdown-common/types/model/commonmark';
import type { IClause } from '@accordproject/markdown-common/types/model/ciceromark';
// or via the barrel:
import type { IDocument, IClause } from '@accordproject/markdown-common/types/model';

Changes by package

  • markdown-common: add @accordproject/concerto-codegen devDep; add scripts/generate-model-types.js; add build:model-types script; @typedef annotations in CommonMarkTransformer.js for IDocument/INode; new types/model/ directory with 5 generated interface files + barrel index.d.ts
  • markdown-cicero: @typedef annotations in CiceroMarkTransformer.js for IDocument, ICiceroDocument, IClause; all public methods use specific types
  • markdown-transform: regenerated types/index.d.ts and types/lib/builtinTransforms.d.ts — transformation graph methods now return IDocument instead of object

Test plan

  • npm run build:types passes cleanly in markdown-common, markdown-cicero, markdown-template
  • Local template-engine linked to these packages builds with zero TypeScript errors
  • types/model/ barrel export verified: import type { IDocument, IClause } from '@accordproject/markdown-common/types/model'
  • Run full test suite: npm test --workspaces

Signed-off-by: Matt Roberts matt@rbrts.uk
🤖 Generated with Claude Code

@coveralls
Copy link
Copy Markdown

coveralls commented May 9, 2026

Coverage Report for CI Build 25613024897

Coverage remained the same at 72.194%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 2613
Covered Lines: 1958
Line Coverage: 74.93%
Relevant Branches: 1156
Covered Branches: 763
Branch Coverage: 66.0%
Branches in Coverage %: Yes
Coverage Strength: 978.44 hits per line

💛 - Coveralls

@mttrbrts mttrbrts force-pushed the feat/tighten-typescript-types branch from da7fa0c to 81df28e Compare May 9, 2026 21:48
mttrbrts and others added 4 commits May 9, 2026 22:51
…ete types

Update JSDoc @param and @returns annotations on the priority public API
methods across four packages so that generated .d.ts files no longer
use `any` where a more specific type is known:

- CommonMarkTransformer: toMarkdown, removeFormatting (object input),
  toTokens (object[] return), fromTokens (object[] param, object return),
  getSerializer (Serializer return)
- CiceroMarkTransformer: getClauseText, fromCiceroEdit, fromCommonMark,
  toMarkdown, toCommonMark, toCiceroMarkUnwrapped (object I/O),
  toTokens/fromTokens (object[]/object), getSerializer (Serializer)
- HtmlTransformer: toHtml (object input), toCiceroMark (object return)
- TemplateMarkTransformer: getSerializer (object return)

Regenerated .d.ts files in each package with `tsc`.

Closes #668

Signed-off-by: Matt Roberts <matt@rbrts.uk>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Matt Roberts <code@rbrts.uk>
- ToMarkdownVisitor.toMarkdown: {*} input → {object}
- TransformEngine.transformToDestination/transform: source {*} → {object|string},
  returns {*}/{Promise} → {Promise<object|string>}
- TransformEngine.registerTransformation: transform {*} → {Function}
- TransformEngine.registerExtension: extension {*} → {object}
- transform.js module exports: add JSDoc to formatDescriptor, transform,
  generateTransformationDiagram, and builtinEngine so tsc can emit
  typed declarations rather than any

Regenerated .d.ts files in markdown-common and markdown-transform.

Signed-off-by: Matt Roberts <matt@rbrts.uk>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Matt Roberts <code@rbrts.uk>
…schemas

Add a codegen script that runs TypescriptVisitor over all four CTO models
(CommonMark, CiceroMark, ConcertoMeta, TemplateMark) and writes clean
.d.ts files to types/model/. The build:types script now runs codegen
before tsc so model types are always up to date.

Update JSDoc @typedef annotations in CommonMarkTransformer and
CiceroMarkTransformer to reference the generated interfaces (IDocument,
INode, IClause) via package-qualified paths, so tsc emits non-relative
imports that resolve correctly from any consumer package.

Result: all public API methods now carry specific model types in their
generated .d.ts signatures rather than plain object.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Matt Roberts <code@rbrts.uk>
…ger in codegen script

strict mode is the default in concerto-core v4.

Signed-off-by: Matt Roberts <code@rbrts.uk>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Matt Roberts <code@rbrts.uk>
@mttrbrts mttrbrts force-pushed the feat/tighten-typescript-types branch from 23736be to 54c752c Compare May 9, 2026 21:51
@mttrbrts mttrbrts requested review from a team, Copilot and dselman May 9, 2026 21:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens TypeScript declarations across the Accord Project Markdown Transform monorepo by introducing generated Concerto model .d.ts interfaces in @accordproject/markdown-common and updating public transformer/engine APIs to use more concrete types instead of any/object.

Changes:

  • Add a markdown-common codegen script to generate and publish Concerto model type declarations under types/model/*.
  • Update transformer and transform-engine JSDoc/types so emitted .d.ts signatures use more specific model types (e.g., IDocument, INode) and clearer input/return types.
  • Regenerate downstream package declaration files (markdown-cicero, markdown-template, markdown-html, markdown-transform) to reference the published model types.

Reviewed changes

Copilot reviewed 12 out of 28 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/markdown-transform/types/lib/transformEngine.d.ts Updates TransformEngine method signatures in emitted declarations.
packages/markdown-transform/types/lib/transform.d.ts Tightens top-level API declaration signatures for transform, formatDescriptor, etc.
packages/markdown-transform/types/lib/builtinTransforms.d.ts Regenerates builtin transform graph typings to return model types in some paths.
packages/markdown-transform/types/index.d.ts Updates package surface typings and builtin transformation graph typings.
packages/markdown-transform/src/transformEngine.js Updates JSDoc for TransformEngine inputs/outputs and registration APIs.
packages/markdown-transform/src/transform.js Adds/updates JSDoc for exported helpers to improve emitted types.
packages/markdown-transform/lib/transformEngine.js Built output mirroring src/transformEngine.js JSDoc updates.
packages/markdown-transform/lib/transform.js Built output mirroring src/transform.js JSDoc updates.
packages/markdown-template/types/lib/TemplateMarkTransformer.d.ts Tightens emitted declaration for TemplateMarkTransformer serializer accessor.
packages/markdown-template/src/TemplateMarkTransformer.js Updates JSDoc for TemplateMarkTransformer serializer accessor.
packages/markdown-template/lib/TemplateMarkTransformer.js Built output mirroring TemplateMarkTransformer JSDoc updates.
packages/markdown-html/types/lib/HtmlTransformer.d.ts Tightens HtmlTransformer declarations (toHtml, toCiceroMark).
packages/markdown-html/src/HtmlTransformer.js Updates JSDoc types for HtmlTransformer inputs/outputs.
packages/markdown-common/types/model/templatemark.d.ts New generated model declaration file for TemplateMark namespace.
packages/markdown-common/types/model/index.d.ts Barrel export for generated model type declarations.
packages/markdown-common/types/model/concerto-metamodel.d.ts New generated model declaration file for Concerto metamodel types.
packages/markdown-common/types/model/concerto-base.d.ts New generated model declaration file for Concerto base types.
packages/markdown-common/types/model/commonmark.d.ts New generated model declaration file for CommonMark DOM interfaces.
packages/markdown-common/types/model/ciceromark.d.ts New generated model declaration file for CiceroMark interfaces.
packages/markdown-common/types/lib/ToMarkdownVisitor.d.ts Tightens emitted declaration for ToMarkdownVisitor input type.
packages/markdown-common/types/lib/CommonMarkTransformer.d.ts Tightens CommonMarkTransformer public API to use model interfaces.
packages/markdown-common/scripts/generate-model-types.js Adds codegen script to generate types/model/*.d.ts from CTO models.
packages/markdown-common/package.json Adds build:model-types and runs it before tsc; adds concerto-codegen devDep.
packages/markdown-common/lib/ToMarkdownVisitor.js Built output reflecting updated JSDoc for ToMarkdownVisitor.
packages/markdown-common/lib/CommonMarkTransformer.js Adds typedef imports + tightens JSDoc return/param types.
packages/markdown-cicero/types/lib/CiceroMarkTransformer.d.ts Tightens CiceroMarkTransformer public API to use model interfaces.
packages/markdown-cicero/lib/CiceroMarkTransformer.js Adds typedef imports + tightens JSDoc types for CiceroMarkTransformer.
package-lock.json Locks newly added dev dependency (@accordproject/concerto-codegen) and transitive deps.
Comments suppressed due to low confidence (1)

packages/markdown-template/src/TemplateMarkTransformer.js:102

  • getSerializer() returns templateMarkManager.serializer, which is constructed as a Serializer from @accordproject/concerto-core (see templatemarkutil.js). Returning/documenting it as a plain object loses useful type information and is inconsistent with the other transformers’ getSerializer(): Serializer. Use Serializer as the return type in JSDoc so .d.ts generation stays accurate.
    /**
     * Get TemplateMark serializer
     * @return {object} templatemark serializer
     */
    getSerializer() {
        return templateMarkManager.serializer;
    }

* @param {object|string} source the input for the transformation
* @param {string} sourceFormat the input format
* @param {string[]} destinationFormat the destination format as an array
* @param {object} parameters the transform parameters
* @param {object|string} source the input for the transformation
* @param {string} sourceFormat the input format
* @param {string} destinationFormat the destination format
* @param {object} parameters the transform parameters
* @param {string} sourceFormat the input format
* @param {string[]} destinationFormat the destination format as an array,
* the transformation are applied in order to reach all formats in the array
* @param {object} parameters the transform parameters
Comment on lines +47 to +51
mm.accept(new CodeGen.TypescriptVisitor(), {
fileWriter: {
openFile: (f) => { files[f] = ''; },
writeLine: (i, l) => { files[Object.keys(files).at(-1)] += ' '.repeat(i) + l + '\n'; },
closeFile: () => {}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead upgrade the Node version to >=22

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — upgraded minimum Node version to >=22 across all package.json files and removed Node 20.x from the CI matrix in commit 8588544.

@mttrbrts
Copy link
Copy Markdown
Member Author

mttrbrts commented May 9, 2026

@copilot apply changes based on the comments in this thread. Also update the minimum node version to 22

- Mark `parameters` as `[parameters]` (optional) in JSDoc for
  `transform.js` and `transformEngine.js` (src/ and lib/) so generated
  `.d.ts` files emit `parameters?: object` instead of `parameters: object`
- Update minimum Node version from >=18/>=15 to >=22 in all package.json
  engines fields
- Remove Node 20.x from CI build matrix (minimum is now 22)
- Regenerate `types/` declarations to reflect optional parameters

Signed-off-by: Copilot <copilot@github.com>

Agent-Logs-Url: https://github.com/accordproject/markdown-transform/sessions/b58c7539-b316-4d97-b13c-bde57770d0b7

Co-authored-by: mttrbrts <7544022+mttrbrts@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI commented May 9, 2026

@copilot apply changes based on the comments in this thread. Also update the minimum node version to 22

Applied in commit 8588544:

  • parameters marked as optional ([parameters]) in JSDoc for transform.js and transformEngine.js (both src/ and lib/), so .d.ts files now emit parameters?: object
  • Minimum Node version updated to >=22 in all package.json files
  • Node 20.x removed from the CI build matrix

@Rishabh060105
Copy link
Copy Markdown
Contributor

Hi @mttrbrts, I went through the current #669 head pretty carefully. The earlier Copilot comments around optional parameters and the Node 22 CI matrix look addressed, but I still found three gaps worth fixing:

  • .github/workflows/publish.yml is still pinned to Node 20 even though this PR raises the package minimum to >=22, so the release path can still fail on an unsupported runtime
  • HtmlTransformer is still emitting very weak public types (object) for toHtml / toCiceroMark, which leaves that part of the #668 API surface only partially tightened
  • TemplateMarkTransformer.getSerializer() still emits object instead of Serializer, so there is one remaining avoidable weak public type there

I patched those on top of the current PR head in a follow-up branch so the diff stays narrow.

Signed-off-by: Rishabh Jain <rishabhj2005@gmail.com>
@mttrbrts
Copy link
Copy Markdown
Member Author

@Rishabh060105 thanks for that patch, it's looking really strong now. I'll wait for a review from another maintainer before merging.

@accordproject/maintainers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: tighten TypeScript type declarations — replace any with Concerto model types

5 participants