diff --git a/src/backend/clients/EventClient.js b/src/backend/clients/EventClient.js index 3a137d12a..4ba862464 100644 --- a/src/backend/clients/EventClient.js +++ b/src/backend/clients/EventClient.js @@ -17,9 +17,11 @@ * along with this program. If not, see . */ +import { extensionStore } from '../extensions'; import { PuterClient } from './types'; export class EventClient extends PuterClient { + /** @type {Recordvoid)[]>} */ #eventListeners = {}; onServerStart() { @@ -60,7 +62,10 @@ export class EventClient extends PuterClient { i === parts.length - 1 ? key : `${parts.slice(0, i + 1).join('.')}.*`; - const listeners = this.#eventListeners[matchKey]; + const extensionListeners = extensionStore.events[matchKey]; + const listeners = (this.#eventListeners[matchKey] || []).concat( + extensionListeners || [], + ); if (!listeners) continue; for (const listener of listeners) { this.#emitEvent(listener, key, data, meta); @@ -93,7 +98,10 @@ export class EventClient extends PuterClient { i === parts.length - 1 ? key : `${parts.slice(0, i + 1).join('.')}.*`; - const listeners = this.#eventListeners[matchKey]; + const extensionListeners = extensionStore.events[matchKey]; + const listeners = (this.#eventListeners[matchKey] || []).concat( + extensionListeners || [], + ); if (!listeners) continue; for (const listener of listeners) { try { diff --git a/src/backend/controllers/apps/AppController.js b/src/backend/controllers/apps/AppController.js index 36f055ad3..a50835959 100644 --- a/src/backend/controllers/apps/AppController.js +++ b/src/backend/controllers/apps/AppController.js @@ -123,7 +123,7 @@ export class AppController extends PuterController { } try { - this.clients.event?.emit( + this.clients.event?.emitAndWait( 'app.opened', { app_uid, diff --git a/src/backend/server.ts b/src/backend/server.ts index 7c73dc4f7..7263d51d0 100644 --- a/src/backend/server.ts +++ b/src/backend/server.ts @@ -124,24 +124,29 @@ export class PuterServer { this.clients = {} as typeof this.clients; for (const [clientName, ClientClass] of Object.entries(clients)) { + // @ts-expect-error as any casting to avoid overly complex or circular types this.clients[clientName] = typeof ClientClass === 'object' ? ClientClass : (new (ClientClass as any)(this.#config) as any); + // @ts-expect-error implicit any casting to avoid overly complex or circular types clientsContainers[clientName] = this.clients[clientName]; } for (const [clientName, ClientClass] of Object.entries( extensionStore.clients, )) { + // @ts-expect-error as any casting to avoid overly complex or circular types this.clients[clientName] = typeof ClientClass === 'object' ? ClientClass : (new (ClientClass as any)(this.#config) as any); + // @ts-expect-error implicit any casting to avoid overly complex or circular types clientsContainers[clientName] = this.clients[clientName]; } this.stores = {} as typeof this.stores; for (const [storeName, StoreClass] of Object.entries(stores)) { + // @ts-expect-error as any casting to avoid overly complex or circular types this.stores[storeName] = typeof StoreClass === 'object' ? StoreClass @@ -150,11 +155,13 @@ export class PuterServer { this.clients, this.stores, ) as any); + // @ts-expect-error implicit any casting to avoid overly complex or circular types storesContainers[storeName] = this.stores[storeName]; } for (const [storeName, StoreClass] of Object.entries( extensionStore.stores, )) { + // @ts-expect-error as any casting to avoid overly complex or circular types this.stores[storeName] = typeof StoreClass === 'object' ? StoreClass @@ -163,11 +170,13 @@ export class PuterServer { this.clients, this.stores, ) as any); + // @ts-expect-error implicit any casting to avoid overly complex or circular types storesContainers[storeName] = this.stores[storeName]; } this.services = {} as typeof this.services; for (const [serviceName, ServiceClass] of Object.entries(services)) { + // @ts-expect-error as any casting to avoid overly complex or circular types this.services[serviceName] = typeof ServiceClass === 'object' ? ServiceClass @@ -177,11 +186,13 @@ export class PuterServer { this.stores, this.services, ) as any); + // @ts-expect-error implicit any casting to avoid overly complex or circular types servicesContainers[serviceName] = this.services[serviceName]; } for (const [serviceName, ServiceClass] of Object.entries( extensionStore.services, )) { + // @ts-expect-error as any casting to avoid overly complex or circular types this.services[serviceName] = typeof ServiceClass === 'object' ? ServiceClass @@ -191,6 +202,7 @@ export class PuterServer { this.stores, this.services, ) as any); + // @ts-expect-error implicit any casting to avoid overly complex or circular types servicesContainers[serviceName] = this.services[serviceName]; } @@ -235,6 +247,7 @@ export class PuterServer { this.stores, this.services, ) as any); + // @ts-expect-error as any casting to avoid overly complex or circular types this.drivers[driverKey] = instance; driversContainers[driverKey] = instance; } @@ -243,6 +256,7 @@ export class PuterServer { for (const [controllerName, ControllerClass] of Object.entries( controllers, )) { + // @ts-expect-error as any casting to avoid overly complex or circular types this.controllers[controllerName] = typeof ControllerClass === 'object' ? ControllerClass @@ -255,14 +269,17 @@ export class PuterServer { ) as any); this.#registerControllerRoutes( controllerName, + // @ts-expect-error as any casting to avoid overly complex or circular types this.controllers[controllerName], ); controllersContainers[controllerName] = + // @ts-expect-error as any casting to avoid overly complex or circular types this.controllers[controllerName]; } for (const [controllerName, ControllerClass] of Object.entries( extensionStore.controllers, )) { + // @ts-expect-error as any casting to avoid overly complex or circular types this.controllers[controllerName] = typeof ControllerClass === 'object' ? ControllerClass @@ -275,26 +292,14 @@ export class PuterServer { ) as any); this.#registerControllerRoutes( controllerName, + // @ts-expect-error as any casting to avoid overly complex or circular types this.controllers[controllerName], ); controllersContainers[controllerName] = + // @ts-expect-error as any casting to avoid overly complex or circular types this.controllers[controllerName]; } - // Register extension event listeners. Extensions opted for a - // 2-arg `(data, meta)` handler shape; EventClient calls with - // `(key, data, meta)`. Drop `key` in the adapter so extension - // code stays stable. - Object.entries(extensionStore.events).forEach(([event, handlers]) => { - handlers.forEach((handler) => { - this.clients.event.on( - event, - (_key: string, data: unknown, meta: object) => - handler(data, meta), - ); - }); - }); - // Extension routes are shaped as `RouteDescriptor`s too, so they // flow through the same materializer as controller routes — same // option → middleware translation (subdomain, auth, body parsers, …). @@ -1100,16 +1105,16 @@ export class PuterServer { }); } else { this.#server = { - close: (cb) => { + close: (cb: (error?: Error) => void | undefined) => { console.debug('PuterServer mock close called'); - cb(); + cb?.(); }, closeAllConnections: () => { console.debug( 'PuterServer mock closeAllConnections called', ); }, - }; + } as unknown as http.Server; } }