mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-09 11:55:53 +00:00
fixes linter issues
This commit is contained in:
parent
9101613351
commit
3351cc08c2
9 changed files with 92 additions and 48 deletions
|
|
@ -462,7 +462,8 @@ export class FileBrowser extends LitElement {
|
|||
}
|
||||
|
||||
// Fallback to simple diff display
|
||||
const lines = this.diff!.diff.split('\n');
|
||||
if (!this.diff) return html``;
|
||||
const lines = this.diff.diff.split('\n');
|
||||
return html`
|
||||
<div class="overflow-auto h-full p-4 font-mono text-xs">
|
||||
${lines.map((line) => {
|
||||
|
|
@ -839,11 +840,22 @@ export class FileBrowser extends LitElement {
|
|||
document.addEventListener('touchend', handleTouchEnd);
|
||||
|
||||
// Store handlers for removal
|
||||
(this as any)._touchHandlers = { handleTouchStart, handleTouchEnd };
|
||||
interface TouchHandlers {
|
||||
handleTouchStart: (e: TouchEvent) => void;
|
||||
handleTouchEnd: (e: TouchEvent) => void;
|
||||
}
|
||||
(this as unknown as { _touchHandlers: TouchHandlers })._touchHandlers = {
|
||||
handleTouchStart,
|
||||
handleTouchEnd,
|
||||
};
|
||||
}
|
||||
|
||||
private removeTouchHandlers() {
|
||||
const handlers = (this as any)._touchHandlers;
|
||||
interface TouchHandlers {
|
||||
handleTouchStart: (e: TouchEvent) => void;
|
||||
handleTouchEnd: (e: TouchEvent) => void;
|
||||
}
|
||||
const handlers = (this as unknown as { _touchHandlers?: TouchHandlers })._touchHandlers;
|
||||
if (handlers) {
|
||||
document.removeEventListener('touchstart', handlers.handleTouchStart);
|
||||
document.removeEventListener('touchend', handlers.handleTouchEnd);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const logger = createLogger('monaco-editor');
|
|||
// Import Monaco Editor types
|
||||
declare global {
|
||||
interface Window {
|
||||
monaco: any;
|
||||
monaco: typeof import('monaco-editor');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ interface PushNotificationPayload {
|
|||
}
|
||||
|
||||
// Install event
|
||||
self.addEventListener('install', (event: ExtendableEvent) => {
|
||||
self.addEventListener('install', (_event: ExtendableEvent) => {
|
||||
console.log('[SW] Installing service worker');
|
||||
|
||||
// Force activation of new service worker
|
||||
|
|
@ -158,8 +158,13 @@ async function handlePushNotification(payload: PushNotificationPayload): Promise
|
|||
}
|
||||
}
|
||||
|
||||
function getDefaultActions(data: NotificationData): any[] {
|
||||
const baseActions: any[] = [
|
||||
interface NotificationAction {
|
||||
action: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
function getDefaultActions(data: NotificationData): NotificationAction[] {
|
||||
const baseActions: NotificationAction[] = [
|
||||
{
|
||||
action: 'dismiss',
|
||||
title: 'Dismiss',
|
||||
|
|
|
|||
|
|
@ -11,8 +11,11 @@ const logger = createLogger('monaco-loader');
|
|||
// Declare monaco on window
|
||||
declare global {
|
||||
interface Window {
|
||||
monaco: any;
|
||||
require: any;
|
||||
monaco: typeof import('monaco-editor');
|
||||
require: {
|
||||
(dependencies: string[], callback: (...args: unknown[]) => void): void;
|
||||
config: (config: { paths: { [key: string]: string } }) => void;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,8 +45,10 @@ async function loadMonacoEditor(): Promise<void> {
|
|||
// Disable workers - they interfere with diff computation
|
||||
// Monaco will fall back to synchronous mode which works fine
|
||||
window.MonacoEnvironment = {
|
||||
getWorker: function (_workerId: string, _label: string) {
|
||||
return null as any;
|
||||
getWorker: function (_workerId: string, _label: string): Worker {
|
||||
// Return a dummy worker that will never be used
|
||||
// Monaco will fall back to synchronous mode
|
||||
return new Worker('data:,');
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -150,7 +155,7 @@ export async function initializeMonaco(): Promise<void> {
|
|||
/**
|
||||
* Ensure Monaco is loaded and ready
|
||||
*/
|
||||
export async function ensureMonacoLoaded(): Promise<any> {
|
||||
export async function ensureMonacoLoaded(): Promise<typeof import('monaco-editor')> {
|
||||
await initializeMonaco();
|
||||
return window.monaco;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,8 +205,9 @@ export class OfflineNotificationManager {
|
|||
return [];
|
||||
}
|
||||
|
||||
const db = this.db;
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = this.db!.transaction([STORE_NAME], 'readonly');
|
||||
const transaction = db.transaction([STORE_NAME], 'readonly');
|
||||
const store = transaction.objectStore(STORE_NAME);
|
||||
const index = store.index('nextRetry');
|
||||
|
||||
|
|
@ -229,8 +230,9 @@ export class OfflineNotificationManager {
|
|||
throw new Error('Database not initialized');
|
||||
}
|
||||
|
||||
const db = this.db;
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = this.db!.transaction([STORE_NAME], 'readwrite');
|
||||
const transaction = db.transaction([STORE_NAME], 'readwrite');
|
||||
const store = transaction.objectStore(STORE_NAME);
|
||||
const request = store.add(notification);
|
||||
|
||||
|
|
@ -244,8 +246,9 @@ export class OfflineNotificationManager {
|
|||
throw new Error('Database not initialized');
|
||||
}
|
||||
|
||||
const db = this.db;
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = this.db!.transaction([STORE_NAME], 'readwrite');
|
||||
const transaction = db.transaction([STORE_NAME], 'readwrite');
|
||||
const store = transaction.objectStore(STORE_NAME);
|
||||
const request = store.put(notification);
|
||||
|
||||
|
|
@ -259,8 +262,9 @@ export class OfflineNotificationManager {
|
|||
throw new Error('Database not initialized');
|
||||
}
|
||||
|
||||
const db = this.db;
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = this.db!.transaction([STORE_NAME], 'readwrite');
|
||||
const transaction = db.transaction([STORE_NAME], 'readwrite');
|
||||
const store = transaction.objectStore(STORE_NAME);
|
||||
const request = store.delete(id);
|
||||
|
||||
|
|
@ -277,8 +281,9 @@ export class OfflineNotificationManager {
|
|||
return { total: 0, pending: 0, failed: 0, lastProcessed: 0 };
|
||||
}
|
||||
|
||||
const db = this.db;
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = this.db!.transaction([STORE_NAME], 'readonly');
|
||||
const transaction = db.transaction([STORE_NAME], 'readonly');
|
||||
const store = transaction.objectStore(STORE_NAME);
|
||||
const request = store.getAll();
|
||||
|
||||
|
|
@ -311,8 +316,9 @@ export class OfflineNotificationManager {
|
|||
return;
|
||||
}
|
||||
|
||||
const db = this.db;
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = this.db!.transaction([STORE_NAME], 'readwrite');
|
||||
const transaction = db.transaction([STORE_NAME], 'readwrite');
|
||||
const store = transaction.objectStore(STORE_NAME);
|
||||
const request = store.clear();
|
||||
|
||||
|
|
|
|||
|
|
@ -530,7 +530,10 @@ export function createFilesystemRoutes(): Router {
|
|||
logger.error(`Failed to get HEAD version of ./${relativePath}:`, error);
|
||||
// Check if it's a stderr message
|
||||
if (error instanceof Error && 'stderr' in error) {
|
||||
logger.error(`Git stderr: ${(error as any).stderr}`);
|
||||
const execError = error as Error & { stderr?: string };
|
||||
if (execError.stderr) {
|
||||
logger.error(`Git stderr: ${execError.stderr}`);
|
||||
}
|
||||
}
|
||||
// For non-git repos, show no diff
|
||||
originalContent = currentContent;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Router, Request, Response } from 'express';
|
||||
import { VapidManager } from '../utils/vapid-manager.js';
|
||||
import { PushNotificationService } from '../services/push-notification-service.js';
|
||||
import { BellEventHandler } from '../services/bell-event-handler.js';
|
||||
import { createLogger } from '../utils/logger.js';
|
||||
|
||||
const logger = createLogger('push-routes');
|
||||
|
|
@ -8,25 +9,13 @@ const logger = createLogger('push-routes');
|
|||
export interface CreatePushRoutesOptions {
|
||||
vapidManager: VapidManager;
|
||||
pushNotificationService: PushNotificationService | null;
|
||||
bellEventHandler?: any;
|
||||
bellEventHandler?: BellEventHandler;
|
||||
}
|
||||
|
||||
export function createPushRoutes(options: CreatePushRoutesOptions): Router {
|
||||
const { vapidManager, pushNotificationService } = options;
|
||||
const router = Router();
|
||||
|
||||
// Helper function to check if push service is available
|
||||
const checkPushService = (res: Response): boolean => {
|
||||
if (!pushNotificationService) {
|
||||
res.status(503).json({
|
||||
error: 'Push notifications not initialized',
|
||||
message: 'Push notification service is not available',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get VAPID public key for client registration
|
||||
*/
|
||||
|
|
@ -65,7 +54,12 @@ export function createPushRoutes(options: CreatePushRoutesOptions): Router {
|
|||
* Subscribe to push notifications
|
||||
*/
|
||||
router.post('/push/subscribe', async (req: Request, res: Response) => {
|
||||
if (!checkPushService(res)) return;
|
||||
if (!pushNotificationService) {
|
||||
return res.status(503).json({
|
||||
error: 'Push notifications not initialized',
|
||||
message: 'Push notification service is not available',
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const { endpoint, keys } = req.body;
|
||||
|
|
@ -77,7 +71,7 @@ export function createPushRoutes(options: CreatePushRoutesOptions): Router {
|
|||
});
|
||||
}
|
||||
|
||||
const subscriptionId = await pushNotificationService!.addSubscription(endpoint, keys);
|
||||
const subscriptionId = await pushNotificationService.addSubscription(endpoint, keys);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
|
|
@ -99,7 +93,12 @@ export function createPushRoutes(options: CreatePushRoutesOptions): Router {
|
|||
* Unsubscribe from push notifications
|
||||
*/
|
||||
router.post('/push/unsubscribe', async (req: Request, res: Response) => {
|
||||
if (!checkPushService(res)) return;
|
||||
if (!pushNotificationService) {
|
||||
return res.status(503).json({
|
||||
error: 'Push notifications not initialized',
|
||||
message: 'Push notification service is not available',
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const { endpoint } = req.body;
|
||||
|
|
@ -112,11 +111,11 @@ export function createPushRoutes(options: CreatePushRoutesOptions): Router {
|
|||
}
|
||||
|
||||
// For simplicity, we'll find and remove by endpoint
|
||||
const subscriptions = pushNotificationService!.getSubscriptions();
|
||||
const subscriptions = pushNotificationService.getSubscriptions();
|
||||
const subscription = subscriptions.find((sub) => sub.endpoint === endpoint);
|
||||
|
||||
if (subscription) {
|
||||
await pushNotificationService!.removeSubscription(subscription.id);
|
||||
await pushNotificationService.removeSubscription(subscription.id);
|
||||
logger.log(`Push subscription removed: ${subscription.id}`);
|
||||
}
|
||||
|
||||
|
|
@ -137,10 +136,15 @@ export function createPushRoutes(options: CreatePushRoutesOptions): Router {
|
|||
* Send test notification
|
||||
*/
|
||||
router.post('/push/test', async (req: Request, res: Response) => {
|
||||
if (!checkPushService(res)) return;
|
||||
if (!pushNotificationService) {
|
||||
return res.status(503).json({
|
||||
error: 'Push notifications not initialized',
|
||||
message: 'Push notification service is not available',
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await pushNotificationService!.sendNotification({
|
||||
const result = await pushNotificationService.sendNotification({
|
||||
type: 'test',
|
||||
title: '🔔 Test Notification',
|
||||
body: 'This is a test notification from VibeTunnel',
|
||||
|
|
@ -178,10 +182,15 @@ export function createPushRoutes(options: CreatePushRoutesOptions): Router {
|
|||
* Get service status
|
||||
*/
|
||||
router.get('/push/status', (req: Request, res: Response) => {
|
||||
if (!checkPushService(res)) return;
|
||||
if (!pushNotificationService) {
|
||||
return res.status(503).json({
|
||||
error: 'Push notifications not initialized',
|
||||
message: 'Push notification service is not available',
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const subscriptions = pushNotificationService!.getSubscriptions();
|
||||
const subscriptions = pushNotificationService.getSubscriptions();
|
||||
|
||||
res.json({
|
||||
enabled: vapidManager.isEnabled(),
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { SessionInfo } from '../../shared/types.js';
|
||||
import { createLogger } from '../utils/logger.js';
|
||||
import { PushNotificationService } from './push-notification-service.js';
|
||||
|
||||
const logger = createLogger('bell-event-handler');
|
||||
|
||||
|
|
@ -45,7 +46,7 @@ export interface BellNotificationPayload {
|
|||
* Ultra-simple bell event handler
|
||||
*/
|
||||
export class BellEventHandler {
|
||||
private pushNotificationService: any = null;
|
||||
private pushNotificationService: PushNotificationService | null = null;
|
||||
|
||||
constructor() {
|
||||
logger.debug('BellEventHandler initialized');
|
||||
|
|
@ -54,7 +55,7 @@ export class BellEventHandler {
|
|||
/**
|
||||
* Set the push notification service for sending notifications
|
||||
*/
|
||||
setPushNotificationService(service: any): void {
|
||||
setPushNotificationService(service: PushNotificationService): void {
|
||||
this.pushNotificationService = service;
|
||||
logger.debug('Push notification service configured');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ export interface NotificationPayload {
|
|||
action: string;
|
||||
title: string;
|
||||
}>;
|
||||
data?: any;
|
||||
data?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -195,13 +195,15 @@ export class PushNotificationService {
|
|||
const shouldRemove = this.shouldRemoveSubscription(error);
|
||||
if (shouldRemove) {
|
||||
this.subscriptions.delete(subscription.id);
|
||||
const webPushError = error as Error & { statusCode?: number };
|
||||
logger.log(
|
||||
`Removed expired subscription: ${subscription.id} (status: ${(error as any).statusCode})`
|
||||
`Removed expired subscription: ${subscription.id} (status: ${webPushError.statusCode})`
|
||||
);
|
||||
} else {
|
||||
// Debug log for unhandled errors
|
||||
const webPushError = error as Error & { statusCode?: number };
|
||||
logger.debug(
|
||||
`Not removing subscription ${subscription.id}, error: ${error instanceof Error ? error.message : String(error)}, statusCode: ${(error as any).statusCode}`
|
||||
`Not removing subscription ${subscription.id}, error: ${error instanceof Error ? error.message : String(error)}, statusCode: ${webPushError.statusCode}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -254,7 +256,7 @@ export class PushNotificationService {
|
|||
|
||||
// Check for HTTP 410 Gone status (subscription expired)
|
||||
// WebPushError has a statusCode property
|
||||
const webPushError = error as any;
|
||||
const webPushError = error as Error & { statusCode?: number };
|
||||
if (webPushError.statusCode === 410) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -315,7 +317,8 @@ export class PushNotificationService {
|
|||
|
||||
logger.debug(`Loaded ${subscriptions.length} subscriptions`);
|
||||
} catch (error) {
|
||||
if ((error as any).code === 'ENOENT') {
|
||||
const fsError = error as NodeJS.ErrnoException;
|
||||
if (fsError.code === 'ENOENT') {
|
||||
logger.debug('No existing subscriptions file found');
|
||||
} else {
|
||||
logger.error('Failed to load subscriptions:', error);
|
||||
|
|
|
|||
Loading…
Reference in a new issue