Skip to content

Commit 5a026fd

Browse files
authored
refactor(superdoc): narrow Editor|PresentationEditor (SD-2867 phase B) (#3062)
* refactor(superdoc): type createSuperdocVueApp return shape (SD-2867 phase B) `createSuperdocVueApp()` returned `Object` per its JSDoc, so the five fields SuperDoc.js destructures from the call (`app`, `pinia`, `superdocStore`, `commentsStore`, `highContrastModeStore`) all resolved to `Object` for any consumer enabling `// @ts-check`. Five TS2339 'Property does not exist on type Object' errors at SuperDoc.js line 464 — and inside the SD-2867 ratchet that turns each into a gate failure. Promotes the return type to a named `SuperdocVueAppRefs` typedef that imports `vue.App`, `pinia.Pinia`, and the store types via `ReturnType<typeof useSuperdocStore>` etc. The shape is internal-only (this typedef is not on the public Modules / Config surface), so adding it here doesn't widen the customer-visible surface. Verified: pnpm --filter superdoc run check:jsdoc passes (3 gated files clean); the consumer-typecheck matrix passes 31/31; the postbuild declaration audit reports no FAIL findings; pnpm --filter superdoc test passes 944/944. This is groundwork for SD-2867 phase B: closing each cluster of SuperDoc.js TS errors so the file can eventually enroll in `CHECKED_FILES`. Five errors closed; ~133 remain across implicit-any params, strict-null guards, and other type-not-assignable callsites. Each cluster will land as its own focused commit. * refactor(superdoc): add RuntimeDocument typedef for runtime doc shape (SD-2867 phase B) The internal `doc` parameter in SuperDoc.js's private methods (#applyDocumentMode, #attachExternalCollaboration, etc.) is shaped differently from the public `Document` interface: SuperDoc attaches a runtime `role`, `getEditor()`, and `getPresentationEditor()` to each entry during init. Today those methods are typed `@param {Object} doc`, so any attempt to enable `// @ts-check` on SuperDoc.js fails with TS2339 errors at every `doc.getEditor()` / `doc.getPresentationEditor()` / `doc.role` access (~10 sites). Adds a `RuntimeDocument` typedef in core/types/index.ts that extends the public `Document` with the runtime-attached fields. Updates #applyDocumentMode's `@param {Object} doc` to `@param {RuntimeDocument} doc` as the first call site to migrate. The typedef is internal-only and not on the public superdoc surface (not in the public typedef block of packages/superdoc/src/index.js), so consumers cannot import or pass these fields from outside. This is groundwork: subsequent SD-2867 phase B PRs will migrate the remaining `@param {Object} doc` sites and then enable @ts-check on the methods involved. Verified: pnpm --filter superdoc run check:jsdoc passes (3 gated files clean); consumer matrix passes 31/31; declaration audit reports no FAIL findings; published .d.ts surface unchanged (RuntimeDocument is not re-exported from the public superdoc entry). * refactor(superdoc): type #initCollaboration param as Modules (SD-2867 phase B) #initCollaboration's @param was typed `Object`, so any consumer that enables `// @ts-check` on SuperDoc.js fails at every destructure of the function's parameter (`{ collaboration, comments }`) and at every read of `collaborationModuleConfig.{ydoc,provider}` and `commentsConfig.*`. Two TS2339s on line 519, plus all the downstream property accesses up to line 605. The actual call site at line 295 passes `this.config.modules`, so the right shape is `Modules` (already publicly exported). Tightens the @param to `Modules` and the @returns to `Promise<Document[] | undefined>` (which is what the function actually returns; the value is informational, not consumed by the caller). Verified locally: with `// @ts-check` enabled on SuperDoc.js, `#initCollaboration`'s body (lines 519-605) is fully type-clean. The remaining error at line 606 is a downstream callsite (passing `User | undefined` to a function expecting `Object`) and belongs to the next phase B cluster, not this one. This is groundwork; SuperDoc.js does not enroll under the gate yet. Verified: pnpm --filter superdoc run check:jsdoc passes (3 gated files clean); consumer matrix passes 31/31; declaration audit reports no FAIL findings; published .d.ts surface unchanged. * refactor(superdoc): tighten @param {Object} on three callback methods (SD-2867 phase B) Three private/public callback methods on SuperDoc had `@param {Object}` JSDoc that masked their actual contract: - addSharedUser(user) — typed as Object; actually expects User (the function reads u.email, which is a User field). - onContentError({ error, editor }) — typed as Object; actually expects an Error/Editor pair forwarded to config.onContentError. - canPerformPermission({ permission, role, isInternal, comment, trackedChange }) — typed as Object; the params are read at the body and forwarded into the permissions resolver chain. Promoted to a structural typedef with permission/role/isInternal/comment/ trackedChange optional (the function defaults `= {}` and treats missing permission as a no-op via the early `if (!permission) return false` guard). Skipped goToSearchResult: the upstream `commands.goToSearchResult` expects a private `SearchMatch` shape (id/from/to/text) that is not on the public surface yet. Tightening that requires either exporting SearchMatch publicly or asserting at the call site; deferring to a separate follow-up. Left a comment on the JSDoc documenting the deferral. This is groundwork for SD-2867 phase B's gate enrollment of SuperDoc.js. Each subsequent PR closes one cluster. Verified: pnpm --filter superdoc run check:jsdoc passes (3 gated files clean); consumer matrix passes 31/31; declaration audit reports no FAIL findings; published .d.ts surface unchanged. * refactor(superdoc): narrow Editor|PresentationEditor (SD-2867 phase B) Line 816's `editorInstance.editor ?? editorInstance` extracts the inner Editor from a PresentationEditor wrapper. PresentationEditor declares `editor: Editor` (PresentationEditor.ts:329); plain Editor does not, so the runtime fallback applies. Under @ts-check the access fails because the union arm Editor does not declare it. Resolved with a JSDoc cast that names the structural lookup without claiming the field exists on Editor. Verified: pnpm --filter superdoc run check:jsdoc passes (3 gated files clean); consumer matrix passes 33/33; declaration audit reports no FAIL findings; published .d.ts surface unchanged.
1 parent 0d1d8b8 commit 5a026fd

1 file changed

Lines changed: 7 additions & 1 deletion

File tree

packages/superdoc/src/core/SuperDoc.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,13 @@ export class SuperDoc extends EventEmitter {
813813
const TIMEOUT_MS = 10_000;
814814

815815
// PresentationEditor wraps Editor; get the underlying editor for event listening.
816-
const editor = editorInstance.editor ?? editorInstance;
816+
// PresentationEditor exposes a `get editor(): Editor` accessor; plain
817+
// Editor has no such property, so the runtime `??` fallback returns
818+
// the instance itself in that case. The cast names the structural
819+
// `.editor` lookup without claiming the field exists on the Editor
820+
// arm of the union, so the access type-checks once SuperDoc.js is
821+
// brought under the SD-2863 checkJs gate.
822+
const editor = /** @type {Editor} */ (/** @type {{ editor?: Editor }} */ (editorInstance).editor ?? editorInstance);
817823

818824
// If collaborationReady already fired (options flag set by collaboration extension)
819825
if (editor.options?.collaborationIsReady) {

0 commit comments

Comments
 (0)