Skip to content

Commit 9d9b24c

Browse files
authored
fix(types): remove ambient shims that override external package types (SD-2445) (#2682)
* fix(types): remove ambient shims that override external package types (IT-852) The published `_internal-shims.d.ts` contained `declare module` blocks for prosemirror-*, vue, eventemitter3, yjs, and @hocuspocus/provider that typed all exports as `any`. These ambient declarations globally override real types, breaking consumers who use those packages (e.g. Tiptap users lost all prosemirror type safety). - Remove all external package shims from `ensure-types.cjs` - Keep only `@superdoc/*` workspace package shims (consumers can't install those) - Add prosemirror-* as optional peerDependencies (public API re-exports their types) - Add IT-852 regression test: consumer-typecheck scenario that installs prosemirror alongside superdoc and verifies types are real (not `any`) via `@ts-expect-error` * chore: update pnpm lockfile for new prosemirror peer deps * fix(types): keep @hocuspocus/provider, yjs, y-prosemirror as required peers
1 parent 650fc10 commit 9d9b24c

7 files changed

Lines changed: 1800 additions & 100 deletions

File tree

packages/superdoc/package.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,30 @@
9292
"peerDependencies": {
9393
"@hocuspocus/provider": "^2.13.6",
9494
"pdfjs-dist": "^5.4.296",
95+
"prosemirror-model": "^1.25.0",
96+
"prosemirror-state": "^1.4.0",
97+
"prosemirror-transform": "^1.9.0",
98+
"prosemirror-view": "^1.33.0",
9599
"y-prosemirror": "catalog:",
96100
"yjs": "catalog:"
97101
},
102+
"peerDependenciesMeta": {
103+
"pdfjs-dist": {
104+
"optional": true
105+
},
106+
"prosemirror-model": {
107+
"optional": true
108+
},
109+
"prosemirror-state": {
110+
"optional": true
111+
},
112+
"prosemirror-transform": {
113+
"optional": true
114+
},
115+
"prosemirror-view": {
116+
"optional": true
117+
}
118+
},
98119
"devDependencies": {
99120
"@hocuspocus/provider": "catalog:",
100121
"@hocuspocus/server": "catalog:",

packages/superdoc/scripts/ensure-types.cjs

Lines changed: 13 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,11 @@ if (fs.readFileSync(superEditorFacadePath, 'utf8') !== expectedSuperEditorFacade
190190
//
191191
// Internal .d.ts files reference @superdoc/* workspace packages that consumers
192192
// can't install. Generate a shim so TypeScript can resolve these imports.
193-
// Also shim prosemirror peer deps that are bundled (not in consumer node_modules).
194193
// ---------------------------------------------------------------------------
195194

196195
// Collect @superdoc/* workspace module specifiers and their named imports from
197196
// all .d.ts files. These are private packages consumers can't install — we
198-
// generate ambient `declare module` shims for them. External packages
199-
// (prosemirror, vue, yjs, etc.) are handled by the hand-written shims below.
197+
// generate ambient `declare module` shims for them.
200198
const workspaceImports = new Map(); // module → Set<name>
201199

202200
for (const filePath of dtsFiles) {
@@ -244,110 +242,25 @@ for (const filePath of dtsFiles) {
244242
// ---------------------------------------------------------------------------
245243
// Write _internal-shims.d.ts
246244
//
247-
// Two sections:
248-
// 1. Hand-written shims for external packages (prosemirror-*, vue, yjs,
249-
// eventemitter3, @hocuspocus/provider). See KNOWN LIMITATION note in the
250-
// generated file about ambient shims overriding real package types.
251-
// 2. Auto-generated shims for @superdoc/* workspace packages.
245+
// Only contains auto-generated shims for @superdoc/* workspace packages.
246+
// External packages (prosemirror-*, vue, eventemitter3, yjs, etc.) are NOT
247+
// shimmed — ambient `declare module` overrides real types globally, breaking
248+
// consumers who depend on those packages (IT-852).
252249
// ---------------------------------------------------------------------------
253250

254251
const shimLines = [
255-
'// Auto-generated ambient declarations for internal/bundled packages.',
256-
'// These packages are bundled into superdoc or are internal workspace packages.',
257-
'// Consumers do not need to install them. This file prevents TypeScript errors',
258-
'// when skipLibCheck is false.',
252+
'// Auto-generated ambient declarations for internal workspace packages.',
253+
'// These are private @superdoc/* packages that consumers cannot install.',
254+
'// This file prevents TypeScript errors when skipLibCheck is false.',
259255
'//',
260-
'// KNOWN LIMITATION: ambient `declare module` with `export type X = any`',
261-
'// overrides real package types when both are present. This affects:',
262-
'// - vue, eventemitter3: direct deps of superdoc — ALWAYS in consumer',
263-
'// node_modules, so real types are always replaced by `any`.',
264-
'// - yjs, @hocuspocus/provider: peer deps — affected when installed.',
265-
'// - prosemirror-*: bundled (not in consumer node_modules) — no conflict.',
266-
'// The proper fix is adding prosemirror-* as peerDependencies and removing',
267-
'// shims for packages consumers already have installed.',
256+
'// External packages (prosemirror-*, vue, eventemitter3, yjs, etc.) are NOT',
257+
'// shimmed here — their real types come from node_modules. Ambient shims for',
258+
'// external packages would override real types globally, breaking consumers',
259+
'// who depend on those packages (e.g. Tiptap users need real prosemirror types).',
268260
'//',
269261
'// NOTE: This is a script file (no exports), so `declare module` creates',
270262
'// global ambient declarations and top-level declarations are global.',
271263
'',
272-
'// --- Well-known external packages (hand-written for correctness) ---',
273-
'',
274-
"declare module 'prosemirror-model' {",
275-
' export type DOMOutputSpec = any;',
276-
' export type Fragment = any;',
277-
' export type Mark = any;',
278-
' export type MarkType = any;',
279-
' export type Node = any;',
280-
' export type NodeType = any;',
281-
' export type ParseRule = any;',
282-
' export type ResolvedPos = any;',
283-
' export type Schema<N extends string = any, M extends string = any> = any;',
284-
' export type Slice = any;',
285-
'}',
286-
'',
287-
"declare module 'prosemirror-state' {",
288-
' export type EditorState = any;',
289-
' export type Plugin<T = any> = any;',
290-
' export type PluginKey<T = any> = any;',
291-
' export type TextSelection = any;',
292-
' export type Transaction = any;',
293-
'}',
294-
'',
295-
"declare module 'prosemirror-transform' {",
296-
' export type Mapping = any;',
297-
' export type ReplaceAroundStep = any;',
298-
' export type ReplaceStep = any;',
299-
' export type Step = any;',
300-
'}',
301-
'',
302-
"declare module 'prosemirror-view' {",
303-
' export type Decoration = any;',
304-
' export type DecorationSet = any;',
305-
' export type DecorationSource = any;',
306-
' export type EditorProps = any;',
307-
' export type EditorView = any;',
308-
' export type NodeView = any;',
309-
'}',
310-
'',
311-
"declare module 'eventemitter3' {",
312-
' export class EventEmitter<EventTypes extends string | symbol = string | symbol, Context = any> {',
313-
' on(event: EventTypes, fn: (...args: any[]) => void, context?: Context): this;',
314-
' off(event: EventTypes, fn: (...args: any[]) => void, context?: Context): this;',
315-
' emit(event: EventTypes, ...args: any[]): boolean;',
316-
' removeAllListeners(event?: EventTypes): this;',
317-
' }',
318-
' export default EventEmitter;',
319-
'}',
320-
'',
321-
"declare module 'vue' {",
322-
' export type App<T = any> = any;',
323-
' export type ComponentOptionsBase<P = any, B = any, D = any, C = any, M = any, Mixin = any, Extends = any, E = any, EE = any, Defaults = any, I = any, II = any, S = any, LC = any, Directives = any, Exposed = any, Provide = any> = any;',
324-
' export type ComponentOptionsMixin = any;',
325-
' export type ComponentProvideOptions = any;',
326-
' export type ComponentPublicInstance<P = any, B = any, D = any, C = any, M = any, E = any, S = any, Options = any, Defaults = any, MakeDefaultsOptional = any, I = any, PublicMixin = any, A = any, B2 = any, C2 = any> = any;',
327-
' export type ComputedRef<T = any> = any;',
328-
' export type CreateComponentPublicInstanceWithMixins<T = any, S = any, U = any, V = any, W = any, X = any, Y = any, Z = any, A = any, B = any, C = any, D = any> = any;',
329-
' export type DefineComponent<P = any, B = any, D = any, C = any, M = any, Mixin = any, Extends = any, E = any, EE = any, PP = any, Props = any, Defaults = any, S = any> = any;',
330-
' export type ExtractPropTypes<T = any> = any;',
331-
' export type GlobalComponents = any;',
332-
' export type GlobalDirectives = any;',
333-
' export type PublicProps = any;',
334-
' export type Ref<T = any> = any;',
335-
' export type RendererElement = any;',
336-
' export type RendererNode = any;',
337-
' export type ShallowRef<T = any> = any;',
338-
' export type VNode = any;',
339-
'}',
340-
'',
341-
"declare module 'yjs' {",
342-
' export type Doc = any;',
343-
' export type XmlFragment = any;',
344-
' export type RelativePosition = any;',
345-
'}',
346-
'',
347-
"declare module '@hocuspocus/provider' {",
348-
' export type HocuspocusProvider = any;',
349-
'}',
350-
'',
351264
];
352265

353266
// --- Auto-generated @superdoc/* workspace package shims ---
@@ -383,5 +296,5 @@ for (const entry of requiredEntryPoints) {
383296
}
384297
}
385298

386-
console.log(`[ensure-types] ✓ Generated ambient shims for ${wsCount} workspace + 8 external modules`);
299+
console.log(`[ensure-types] ✓ Generated ambient shims for ${wsCount} workspace modules`);
387300
console.log('[ensure-types] ✓ Verified type entry points');

pnpm-lock.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)