@@ -58,291 +58,4 @@ if (hadWorkspaceImport) {
5858 console . log ( '[ensure-types] ✓ Inlined @superdoc/common types' ) ;
5959}
6060
61- // ---------------------------------------------------------------------------
62- // Fix pnpm node_modules paths in ALL .d.ts files (SD-2227)
63- //
64- // vite-plugin-dts resolves bare specifiers like 'prosemirror-view' to physical
65- // pnpm paths like '../../node_modules/.pnpm/prosemirror-view@1.41.5/node_modules/prosemirror-view/dist/index.js'.
66- // Consumers don't have these paths — rewrite them back to bare specifiers.
67- // ---------------------------------------------------------------------------
68-
69- /**
70- * Recursively find all .d.ts files under a directory.
71- */
72- function findDtsFiles ( dir ) {
73- const results = [ ] ;
74- for ( const entry of fs . readdirSync ( dir , { withFileTypes : true } ) ) {
75- const fullPath = path . join ( dir , entry . name ) ;
76- if ( entry . isDirectory ( ) ) {
77- results . push ( ...findDtsFiles ( fullPath ) ) ;
78- } else if ( entry . name . endsWith ( '.d.ts' ) ) {
79- results . push ( fullPath ) ;
80- }
81- }
82- return results ;
83- }
84-
85- // Match pnpm node_modules paths in both `from '...'` and `import('...')` contexts.
86- // Captures the bare package name from the pnpm structure:
87- // .../node_modules/.pnpm/<pkg>@<ver>/node_modules/<pkg>/dist/index.js
88- // ^^^^^ capture this
89- const PNPM_PATH_RE = / ( [ ' " ] ) ( [ ^ ' " ] * \/ n o d e _ m o d u l e s \/ \. p n p m \/ [ ^ / ] + \/ n o d e _ m o d u l e s \/ ( @ [ ^ / ] + \/ [ ^ / ] + | [ ^ / ] + ) \/ d i s t \/ i n d e x \. j s ) \1/ g;
90-
91- // Match broken absolute-looking paths like 'packages/superdoc/src/types.js'
92- // that vite-plugin-dts sometimes emits from path alias resolution.
93- const BAD_ABSOLUTE_PATH_RE = / ( [ ' " ] ) p a c k a g e s \/ s u p e r d o c \/ s r c \/ ( [ ^ ' " ] + ) \1/ g;
94-
95- // vite-plugin-dts incorrectly resolves subpath exports (e.g. @superdoc/super-editor/types)
96- // by appending the subpath to the main entry: '../../super-editor/src/index.js/types'
97- // Fix: rewrite index.js/<subpath> → <subpath>.js
98- const BAD_SUBPATH_RE = / ( [ ' " ] ) ( [ ^ ' " ] * \/ i n d e x \. j s ) ( \/ [ ^ ' " ] + ) \1/ g;
99-
100- let fixedFiles = 0 ;
101- let totalReplacements = 0 ;
102-
103- const dtsFiles = findDtsFiles ( distRoot ) ;
104- for ( const filePath of dtsFiles ) {
105- let fileContent = fs . readFileSync ( filePath , 'utf8' ) ;
106- let changed = false ;
107-
108- // Fix pnpm node_modules paths → bare specifiers
109- fileContent = fileContent . replace ( PNPM_PATH_RE , ( match , quote , _fullPath , packageName ) => {
110- changed = true ;
111- totalReplacements ++ ;
112- return `${ quote } ${ packageName } ${ quote } ` ;
113- } ) ;
114-
115- // Fix broken absolute-looking paths → relative paths
116- const relDir = path . relative ( path . dirname ( filePath ) , path . join ( distRoot , 'superdoc/src' ) ) ;
117- fileContent = fileContent . replace ( BAD_ABSOLUTE_PATH_RE , ( match , quote , rest ) => {
118- changed = true ;
119- totalReplacements ++ ;
120- let relativePath = path . posix . join (
121- relDir . split ( path . sep ) . join ( '/' ) ,
122- rest ,
123- ) ;
124- // Ensure relative paths start with ./ (bare names are treated as package specifiers)
125- if ( ! relativePath . startsWith ( '.' ) && ! relativePath . startsWith ( '/' ) ) {
126- relativePath = './' + relativePath ;
127- }
128- return `${ quote } ${ relativePath } ${ quote } ` ;
129- } ) ;
130-
131- // Fix broken subpath exports (index.js/types → types.js)
132- fileContent = fileContent . replace ( BAD_SUBPATH_RE , ( match , quote , basePath , subpath ) => {
133- changed = true ;
134- totalReplacements ++ ;
135- // Replace 'foo/index.js/types' with 'foo/types.js'
136- const dir = basePath . replace ( / \/ i n d e x \. j s $ / , '' ) ;
137- return `${ quote } ${ dir } ${ subpath } .js${ quote } ` ;
138- } ) ;
139-
140-
141- if ( changed ) {
142- fs . writeFileSync ( filePath , fileContent ) ;
143- fixedFiles ++ ;
144- }
145- }
146-
147- if ( fixedFiles > 0 ) {
148- console . log ( `[ensure-types] ✓ Fixed ${ totalReplacements } import paths in ${ fixedFiles } .d.ts files` ) ;
149- }
150-
151- // ---------------------------------------------------------------------------
152- // Generate ambient module declarations for private workspace packages (SD-2227)
153- //
154- // Internal .d.ts files reference @superdoc /* workspace packages that consumers
155- // can't install. Generate a shim so TypeScript can resolve these imports.
156- // Also shim prosemirror peer deps that are bundled (not in consumer node_modules).
157- // ---------------------------------------------------------------------------
158-
159- // Collect @superdoc /* workspace module specifiers and their named imports from
160- // all .d.ts files. These are private packages consumers can't install — we
161- // generate ambient `declare module` shims for them. External packages
162- // (prosemirror, vue, yjs, etc.) are handled by the hand-written shims below.
163- const workspaceImports = new Map ( ) ; // module → Set<name>
164-
165- for ( const filePath of dtsFiles ) {
166- const fileContent = fs . readFileSync ( filePath , 'utf8' ) ;
167-
168- // Match: import { Foo, Bar } from '...' and import type { Foo } from '...'
169- const namedImports = fileContent . matchAll ( / i m p o r t \s + (?: t y p e \s + ) ? \{ ( [ ^ } ] + ) \} \s * f r o m \s * [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / g) ;
170- for ( const m of namedImports ) {
171- const mod = m [ 2 ] ;
172-
173- // Skip relative imports and already-handled packages
174- if ( mod . startsWith ( '.' ) || mod . startsWith ( '@superdoc/common' ) || mod . startsWith ( '@superdoc/super-editor' ) ) continue ;
175-
176- if ( mod . startsWith ( '@superdoc/' ) ) {
177- if ( ! workspaceImports . has ( mod ) ) workspaceImports . set ( mod , new Set ( ) ) ;
178- const names = m [ 1 ] . split ( ',' ) . map ( n => n . trim ( ) . split ( / \s + a s \s + / ) [ 0 ] . trim ( ) ) . filter ( Boolean ) ;
179- for ( const name of names ) workspaceImports . get ( mod ) . add ( name ) ;
180- }
181- }
182-
183- // Match: import('...').SomeName — dynamic import type references
184- const dynamicImports = fileContent . matchAll ( / i m p o r t \( [ ' " ] ( [ ^ ' " ] + ) [ ' " ] \) \. ( \w + ) / g) ;
185- for ( const m of dynamicImports ) {
186- const mod = m [ 1 ] ;
187- if ( mod . startsWith ( '.' ) || mod . startsWith ( '@superdoc/common' ) || mod . startsWith ( '@superdoc/super-editor' ) ) continue ;
188-
189- if ( mod . startsWith ( '@superdoc/' ) ) {
190- if ( ! workspaceImports . has ( mod ) ) workspaceImports . set ( mod , new Set ( ) ) ;
191- workspaceImports . get ( mod ) . add ( m [ 2 ] ) ;
192- }
193- }
194-
195- // Match bare @superdoc /* module references
196- const bareRefs = fileContent . matchAll ( / [ ' " ] ( @ s u p e r d o c \/ [ ^ ' " ] + ) [ ' " ] / g) ;
197- for ( const m of bareRefs ) {
198- const mod = m [ 1 ] ;
199- if ( mod . startsWith ( '@superdoc/common' ) || mod . startsWith ( '@superdoc/super-editor' ) ) continue ;
200- if ( ! workspaceImports . has ( mod ) ) workspaceImports . set ( mod , new Set ( ) ) ;
201- }
202- }
203-
204- // ---------------------------------------------------------------------------
205- // Write _internal-shims.d.ts
206- //
207- // Two sections:
208- // 1. Hand-written shims for external packages (prosemirror-*, vue, yjs,
209- // eventemitter3, @hocuspocus/provider). See KNOWN LIMITATION note in the
210- // generated file about ambient shims overriding real package types.
211- // 2. Auto-generated shims for @superdoc/* workspace packages.
212- // ---------------------------------------------------------------------------
213-
214- const shimLines = [
215- '// Auto-generated ambient declarations for internal/bundled packages.' ,
216- '// These packages are bundled into superdoc or are internal workspace packages.' ,
217- '// Consumers do not need to install them. This file prevents TypeScript errors' ,
218- '// when skipLibCheck is false.' ,
219- '//' ,
220- '// KNOWN LIMITATION: ambient `declare module` with `export type X = any`' ,
221- '// overrides real package types when both are present. This affects:' ,
222- '// - vue, eventemitter3: direct deps of superdoc — ALWAYS in consumer' ,
223- '// node_modules, so real types are always replaced by `any`.' ,
224- '// - yjs, @hocuspocus/provider: peer deps — affected when installed.' ,
225- '// - prosemirror-*: bundled (not in consumer node_modules) — no conflict.' ,
226- '// The proper fix is adding prosemirror-* as peerDependencies and removing' ,
227- '// shims for packages consumers already have installed.' ,
228- '//' ,
229- '// NOTE: This is a script file (no exports), so `declare module` creates' ,
230- '// global ambient declarations and top-level declarations are global.' ,
231- '' ,
232- '// --- Well-known external packages (hand-written for correctness) ---' ,
233- '' ,
234- "declare module 'prosemirror-model' {" ,
235- ' export type DOMOutputSpec = any;' ,
236- ' export type Fragment = any;' ,
237- ' export type Mark = any;' ,
238- ' export type MarkType = any;' ,
239- ' export type Node = any;' ,
240- ' export type NodeType = any;' ,
241- ' export type ParseRule = any;' ,
242- ' export type ResolvedPos = any;' ,
243- ' export type Schema<N extends string = any, M extends string = any> = any;' ,
244- ' export type Slice = any;' ,
245- '}' ,
246- '' ,
247- "declare module 'prosemirror-state' {" ,
248- ' export type EditorState = any;' ,
249- ' export type Plugin<T = any> = any;' ,
250- ' export type PluginKey<T = any> = any;' ,
251- ' export type TextSelection = any;' ,
252- ' export type Transaction = any;' ,
253- '}' ,
254- '' ,
255- "declare module 'prosemirror-transform' {" ,
256- ' export type Mapping = any;' ,
257- ' export type ReplaceAroundStep = any;' ,
258- ' export type ReplaceStep = any;' ,
259- ' export type Step = any;' ,
260- '}' ,
261- '' ,
262- "declare module 'prosemirror-view' {" ,
263- ' export type Decoration = any;' ,
264- ' export type DecorationSet = any;' ,
265- ' export type DecorationSource = any;' ,
266- ' export type EditorProps = any;' ,
267- ' export type EditorView = any;' ,
268- ' export type NodeView = any;' ,
269- '}' ,
270- '' ,
271- "declare module 'eventemitter3' {" ,
272- ' export class EventEmitter<EventTypes extends string | symbol = string | symbol, Context = any> {' ,
273- ' on(event: EventTypes, fn: (...args: any[]) => void, context?: Context): this;' ,
274- ' off(event: EventTypes, fn: (...args: any[]) => void, context?: Context): this;' ,
275- ' emit(event: EventTypes, ...args: any[]): boolean;' ,
276- ' removeAllListeners(event?: EventTypes): this;' ,
277- ' }' ,
278- ' export default EventEmitter;' ,
279- '}' ,
280- '' ,
281- "declare module 'vue' {" ,
282- ' export type App<T = any> = any;' ,
283- ' 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;' ,
284- ' export type ComponentOptionsMixin = any;' ,
285- ' export type ComponentProvideOptions = any;' ,
286- ' 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;' ,
287- ' export type ComputedRef<T = any> = any;' ,
288- ' 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;' ,
289- ' 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;' ,
290- ' export type ExtractPropTypes<T = any> = any;' ,
291- ' export type GlobalComponents = any;' ,
292- ' export type GlobalDirectives = any;' ,
293- ' export type PublicProps = any;' ,
294- ' export type Ref<T = any> = any;' ,
295- ' export type RendererElement = any;' ,
296- ' export type RendererNode = any;' ,
297- ' export type ShallowRef<T = any> = any;' ,
298- ' export type VNode = any;' ,
299- '}' ,
300- '' ,
301- "declare module 'yjs' {" ,
302- ' export type Doc = any;' ,
303- ' export type XmlFragment = any;' ,
304- ' export type RelativePosition = any;' ,
305- '}' ,
306- '' ,
307- "declare module '@hocuspocus/provider' {" ,
308- ' export type HocuspocusProvider = any;' ,
309- '}' ,
310- '' ,
311- ] ;
312-
313- // --- Auto-generated @superdoc/* workspace package shims ---
314-
315- let wsCount = 0 ;
316- if ( workspaceImports . size > 0 ) {
317- shimLines . push ( '// --- Internal workspace packages (auto-generated) ---' ) ;
318- shimLines . push ( '' ) ;
319- for ( const [ mod , names ] of [ ...workspaceImports . entries ( ) ] . sort ( ( a , b ) => a [ 0 ] . localeCompare ( b [ 0 ] ) ) ) {
320- wsCount ++ ;
321- const sortedNames = [ ...names ] . sort ( ) ;
322- const exportLines = sortedNames
323- . map ( n => ` export type ${ n } = any;` ) ;
324- if ( exportLines . length > 0 ) {
325- shimLines . push ( `declare module '${ mod } ' {\n${ exportLines . join ( '\n' ) } \n}` ) ;
326- } else {
327- shimLines . push ( `declare module '${ mod } ' { const _: any; export default _; }` ) ;
328- }
329- }
330- }
331- shimLines . push ( '' ) ;
332-
333- const shimPath = path . join ( distRoot , '_internal-shims.d.ts' ) ;
334- fs . writeFileSync ( shimPath , shimLines . join ( '\n' ) ) ;
335-
336- // Add reference directive to entry points so TypeScript includes the shims
337- const shimRef = '/// <reference path="../../_internal-shims.d.ts" />\n' ;
338- for ( const entry of requiredEntryPoints ) {
339- const entryPath = path . join ( distRoot , entry ) ;
340- const entryContent = fs . readFileSync ( entryPath , 'utf8' ) ;
341- if ( ! entryContent . includes ( '_internal-shims.d.ts' ) ) {
342- fs . writeFileSync ( entryPath , shimRef + entryContent ) ;
343- }
344- }
345-
346- console . log ( `[ensure-types] ✓ Generated ambient shims for ${ wsCount } workspace + 8 external modules` ) ;
347-
34861console . log ( '[ensure-types] ✓ Verified type entry points' ) ;
0 commit comments