@@ -82,6 +82,10 @@ export type ServerOptions = {
8282 projectPath : string
8383 /** the working directory */
8484 workingDirectory ?: string
85+ /** the path to the template backend configuration */
86+ templateBackendConfigPath ?: string
87+ /** the content of the template backend configuration */
88+ templateBackendConfig ?: string
8589 /** whether to print verbose messages */
8690 verboseMessages ?: boolean
8791 /** Whether to enable strict checks (avoid `any` type fallbacks) */
@@ -103,6 +107,8 @@ export class Server {
103107 private rootFilePaths : Cache < string [ ] >
104108 private rootTsFileCount : number
105109 private rootFilePathsVersion : number
110+ private templateBackendConfigPath : string
111+ private templateBackendConfig : ts . IScriptSnapshot | null
106112 private configErrors : ts . Diagnostic [ ]
107113 private pendingAsyncTasksListeners : ( ( ) => void ) [ ] = [ ]
108114
@@ -111,9 +117,15 @@ export class Server {
111117 const tsc = this . tsc
112118 this . tmplGroup = options . tmplGroup
113119 const tmplGroup = this . tmplGroup
114- this . options = options
115120 this . workingDirectory = options . workingDirectory ?? process . cwd ( )
116121 this . projectPath = path . resolve ( this . workingDirectory , options . projectPath )
122+ this . templateBackendConfig = options . templateBackendConfig
123+ ? tsc . ScriptSnapshot . fromString ( options . templateBackendConfig )
124+ : null
125+ this . templateBackendConfigPath = options . templateBackendConfigPath
126+ ? path . resolve ( this . workingDirectory , options . templateBackendConfigPath )
127+ : ''
128+ this . options = options
117129
118130 // initialize virtual file system
119131 this . projectDirManager = new ProjectDirManager ( tsc , tmplGroup , this . projectPath , ( ) => {
@@ -217,9 +229,19 @@ export class Server {
217229 return this . rootFilePaths . get ( )
218230 } ,
219231 getScriptVersion : ( fullPath ) => {
232+ if ( fullPath === this . options . templateBackendConfigPath ) {
233+ if ( this . templateBackendConfig !== null ) {
234+ return '1'
235+ }
236+ }
220237 return this . projectDirManager . getFileVersion ( fullPath ) ?. toString ( ) ?? ''
221238 } ,
222239 getScriptSnapshot : ( fullPath ) => {
240+ if ( fullPath === this . options . templateBackendConfigPath ) {
241+ if ( this . templateBackendConfig !== null ) {
242+ return this . templateBackendConfig
243+ }
244+ }
223245 const content = this . projectDirManager . getFileTsContent ( fullPath )
224246 if ( content === null ) return undefined
225247 return tsc . ScriptSnapshot . fromString ( content )
@@ -302,6 +324,13 @@ export class Server {
302324 // escape helper
303325 const escapeJsString = ( str : string ) => str . replace ( / [ ' \\ ] / g, ( a ) => `\\${ a } ` )
304326
327+ // get global backend configuraion fields
328+ const globalBackendConfigLine = this . templateBackendConfigPath
329+ ? `import type { ComponentProperties as _GlobalComponentProperties_ } from '${ escapeJsString (
330+ this . templateBackendConfigPath ,
331+ ) } '`
332+ : 'type _GlobalComponentProperties_ = Record<string, never>'
333+
305334 // get exports from corresponding ts file
306335 const defaultExport = getDefaultExportOfSourceFile ( tc , source )
307336 const relPath = path . relative ( compDir , tsFullPath . slice ( 0 , - 3 ) )
@@ -322,7 +351,7 @@ declare const methods: _ComponentFieldTypes_<typeof component> extends _Componen
322351
323352 // get exports from using components
324353 const propertiesHelperLine = `
325- type Properties <T> = _ComponentFieldTypes_<T> extends _Component_<infer P, any, any>
354+ type _Properties_ <T> = _ComponentFieldTypes_<T> extends _Component_<infer P, any, any>
326355? P
327356: { [k: string]: any }`
328357 let usingComponentsImports = ''
@@ -336,7 +365,7 @@ type Properties<T> = _ComponentFieldTypes_<T> extends _Component_<infer P, any,
336365 const relPath = path . relative ( compDir , compPath )
337366 const entryName = `_component_${ tagName . replace ( / - / g, '_' ) } `
338367 usingComponentsImports += `import type ${ entryName } from './${ escapeJsString ( relPath ) } '\n`
339- usingComponentsItems . push ( `'${ tagName } ': Properties <typeof ${ entryName } >;\n` )
368+ usingComponentsItems . push ( `'${ tagName } ': _Properties_ <typeof ${ entryName } >;\n` )
340369 } )
341370
342371 // treat generics as any type tags
@@ -355,13 +384,14 @@ type Properties<T> = _ComponentFieldTypes_<T> extends _Component_<infer P, any,
355384 ? '[other: string]: unknown'
356385 : '[other: string]: any'
357386 const tagsLine = `
358- declare const tags: {
387+ declare const tags: _GlobalComponentProperties_ & {
359388${ usingComponentsItems . join ( '' ) } ${ otherComponents } }`
360389
361390 // add an empty export to avoid some tsc behavior
362391 const exportLine = 'export default {}'
363392
364393 return [
394+ globalBackendConfigLine ,
365395 tsImportLine ,
366396 usingComponentsImports ,
367397 adapterTypesLine ,
0 commit comments