@bakit/service 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -22,6 +22,7 @@ interface BaseClientDriver extends EventBus<BaseClientDriverEvents> {
22
22
  send(message: Serializable): void;
23
23
  connect(): void;
24
24
  disconnect(): void;
25
+ readonly ready: boolean;
25
26
  }
26
27
 
27
28
  interface BaseServerDriver extends EventBus<BaseServerDriverEvents> {
@@ -85,6 +86,7 @@ interface IPCSocketConnection extends EventBus<IPCClientEvents>, IPCSocketMessag
85
86
  reconnect: () => void;
86
87
  write: (chunk: Buffer) => void;
87
88
  readonly state: SocketState;
89
+ readonly ready: boolean;
88
90
  }
89
91
  interface IPCSocketMessageHandler extends BaseClientDriver {
90
92
  handleData: (chunk: Buffer) => void;
@@ -166,6 +168,7 @@ interface TransportClient extends TransportClientProtocol, EventBus<TransportCli
166
168
  send: BaseServerDriver["send"];
167
169
  connect: BaseClientDriver["connect"];
168
170
  disconnect: BaseClientDriver["disconnect"];
171
+ readonly ready: boolean;
169
172
  }
170
173
  interface TransportServer extends TransportServerProtocol, EventBus<TransportServerEvents> {
171
174
  broadcast: BaseServerDriver["broadcast"];
@@ -217,29 +220,37 @@ interface ServiceOptions {
217
220
  interface Service {
218
221
  readonly name: string;
219
222
  readonly role: ServiceRole;
223
+ initialize?: FunctionLike<[], Awaitable<void>>;
224
+ onReady?: FunctionLike<[], Awaitable<void>>;
220
225
  define<F extends ServiceFunction>(method: string, handler: F): Promisify<F>;
221
226
  }
222
227
  type ServiceFunction = FunctionLike<any[], Awaitable<any>>;
223
228
  declare const ServiceRole: {
224
229
  readonly Client: "client";
225
230
  readonly Server: "server";
226
- readonly Unknown: "unknown";
227
231
  };
228
232
  type ServiceRole = ValueOf<typeof ServiceRole>;
229
- type ServiceRuntime = {
230
- role: "unknown";
231
- } | {
232
- role: "client";
233
+ interface ServiceClientRuntime {
234
+ role: typeof ServiceRole.Client;
233
235
  transport: TransportClient;
234
- } | {
235
- role: "server";
236
+ }
237
+ interface ServiceServerRuntime {
238
+ role: typeof ServiceRole.Server;
236
239
  transport: TransportServer;
237
- };
240
+ }
241
+ type ServiceRuntime = ServiceClientRuntime | ServiceServerRuntime;
242
+ interface MutableRuntime {
243
+ role: ServiceRole | "unknown";
244
+ transport?: TransportClient | TransportServer;
245
+ }
238
246
  interface ServiceInteral {
239
247
  runtime: ServiceRuntime;
240
248
  bind(role: "client" | "server"): void;
241
249
  }
242
250
  declare function createService(options: ServiceOptions): Service;
243
- declare function getInteralService(service: Service): ServiceInteral;
251
+ declare function startServiceServer(service: Service): Promise<void>;
252
+ declare function assertRuntimeClient(service: Service, runtime: MutableRuntime): asserts runtime is ServiceClientRuntime;
253
+ declare function assertRuntimeServer(service: Service, runtime: MutableRuntime): asserts runtime is ServiceServerRuntime;
254
+ declare function getInternalService(service: Service): ServiceInteral;
244
255
 
245
- export { type BaseClientDriver, type BaseClientDriverEvents, type BaseServerDriver, type BaseServerDriverEvents, DEFAULT_IPC_SOCKET_CONNECTION_OPTIONS, type IPCClientEvents, type IPCClientOptions, type IPCServer, type IPCServerEvents, type IPCServerOptions, IPCServerState, type IPCSocketConnection, type IPCSocketConnectionOptions, type IPCSocketMessageHandler, type IPCSocketMessageHandlerOptions, RPCError, type RPCErrorPayload, type RPCHandler, type RPCRequestMessage, type RPCResponseMessage, type Serializable, type Service, type ServiceFunction, type ServiceInteral, type ServiceOptions, ServiceRole, type ServiceRuntime, SocketState, type TransportClient, type TransportClientDriverSpecificOptions, type TransportClientEvents, type TransportClientOptions, type TransportClientProtocol, TransportDriver, type TransportServer, type TransportServerDriverSpecificOptions, type TransportServerEvents, type TransportServerOptions, type TransportServerProtocol, createIPCClient, createIPCServer, createIPCSocketConnection, createIPCSocketMessageHandler, createService, createTransportClient, createTransportClientProtocol, createTransportServer, createTransportServerProtocol, deserializeRPCError, getIPCPath, getInteralService, serializeRPCError };
256
+ export { type BaseClientDriver, type BaseClientDriverEvents, type BaseServerDriver, type BaseServerDriverEvents, DEFAULT_IPC_SOCKET_CONNECTION_OPTIONS, type IPCClientEvents, type IPCClientOptions, type IPCServer, type IPCServerEvents, type IPCServerOptions, IPCServerState, type IPCSocketConnection, type IPCSocketConnectionOptions, type IPCSocketMessageHandler, type IPCSocketMessageHandlerOptions, type MutableRuntime, RPCError, type RPCErrorPayload, type RPCHandler, type RPCRequestMessage, type RPCResponseMessage, type Serializable, type Service, type ServiceClientRuntime, type ServiceFunction, type ServiceInteral, type ServiceOptions, ServiceRole, type ServiceRuntime, type ServiceServerRuntime, SocketState, type TransportClient, type TransportClientDriverSpecificOptions, type TransportClientEvents, type TransportClientOptions, type TransportClientProtocol, TransportDriver, type TransportServer, type TransportServerDriverSpecificOptions, type TransportServerEvents, type TransportServerOptions, type TransportServerProtocol, assertRuntimeClient, assertRuntimeServer, createIPCClient, createIPCServer, createIPCSocketConnection, createIPCSocketMessageHandler, createService, createTransportClient, createTransportClientProtocol, createTransportServer, createTransportServerProtocol, deserializeRPCError, getIPCPath, getInternalService, serializeRPCError, startServiceServer };
package/dist/index.js CHANGED
@@ -104,6 +104,9 @@ function createIPCSocketConnection(socketPath, options = {}) {
104
104
  write,
105
105
  get state() {
106
106
  return state;
107
+ },
108
+ get ready() {
109
+ return state === SocketState.Connected;
107
110
  }
108
111
  });
109
112
  function connect() {
@@ -239,7 +242,10 @@ function createTransportClient(options) {
239
242
  ...createTransportClientProtocol(driver),
240
243
  send: driver.send,
241
244
  connect: driver.connect,
242
- disconnect: driver.disconnect
245
+ disconnect: driver.disconnect,
246
+ get ready() {
247
+ return driver.ready;
248
+ }
243
249
  }, self = attachEventBus(base);
244
250
  return driver.on("connect", () => self.emit("connect")), driver.on("disconnect", () => self.emit("disconnect")), driver.on("error", (error) => self.emit("error", error)), self;
245
251
  }
@@ -343,8 +349,7 @@ function createTransportServerProtocol(driver) {
343
349
  }
344
350
  var ServiceRole = {
345
351
  Client: "client",
346
- Server: "server",
347
- Unknown: "unknown"
352
+ Server: "server"
348
353
  }, SERVICE_INTERNAL = Symbol("service-internal");
349
354
  function createService(options) {
350
355
  let handlers = new Collection(), runtime = { role: "unknown" }, service = {
@@ -352,6 +357,8 @@ function createService(options) {
352
357
  return options.name;
353
358
  },
354
359
  get role() {
360
+ if (runtime.role === "unknown")
361
+ throw new Error(`Service "${options.name}" is not bound`);
355
362
  return runtime.role;
356
363
  },
357
364
  define
@@ -360,11 +367,14 @@ function createService(options) {
360
367
  if (handlers.has(method))
361
368
  throw new Error(`Service method "${method}" already defined`);
362
369
  return handlers.set(method, handler), (async (...args) => {
363
- if (runtime.role === "unknown")
370
+ if (ensureClientBound(), runtime.role === "unknown")
364
371
  throw new Error(`Service "${options.name}" is not bound (method "${method}")`);
365
- return runtime.role === "server" ? handler(...args) : runtime.transport.request(method, ...args);
372
+ return runtime.role === "server" ? handler(...args) : (assertRuntimeClient(service, runtime), runtime.transport.request(method, ...args));
366
373
  });
367
374
  }
375
+ function ensureClientBound() {
376
+ runtime.role !== "unknown" || process.env.BAKIT_SERVICE_NAME === options.name || (bind(ServiceRole.Client), assertRuntimeClient(service, runtime), runtime.transport.ready || runtime.transport.connect());
377
+ }
368
378
  function bind(role) {
369
379
  if (runtime.role !== "unknown")
370
380
  throw new Error(`Service "${options.name}" already bound`);
@@ -372,29 +382,41 @@ function createService(options) {
372
382
  let server = createTransportServer(options.transport);
373
383
  for (let [method, handler] of handlers)
374
384
  server.handle(method, handler);
375
- runtime = {
376
- role,
377
- transport: server
378
- }, server.listen();
385
+ runtime.role = "server", runtime.transport = server;
379
386
  } else if (role === "client") {
380
387
  let client = createTransportClient(options.transport);
381
- runtime = {
382
- role,
383
- transport: client
384
- }, client.connect();
388
+ runtime.role = "client", runtime.transport = client;
385
389
  }
386
390
  }
387
391
  return Object.defineProperty(service, SERVICE_INTERNAL, {
388
392
  value: {
389
393
  get runtime() {
394
+ if (runtime.role === "unknown")
395
+ throw new Error(`Service "${options.name}" is not bound`);
390
396
  return runtime;
391
397
  },
392
398
  bind
393
399
  }
394
400
  }), service;
395
401
  }
396
- function getInteralService(service) {
402
+ async function startServiceServer(service) {
403
+ let internal = getInternalService(service);
404
+ return internal.bind(ServiceRole.Server), await service.initialize?.(), await new Promise((resolve) => {
405
+ assertRuntimeServer(service, internal.runtime), internal.runtime.transport.once("listen", async () => {
406
+ resolve(), await service.onReady?.();
407
+ }), internal.runtime.transport.listen();
408
+ });
409
+ }
410
+ function assertRuntimeClient(service, runtime) {
411
+ if (runtime.role !== "client")
412
+ throw new Error(`Service "${service.name}" is not a client`);
413
+ }
414
+ function assertRuntimeServer(service, runtime) {
415
+ if (runtime.role !== "server")
416
+ throw new Error(`Service "${service.name}" is not a server`);
417
+ }
418
+ function getInternalService(service) {
397
419
  return service[SERVICE_INTERNAL];
398
420
  }
399
421
 
400
- export { DEFAULT_IPC_SOCKET_CONNECTION_OPTIONS, IPCServerState, RPCError, ServiceRole, SocketState, TransportDriver, createIPCClient, createIPCServer, createIPCSocketConnection, createIPCSocketMessageHandler, createService, createTransportClient, createTransportClientProtocol, createTransportServer, createTransportServerProtocol, deserializeRPCError, getIPCPath, getInteralService, serializeRPCError };
422
+ export { DEFAULT_IPC_SOCKET_CONNECTION_OPTIONS, IPCServerState, RPCError, ServiceRole, SocketState, TransportDriver, assertRuntimeClient, assertRuntimeServer, createIPCClient, createIPCServer, createIPCSocketConnection, createIPCSocketMessageHandler, createService, createTransportClient, createTransportClientProtocol, createTransportServer, createTransportServerProtocol, deserializeRPCError, getIPCPath, getInternalService, serializeRPCError, startServiceServer };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bakit/service",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "description": "Service manager for bakit framework",
5
5
  "type": "module",
6
6
  "exports": {