11import * as vscode from 'vscode' ;
22import * as path from 'path' ;
33import * as os from 'os' ;
4+ import { z } from 'zod' ;
45import { LanguageClient } from 'vscode-languageclient/node' ;
56import { URI } from 'vscode-uri' ;
67import { DocumentationCache } from './documentation-cache' ;
78import { requireAuth } from './extension' ;
9+ import { API_URL } from './zenstack-auth-provider' ;
810
911/**
1012 * ZModelPreview class handles ZModel file preview functionality
@@ -13,6 +15,25 @@ export class ZModelPreview implements vscode.Disposable {
1315 private documentationCache : DocumentationCache ;
1416 private languageClient : LanguageClient ;
1517
18+ // Schema for validating the request body
19+ private static DocRequestSchema = z . object ( {
20+ models : z . array (
21+ z . object ( {
22+ path : z . string ( ) . optional ( ) ,
23+ content : z . string ( ) ,
24+ } )
25+ ) ,
26+ environments : z
27+ . object ( {
28+ vscodeAppName : z . string ( ) ,
29+ vscodeVersion : z . string ( ) ,
30+ vscodeAppHost : z . string ( ) ,
31+ osRelease : z . string ( ) ,
32+ osType : z . string ( ) ,
33+ } )
34+ . optional ( ) ,
35+ } ) ;
36+
1637 constructor ( context : vscode . ExtensionContext , client : LanguageClient , cache : DocumentationCache ) {
1738 this . documentationCache = cache ;
1839 this . languageClient = client ;
@@ -141,50 +162,53 @@ export class ZModelPreview implements vscode.Disposable {
141162 const importedURIs = astInfo ?. importedURIs ;
142163
143164 // get vscode document from importedURIs
144- const importedTexts = await Promise . all (
165+ const importedModels = await Promise . all (
145166 importedURIs . map ( async ( uri ) => {
146167 try {
147168 const fileUri = vscode . Uri . file ( uri . path ) ;
148169 const fileContent = await vscode . workspace . fs . readFile ( fileUri ) ;
149- return Buffer . from ( fileContent ) . toString ( 'utf8' ) ;
170+ const filePath = fileUri . path ;
171+ return { content : Buffer . from ( fileContent ) . toString ( 'utf8' ) . trim ( ) , path : filePath } ;
150172 } catch ( error ) {
151- console . warn ( `Could not read file for URI ${ uri } :` , error ) ;
152- return null ;
173+ throw new Error (
174+ `Failed to read imported ZModel file at ${ uri . path } : ${
175+ error instanceof Error ? error . message : String ( error )
176+ } `
177+ ) ;
153178 }
154179 } )
155180 ) ;
156181
157- const zmodelContent = [ document . getText ( ) , ...importedTexts . filter ( ( text ) => text !== null ) ] ;
158-
159- // Trim whitespace from each model string
160- const trimmedZmodelContent = zmodelContent . map ( ( content ) => content . trim ( ) ) ;
182+ const allModels = [ { content : document . getText ( ) . trim ( ) , path : document . uri . path } , ...importedModels ] ;
161183
162184 const session = await requireAuth ( ) ;
163185 if ( ! session ) {
164186 throw new Error ( 'Authentication required to generate documentation' ) ;
165187 }
166188
167189 // Prepare request body
168- const requestBody = {
169- models : trimmedZmodelContent ,
190+ const requestBody : z . infer < typeof ZModelPreview . DocRequestSchema > = {
191+ models : allModels ,
170192 environments : {
171- editorName : vscode . env . appName ,
193+ vscodeAppName : vscode . env . appName ,
172194 vscodeVersion : vscode . version ,
173- appHost : vscode . env . appHost ,
195+ vscodeAppHost : vscode . env . appHost ,
174196 osRelease : os . release ( ) ,
175197 osType : os . type ( ) ,
176198 } ,
177199 } ;
178200
201+ const allModelsContent = allModels . map ( ( m ) => m . content ) ;
202+
179203 // Check cache first
180- const cachedResponse = await this . documentationCache . getCachedResponse ( requestBody ) ;
204+ const cachedResponse = await this . documentationCache . getCachedResponse ( allModelsContent ) ;
181205 if ( cachedResponse ) {
182206 return cachedResponse ;
183207 }
184208
185209 // record the time spent
186210 const startTime = Date . now ( ) ;
187- const apiResponse = await fetch ( 'https:// api.zenstack.dev/api/ doc' , {
211+ const apiResponse = await fetch ( ` ${ API_URL } / api/ doc` , {
188212 method : 'POST' ,
189213 headers : {
190214 'Content-Type' : 'application/json' ,
@@ -202,7 +226,7 @@ export class ZModelPreview implements vscode.Disposable {
202226 const responseText = await apiResponse . text ( ) ;
203227
204228 // Cache the response
205- await this . documentationCache . setCachedResponse ( requestBody , responseText ) ;
229+ await this . documentationCache . setCachedResponse ( allModelsContent , responseText ) ;
206230
207231 return responseText ;
208232 } catch ( error ) {
0 commit comments