Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apps/frontend/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZonelessChangeDetection, NgZone } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient, withFetch } from '@angular/common/http';
import { MONACO_PATH, MonacoEditorLoaderService } from '@materia-ui/ngx-monaco-editor';

import { routes } from './app.routes';
Expand All @@ -9,7 +10,8 @@ export const appConfig: ApplicationConfig = {
providers: [
provideBrowserGlobalErrorListeners(),
provideZonelessChangeDetection(),
provideRouter(routes),
provideRouter(routes),
provideHttpClient(withFetch()),
provideClientHydration(withEventReplay()),
{
provide: MONACO_PATH,
Expand Down
32 changes: 32 additions & 0 deletions apps/frontend/src/app/components/editor/editor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { CommonModule, isPlatformBrowser } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
import { PLATFORM_ID, inject } from '@angular/core';
import { CompilerService } from '../../services/compiler';


const DEFAULT_RUST_CODE = `// Welcome to Soroban Smart Contract Editor
Expand Down Expand Up @@ -33,6 +34,7 @@ export class EditorComponent implements OnDestroy {
private timeoutIds = new Set<number>();
isLoading = false;
isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
private compilerService = inject(CompilerService);

// Validation and output properties
errorMessage: string = '';
Expand Down Expand Up @@ -114,6 +116,21 @@ export class EditorComponent implements OnDestroy {
this.outputType = 'info';
console.log('Compiling Rust smart contract code:', this.code);

this.compilerService.compile(this.code).subscribe({
next: (response) => {
this.isLoading = false;
this.outputMessage = 'Compilation completed successfully!';
this.outputType = 'success';
console.log('Compilation response:', response);
},
error: (error) => {
this.isLoading = false;
this.errorMessage = 'Compilation failed: ' + (error.message || error);
this.outputType = 'error';
console.error('Compilation error:', error);
}
});

// TODO: Implement API call to backend compiler
const timeoutId = setTimeout(() => {
this.isLoading = false;
Expand All @@ -140,6 +157,21 @@ export class EditorComponent implements OnDestroy {
this.outputType = 'info';
console.log('Testing Rust smart contract code:', this.code);

this.compilerService.test(this.code).subscribe({
next: (response) => {
this.isLoading = false;
this.outputMessage = 'All tests passed successfully!';
this.outputType = 'success';
console.log('Test response:', response);
},
error: (error) => {
this.isLoading = false;
this.errorMessage = 'Tests failed: ' + (error.message || error);
this.outputType = 'error';
console.error('Test error:', error);
}
});

// TODO: Implement API call to backend test runner
const timeoutId = setTimeout(() => {
this.isLoading = false;
Expand Down
16 changes: 16 additions & 0 deletions apps/frontend/src/app/services/compiler.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { Compiler } from './compiler';

describe('Compiler', () => {
let service: Compiler;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(Compiler);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
85 changes: 85 additions & 0 deletions apps/frontend/src/app/services/compiler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

// Define interfaces for type safety
export interface CompileRequest {
code: string;
}

export interface CompileResponse {
output: string;
success?: boolean;
error?: string;
}

export interface TestResponse {
output: string;
success?: boolean;
error?: string;
}

@Injectable({
providedIn: 'root'
})
export class CompilerService {
private readonly API_BASE_URL = 'http://localhost:3000/api';
private http = inject(HttpClient);

/**
* Compile Rust smart contract code
*/
compile(code: string): Observable<CompileResponse> {
const request: CompileRequest = { code };

return this.http.post<CompileResponse>(`${this.API_BASE_URL}/compile`, request)
.pipe(
map(response => ({
...response,
success: true
})),
catchError(this.handleError)
);
}

/**
* Test Rust smart contract code
*/
test(code: string): Observable<TestResponse> {
const request: CompileRequest = { code };

return this.http.post<TestResponse>(`${this.API_BASE_URL}/test`, request)
.pipe(
map(response => ({
...response,
success: true
})),
catchError(this.handleError)
);
}

/**
* Handle HTTP errors
*/
private handleError(error: HttpErrorResponse): Observable<never> {
let errorMessage = 'An unknown error occurred';

if (error.error instanceof ErrorEvent) {
// Client-side error
errorMessage = `Error: ${error.error.message}`;
} else {
// Server-side error
errorMessage = error.error?.message ||
error.error?.output ||
`Server Error: ${error.status} - ${error.statusText}`;
}

console.error('CompilerService Error:', errorMessage);
return throwError(() => ({
output: errorMessage,
success: false,
error: errorMessage
}));
}
}
Loading