@isthatuzii/create-nano-app
Version:
Desktop application scaffolding tool for the Nano Framework
193 lines (159 loc) • 5.06 kB
text/typescript
/**
* Simple Nano IPC Invoke System
*
* Clean, minimal invoke function for calling nano backend functions
*/
// This is now on NPM: https://www.npmjs.com/package/nano-invoke
// Please use that instead of this file
// import { invoke, configure } from 'nano-invoke';
// Optional: Configure the client
// configure({
// debug: true,
// timeout: 5000
// });
// Call any registered nano function
// const result = await invoke('greet', { name: 'World' });
// console.log(result); // "Hello, World!"
// Call external system functions
// const calculation = await invoke('calculate', {
// operation: 'add',
// values: [10, 20, 30]
// });
// console.log(calculation.result); // 60
// Simple IPC types
export interface IpcRequest {
cmd: string;
args: Record<string, any>;
id?: string;
}
export interface IpcResponse<T = any> {
result?: T;
error?: string;
code?: string;
id?: string;
}
/**
* Simple invoke function for calling nano functions
*
* @param cmd - Function name to invoke
* @param args - Arguments to pass to the function
* @returns Promise resolving to the function result
*/
export async function invoke<T = any>(
cmd: string,
args: Record<string, any> = {}
): Promise<T> {
const request: IpcRequest = {
cmd,
args: args || {}
};
try {
console.log(`[IPC] Invoking: ${cmd}`, args);
const response = await fetch('/ipc', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(request),
});
console.log(`[IPC] Response status: ${response.status} ${response.statusText}`);
if (!response.ok) {
// Try to get the response text for better error messages
const errorText = await response.text();
console.error(`[IPC] Error response:`, errorText);
if (response.status === 404) {
throw new Error('IPC endpoint not found. Make sure the Nano server is running.');
}
throw new Error(`HTTP ${response.status}: ${response.statusText} - ${errorText}`);
}
const result: IpcResponse<T> = await response.json();
console.log(`[IPC] Result:`, result);
if (result.error) {
throw new Error(result.error);
}
return result.result as T;
} catch (error) {
console.error(`[IPC] Invoke error:`, error);
if (error instanceof TypeError && error.message.includes('fetch')) {
throw new Error('Cannot connect to server. Make sure the Nano application is running.');
}
throw new Error(
error instanceof Error ? error.message : String(error)
);
}
}
// Simple namespace for type safety (optional)
export namespace Commands {
// Just the basic types we need
export interface SystemInfo {
os: string;
arch: string;
hostname: string;
}
export interface UserInfo {
name: string;
age: number;
email: string;
}
}
// Simple event system (optional - for WebSocket events)
export type EventListener<T = any> = (data: T) => void;
export class EventManager {
private ws: WebSocket | null = null;
private listeners: Map<string, Set<EventListener>> = new Map();
async connect(): Promise<void> {
return new Promise((resolve, reject) => {
try {
this.ws = new WebSocket(`ws://${window.location.host}/ws`);
this.ws.onopen = () => {
resolve();
};
this.ws.onmessage = (event) => {
try {
const message = JSON.parse(event.data);
this.emit(message.event, message.payload);
} catch (error) {
console.error('Failed to parse event:', error);
}
};
this.ws.onerror = () => {
reject(new Error('WebSocket connection failed'));
};
} catch (error) {
reject(error);
}
});
}
on<T = any>(event: string, listener: EventListener<T>): void {
if (!this.listeners.has(event)) {
this.listeners.set(event, new Set());
}
this.listeners.get(event)!.add(listener as EventListener);
}
off<T = any>(event: string, listener: EventListener<T>): void {
const eventListeners = this.listeners.get(event);
if (eventListeners) {
eventListeners.delete(listener as EventListener);
}
}
private emit(event: string, data: any): void {
const eventListeners = this.listeners.get(event);
if (eventListeners) {
eventListeners.forEach(listener => {
try {
listener(data);
} catch (error) {
console.error(`Error in event listener:`, error);
}
});
}
}
}
// Default event manager instance
export const events = new EventManager();
// Simple utilities
export namespace Utils {
export async function ping(): Promise<string> {
return await invoke('ping');
}
}