@@ -8,15 +8,29 @@ import { SourceControlApi } from "../sourcecontrol/client";
88import { CreateItemClient } from "../sourcecontrol/clients/createItemClient" ;
99import { getCcsSettings } from "../config/settings" ;
1010
11- async function promptForItemName ( ) : Promise < string | undefined > {
11+ interface PromptForItemNameOptions {
12+ initialValue ?: string ;
13+ validationMessage ?: string ;
14+ }
15+
16+ async function promptForItemName ( options : PromptForItemNameOptions = { } ) : Promise < string | undefined > {
1217 const hasValidExt = ( s : string ) => / \. c l s $ / i. test ( s ) || / \. m a c $ / i. test ( s ) ;
1318 const hasBadChars = ( s : string ) => / [ \\ / ] / . test ( s ) || / \s / . test ( s ) ;
1419
1520 const ib = vscode . window . createInputBox ( ) ;
16- ib . title = "Create InterSystems Item" ;
17- ib . prompt = "Enter the name of the class or routine to create (.cls or .mac)" ;
18- ib . placeholder = "MyPackage.MyClass .cls or CCTRIB001 .mac" ;
21+ ib . title = "Criar Item Consistem " ;
22+ ib . prompt = "Informe o nome da classe ou rotina a ser criada (.cls ou .mac)" ;
23+ ib . placeholder = "MeuPacote.MinhaClasse .cls ou MINHAROTINA .mac" ;
1924 ib . ignoreFocusOut = true ;
25+ if ( options . initialValue ) {
26+ ib . value = options . initialValue ;
27+ }
28+ if ( options . validationMessage ) {
29+ ib . validationMessage = {
30+ message : options . validationMessage ,
31+ severity : vscode . InputBoxValidationSeverity . Error ,
32+ } ;
33+ }
2034
2135 return await new Promise < string | undefined > ( ( resolve ) => {
2236 const disposeAll = ( ) => {
@@ -36,19 +50,22 @@ async function promptForItemName(): Promise<string | undefined> {
3650 const name = ib . value . trim ( ) ;
3751
3852 if ( ! name ) {
39- ib . validationMessage = { message : "Item name is required" , severity : vscode . InputBoxValidationSeverity . Error } ;
53+ ib . validationMessage = {
54+ message : "Informe o nome do item" ,
55+ severity : vscode . InputBoxValidationSeverity . Error ,
56+ } ;
4057 return ;
4158 }
4259 if ( hasBadChars ( name ) ) {
4360 ib . validationMessage = {
44- message : "Invalid name: avoid spaces and path separators " ,
61+ message : "Nome inválido: não use espaços nem separadores de caminho (\\ ou /) " ,
4562 severity : vscode . InputBoxValidationSeverity . Error ,
4663 } ;
4764 return ;
4865 }
4966 if ( ! hasValidExt ( name ) ) {
5067 ib . validationMessage = {
51- message : "Please include a valid extension : .cls or .mac" ,
68+ message : "Inclua uma extensão válida : .cls ou .mac" ,
5269 severity : vscode . InputBoxValidationSeverity . Error ,
5370 } ;
5471 return ;
@@ -142,6 +159,24 @@ function getErrorMessage(err: unknown): string | undefined {
142159 return undefined ;
143160}
144161
162+ function getApiValidationMessage ( err : unknown ) : string | undefined {
163+ const anyErr = err as any ;
164+ const response = anyErr ?. response ;
165+ if ( ! response ?. data ) return undefined ;
166+
167+ const status = typeof response . status === "number" ? response . status : undefined ;
168+ if ( typeof status === "number" && status >= 500 ) {
169+ return undefined ;
170+ }
171+
172+ const data = response . data ;
173+ if ( typeof data === "string" && data . trim ( ) ) return data . trim ( ) ;
174+ if ( typeof data ?. error === "string" && data . error . trim ( ) ) return data . error . trim ( ) ;
175+ if ( typeof data ?. message === "string" && data . message . trim ( ) ) return data . message . trim ( ) ;
176+ if ( typeof data ?. Message === "string" && data . Message . trim ( ) ) return data . Message . trim ( ) ;
177+ return undefined ;
178+ }
179+
145180export async function createItem ( ) : Promise < void > {
146181 const workspaceFolder = await getWsFolder (
147182 "Pick the workspace folder where you want to create the item" ,
@@ -171,13 +206,6 @@ export async function createItem(): Promise<void> {
171206 }
172207 const namespace = ns . toUpperCase ( ) ;
173208
174- const itemName = await promptForItemName ( ) ;
175- if ( ! itemName ) {
176- return ;
177- }
178-
179- logDebug ( "CCS createItem invoked" , { namespace, itemName } ) ;
180-
181209 let sourceControlApi : SourceControlApi ;
182210 try {
183211 sourceControlApi = SourceControlApi . fromAtelierApi ( api ) ;
@@ -192,61 +220,85 @@ export async function createItem(): Promise<void> {
192220 const { requestTimeout } = getCcsSettings ( ) ;
193221 const backoff = Math . min ( 500 , Math . max ( 150 , Math . floor ( requestTimeout * 0.1 ) ) ) ;
194222
195- try {
196- const { data, status } = await vscode . window . withProgress (
197- {
198- location : vscode . ProgressLocation . Notification ,
199- title : "Creating item..." ,
200- cancellable : false ,
201- } ,
202- async ( ) => withTimeoutRetry ( ( ) => createItemClient . create ( namespace , itemName ) , 2 , backoff )
203- ) ;
223+ let lastValue : string | undefined ;
224+ let lastValidationMessage : string | undefined ;
204225
205- if ( data . error ) {
206- logError ( "CCS createItem failed" , { namespace , itemName , status , error : data . error } ) ;
207- void vscode . window . showErrorMessage ( data . error ) ;
226+ while ( true ) {
227+ const itemName = await promptForItemName ( { initialValue : lastValue , validationMessage : lastValidationMessage } ) ;
228+ if ( ! itemName ) {
208229 return ;
209230 }
210231
211- if ( status < 200 || status >= 300 ) {
212- const message = `Item creation failed with status ${ status } .` ;
213- logError ( "CCS createItem failed" , { namespace, itemName, status } ) ;
214- void vscode . window . showErrorMessage ( message ) ;
215- return ;
216- }
232+ lastValue = itemName ;
233+ lastValidationMessage = undefined ;
217234
218- if ( ! data . file ) {
219- const message = "Item created on server but no file path was returned." ;
220- logError ( "CCS createItem missing file path" , { namespace, itemName, response : data } ) ;
221- void vscode . window . showErrorMessage ( message ) ;
222- return ;
223- }
235+ logDebug ( "Consistem createItem invoked" , { namespace, itemName } ) ;
224236
225237 try {
226- await openCreatedFile ( data . file ) ;
227- } catch ( openErr ) {
228- logError ( "Failed to open created file" , { file : data . file , error : openErr } ) ;
229- void vscode . window . showWarningMessage ( "Item created, but the returned file could not be opened." ) ;
230- }
238+ const { data, status } = await vscode . window . withProgress (
239+ {
240+ location : vscode . ProgressLocation . Notification ,
241+ title : "Creating item..." ,
242+ cancellable : false ,
243+ } ,
244+ async ( ) => withTimeoutRetry ( ( ) => createItemClient . create ( namespace , itemName ) , 2 , backoff )
245+ ) ;
246+
247+ if ( data . error ) {
248+ logError ( "Consistem createItem failed" , { namespace, itemName, status, error : data . error } ) ;
249+ lastValidationMessage = data . error ;
250+ continue ;
251+ }
231252
232- const createdNamespace = data . namespace ?? namespace ;
233- const createdItem = ( data as any ) . itemIdCriado ?? itemName ;
234- const moduleName = extractModuleName ( data . file , workspaceFolder ) ;
235- const location = moduleName ? `${ createdNamespace } /${ moduleName } ` : createdNamespace ;
236- const successMessage = `Item created successfully in ${ location } : ${ createdItem } ` ;
237- logInfo ( "CCS createItem succeeded" , {
238- namespace : createdNamespace ,
239- module : moduleName ,
240- itemName : createdItem ,
241- file : data . file ,
242- } ) ;
243- void vscode . window . showInformationMessage ( successMessage ) ;
244- } catch ( error ) {
245- const errorMessage =
246- ( CreateItemClient as any ) . getErrorMessage ?.( error ) ??
247- getErrorMessage ( error ) ??
248- ( isTimeoutError ( error ) ? "Item creation timed out." : "Item creation failed." ) ;
249- logError ( "CCS createItem encountered an unexpected error" , error ) ;
250- void vscode . window . showErrorMessage ( errorMessage ) ;
253+ if ( status < 200 || status >= 300 ) {
254+ const message = `Item creation failed with status ${ status } .` ;
255+ logError ( "Consistem createItem failed" , { namespace, itemName, status } ) ;
256+ void vscode . window . showErrorMessage ( message ) ;
257+ return ;
258+ }
259+
260+ if ( ! data . file ) {
261+ const message = "Item created on server but no file path was returned." ;
262+ logError ( "Consistem createItem missing file path" , { namespace, itemName, response : data } ) ;
263+ void vscode . window . showErrorMessage ( message ) ;
264+ return ;
265+ }
266+
267+ try {
268+ await openCreatedFile ( data . file ) ;
269+ } catch ( openErr ) {
270+ logError ( "Failed to open created file" , { file : data . file , error : openErr } ) ;
271+ void vscode . window . showWarningMessage ( "Item created, but the returned file could not be opened." ) ;
272+ }
273+
274+ const createdNamespace = data . namespace ?? namespace ;
275+ const createdItem = ( data as any ) . itemIdCriado ?? itemName ;
276+ const moduleName = extractModuleName ( data . file , workspaceFolder ) ;
277+ const location = moduleName ? `${ createdNamespace } /${ moduleName } ` : createdNamespace ;
278+ const successMessage = `Item created successfully in ${ location } : ${ createdItem } ` ;
279+ logInfo ( "Consistem createItem succeeded" , {
280+ namespace : createdNamespace ,
281+ module : moduleName ,
282+ itemName : createdItem ,
283+ file : data . file ,
284+ } ) ;
285+ void vscode . window . showInformationMessage ( successMessage ) ;
286+ return ;
287+ } catch ( error ) {
288+ const apiValidationMessage = getApiValidationMessage ( error ) ;
289+ if ( apiValidationMessage ) {
290+ logError ( "Consistem createItem API validation failed" , { namespace, itemName, error : apiValidationMessage } ) ;
291+ lastValidationMessage = apiValidationMessage ;
292+ continue ;
293+ }
294+
295+ const errorMessage =
296+ ( CreateItemClient as any ) . getErrorMessage ?.( error ) ??
297+ getErrorMessage ( error ) ??
298+ ( isTimeoutError ( error ) ? "Item creation timed out." : "Item creation failed." ) ;
299+ logError ( "Consistem createItem encountered an unexpected error" , error ) ;
300+ void vscode . window . showErrorMessage ( errorMessage ) ;
301+ return ;
302+ }
251303 }
252304}
0 commit comments