Skip to content

fix(types): split converter/extensionService surfaces, type getActiveFormatting (SD-3240, SD-3245)#3434

Merged
caio-pizzol merged 3 commits into
mainfrom
caio-pizzol/SD-3240-finish-public-type-allowlist
May 21, 2026
Merged

fix(types): split converter/extensionService surfaces, type getActiveFormatting (SD-3240, SD-3245)#3434
caio-pizzol merged 3 commits into
mainfrom
caio-pizzol/SD-3240-finish-public-type-allowlist

Conversation

@caio-pizzol
Copy link
Copy Markdown
Contributor

Splits Editor.converter and Editor.extensionService into public no-any surface interfaces and types getActiveFormatting. The runtime instances stay SuperConverter / ExtensionService; the surface lives on the field types and a single as-unknown-as cast handles the assignment boundary. Toolbar helpers narrow the new getActiveFormatting discriminated union with a type guard instead of reaching through .attrs?.X.

  • Drains the final 18 supported-root allowlist entries to 0 (16 SD-3240, 2 SD-3245)
  • editor-surfaces-not-any.ts fixture pins editor.converter, editor.extensionService, getActiveFormatting param/return, plus exact-type checks on getDocumentCreatedTimestamp (string | null), getDocumentIdentifier (Promise), and converter.exportToDocx (string | Record<string, unknown>)
  • SD-3213 supported-root strict gate: PASS (0 entries)

Surfaced during review: Editor.exportDocx({ exportJsonOnly: true }) is publicly typed as Promise but actually returns a JSON tree at runtime. That is a separate public Editor API correction; tracked as SD-3248.

Verified: type-check → clean; pnpm test:editor → 13119 pass; deep-type-audit --pack --strict-supported-root → PASS; typecheck-matrix → 75/75

…Formatting (SD-3240, SD-3245)

Add `EditorConverterSurface` and `EditorExtensionServiceSurface` as the
public no-`any` field types for `Editor.converter` and
`Editor.extensionService`. The runtime instances are still
SuperConverter / ExtensionService - a single `as unknown as <Surface>`
cast lives at the assignment boundary in Editor.ts. Internal callers
that need deeper member access narrow with a local structural type at
the call site, not via `any`.

`getActiveFormatting` gains a real signature: the editor parameter is a
narrow structural `{ state, storage.formatCommands.storedStyle }` shape;
the return is a discriminated union `{ name: 'copyFormat'; attrs: true }
| { name: string; attrs: Record<string, unknown> }`. The toolbar helpers
in `headless-toolbar/helpers/formatting.ts` narrow the union with a type
guard instead of reaching through `.attrs?.X` on a possibly-boolean
attrs (no casts).

Drains the final 18 supported-root allowlist entries (16 for SD-3240
converter/extensionService leaks across Editor / Extensions / SuperDoc
resolver call sites, 2 for SD-3245 getActiveFormatting param + return)
to 0. New `editor-surfaces-not-any.ts` fixture locks the contract with
`Equal<T, any>` checks so a regression breaks the typecheck matrix, not
just the allowlist JSON.

SD-3213 supported-root strict gate: PASS (0 entries).
…D-3240)

Review caught three runtime/surface mismatches on EditorConverterSurface:

- `getDocumentCreatedTimestamp()` returns ISO string `'2024-01-15T10:30:00Z'`
  or null (per `dcterms:created`), not `number | null`. The misclassification
  drove a misleading `String(timestamp)` coercion in `#trackDocumentOpen`;
  removed.
- `getDocumentIdentifier()` is async and returns `Promise<string>` (the null
  fallback lives on `Editor.getDocumentIdentifier()` for the converter-
  missing case), not synchronous `string | null`.
- `exportToDocx()` returns `Promise<string | Record<string, unknown>>` (XML
  string or intermediate JSON tree); Blob/Buffer wrapping happens upstream
  in `Editor.exportDocx()`. Added a one-line cast at the bridge site for
  the JSON branch to bridge to the (pre-existing, broader) implementation
  return type.

Fixture coverage extended with exact-type assertions on each of the three
methods so a future regression breaks the typecheck matrix, not the
allowlist JSON.

Also normalized em-dashes added in the prior commit to commas/colons/
periods per the writing-style rule (no em-dashes anywhere).
…240)

Adds the missing exact-type assertion on `editor.converter.exportToDocx()`
return (`Promise<string | Record<string, unknown>>`) alongside the
existing assertions for `getDocumentCreatedTimestamp`,
`getDocumentIdentifier`, and the converter / extensionService field
types. Locks the honest converter shape so a future drift back to
`any` (or to the original Blob | Buffer fiction) breaks the typecheck
matrix.

Note: the related `Editor.exportDocx({ exportJsonOnly: true })` overload
still publicly returns `Promise<string>` despite the runtime returning
a JSON tree object. That is a public Editor API correction (different
surface, different defect class) and is tracked separately as SD-3248.
@caio-pizzol caio-pizzol requested a review from a team as a code owner May 21, 2026 23:28
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 21, 2026

SD-3240

SD-3245

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@caio-pizzol caio-pizzol merged commit 6b99f81 into main May 21, 2026
67 checks passed
@caio-pizzol caio-pizzol deleted the caio-pizzol/SD-3240-finish-public-type-allowlist branch May 21, 2026 23:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants