UNPKG

@authup/core-realtime-kit

Version:

Package containing a toolkit for the core realtime service.

1 lines 10.7 kB
{"version":3,"file":"index.mjs","names":[],"sources":["../src/utils/url.ts","../src/client/manager/utils.ts","../src/client/manager/module.ts","../src/event/constants.ts","../src/event/helpers.ts","../src/helpers.ts"],"sourcesContent":["/*\n * Copyright (c) 2025-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function cleanDoubleSlashes(input = ''): string {\n if (input.includes('://')) {\n return input.split('://')\n .map((str) => cleanDoubleSlashes(str))\n .join('://');\n }\n\n return input.replace(/\\/+/g, '/');\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject } from '@authup/kit';\nimport type { DisconnectDescription } from '../../types';\nimport type { ClientManagerTokenFn } from './types';\n\nexport function toClientManagerTokenAsyncFn(input?: string | ClientManagerTokenFn) {\n if (typeof input === 'undefined') {\n return () => undefined;\n }\n\n if (typeof input === 'string') {\n return () => input;\n }\n\n return input;\n}\n\nexport function isDisconnectDescription(input: unknown) : input is DisconnectDescription {\n return isObject(input) &&\n typeof input.description === 'string';\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ManagerOptions, Socket } from 'socket.io-client';\nimport { Manager } from 'socket.io-client';\nimport type { CTSEvents, DefaultEvents, STCEvents } from '../../types';\nimport { cleanDoubleSlashes } from '../../utils';\nimport type { ClientManagerContext, ClientManagerTokenFn } from './types';\nimport { isDisconnectDescription, toClientManagerTokenAsyncFn } from './utils';\n\nexport class ClientManager<\n ListenEvents extends DefaultEvents = STCEvents,\n EmitEvents extends DefaultEvents = CTSEvents,\n> {\n protected manager : Manager<ListenEvents, EmitEvents>;\n\n protected sockets: Map<string, Socket<ListenEvents, EmitEvents>>;\n\n protected tokenFn : ClientManagerTokenFn;\n\n constructor(ctx: ClientManagerContext) {\n this.sockets = new Map();\n\n const url = new URL(ctx.url);\n const baseURL = `${url.protocol}//${url.host}`;\n\n const options : Partial<ManagerOptions> = { ...(ctx.options || {}) };\n\n if (options.path) {\n if (url.pathname.endsWith(options.path)) {\n options.path = url.pathname;\n } else if (url.pathname !== '/') {\n options.path = cleanDoubleSlashes(url.pathname + options.path);\n }\n } else if (url.pathname.endsWith('/socket.io')) {\n options.path = url.pathname;\n } else if (url.pathname !== '/') {\n options.path = cleanDoubleSlashes(`${url.pathname}/socket.io`);\n }\n\n this.manager = new Manager(baseURL, {\n autoConnect: false,\n ...options,\n });\n\n this.tokenFn = toClientManagerTokenAsyncFn(ctx.token);\n }\n\n get options() {\n return this.manager.opts;\n }\n\n async connect(namespace = '/') : Promise<Socket<ListenEvents, EmitEvents>> {\n const socket = this.inject(namespace);\n if (socket.connected) {\n return socket;\n }\n\n return new Promise((resolve, reject) => {\n socket.once('connect', () => {\n resolve(socket);\n });\n\n socket.once('connect_error', (err) => {\n reject(err);\n });\n\n socket.connect();\n });\n }\n\n async disconnect(namespace = '/') : Promise<void> {\n const socket = this.inject(namespace);\n if (!socket.connected) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n socket.once('disconnect', (\n reason,\n description,\n ) => {\n if (reason === 'io client disconnect') {\n resolve();\n return;\n }\n\n if (isDisconnectDescription(description)) {\n reject(new Error(description.description));\n return;\n }\n\n reject(description);\n });\n\n socket.disconnect();\n });\n }\n\n async reconnect(namespace = '/') : Promise<Socket<ListenEvents, EmitEvents>> {\n await this.disconnect(namespace);\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n this.connect(namespace)\n .then((socket) => resolve(socket))\n .catch((err) => reject(err));\n });\n });\n }\n\n async reconnectAll() : Promise<Socket<ListenEvents, EmitEvents>[]> {\n const keys = this.sockets.keys();\n const promises : Promise<Socket<ListenEvents, EmitEvents>>[] = [];\n \n while (true) {\n const key = keys.next();\n if (key.done) {\n break;\n }\n\n promises.push(this.reconnect(key.value));\n }\n\n return Promise.all(promises);\n }\n\n inject(namespace = '/') : Socket<ListenEvents, EmitEvents> {\n let socket = this.sockets.get(namespace);\n if (socket) {\n return socket;\n }\n\n socket = this.manager.socket(namespace, {\n auth: (cb: CallableFunction) => {\n Promise.resolve()\n .then(() => this.tokenFn())\n .then((token) => {\n cb({ token });\n })\n .catch(() => cb());\n },\n });\n\n this.sockets.set(namespace, socket);\n\n return socket;\n }\n\n eject(namespace = '/') {\n const socket = this.sockets.get(namespace);\n\n if (socket) {\n socket.disconnect();\n this.sockets.delete(namespace);\n }\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum EventNameSuffix {\n CREATED = 'created',\n DELETED = 'deleted',\n UPDATED = 'updated',\n\n SUBSCRIBE = 'subscribe',\n UNSUBSCRIBE = 'unsubscribe',\n}\n","/*\n * Copyright (c) 2023-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { EventFullName } from './types';\n\nexport function buildEventFullName<\n ENTITY extends string,\n VERB extends string,\n>(\n entity: ENTITY,\n event: VERB,\n) : EventFullName<ENTITY, VERB> {\n const eventCapitalized = event.substring(0, 1).toUpperCase() + event.substring(1);\n\n return entity + eventCapitalized as EventFullName<ENTITY, VERB>;\n}\n","/*\n * Copyright (c) 2021-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { EventCallback, EventTarget } from './types';\n\nexport function isEventTarget(\n input: unknown,\n) : input is EventTarget {\n return typeof input === 'number' ||\n typeof input === 'string' ||\n typeof input === 'undefined';\n}\n\nexport function isEventCallback(\n input: unknown,\n fnArgs?: number,\n) : input is EventCallback {\n if (typeof fnArgs === 'undefined') {\n return typeof input === 'function';\n }\n\n return typeof input === 'function' &&\n input.length >= fnArgs;\n}\n"],"mappings":";;;AAOA,SAAgB,mBAAmB,QAAQ,IAAY;AACnD,KAAI,MAAM,SAAS,MAAM,CACrB,QAAO,MAAM,MAAM,MAAM,CACpB,KAAK,QAAQ,mBAAmB,IAAI,CAAC,CACrC,KAAK,MAAM;AAGpB,QAAO,MAAM,QAAQ,QAAQ,IAAI;;;;ACHrC,SAAgB,4BAA4B,OAAuC;AAC/E,KAAI,OAAO,UAAU,YACjB,cAAa,KAAA;AAGjB,KAAI,OAAO,UAAU,SACjB,cAAa;AAGjB,QAAO;;AAGX,SAAgB,wBAAwB,OAAiD;AACrF,QAAO,SAAS,MAAM,IAClB,OAAO,MAAM,gBAAgB;;;;ACXrC,IAAa,gBAAb,MAGE;CACE;CAEA;CAEA;CAEA,YAAY,KAA2B;AACnC,OAAK,0BAAU,IAAI,KAAK;EAExB,MAAM,MAAM,IAAI,IAAI,IAAI,IAAI;EAC5B,MAAM,UAAU,GAAG,IAAI,SAAS,IAAI,IAAI;EAExC,MAAM,UAAoC,EAAE,GAAI,IAAI,WAAW,EAAE,EAAG;AAEpE,MAAI,QAAQ;OACJ,IAAI,SAAS,SAAS,QAAQ,KAAK,CACnC,SAAQ,OAAO,IAAI;YACZ,IAAI,aAAa,IACxB,SAAQ,OAAO,mBAAmB,IAAI,WAAW,QAAQ,KAAK;aAE3D,IAAI,SAAS,SAAS,aAAa,CAC1C,SAAQ,OAAO,IAAI;WACZ,IAAI,aAAa,IACxB,SAAQ,OAAO,mBAAmB,GAAG,IAAI,SAAS,YAAY;AAGlE,OAAK,UAAU,IAAI,QAAQ,SAAS;GAChC,aAAa;GACb,GAAG;GACN,CAAC;AAEF,OAAK,UAAU,4BAA4B,IAAI,MAAM;;CAGzD,IAAI,UAAU;AACV,SAAO,KAAK,QAAQ;;CAGxB,MAAM,QAAQ,YAAY,KAAiD;EACvE,MAAM,SAAS,KAAK,OAAO,UAAU;AACrC,MAAI,OAAO,UACP,QAAO;AAGX,SAAO,IAAI,SAAS,SAAS,WAAW;AACpC,UAAO,KAAK,iBAAiB;AACzB,YAAQ,OAAO;KACjB;AAEF,UAAO,KAAK,kBAAkB,QAAQ;AAClC,WAAO,IAAI;KACb;AAEF,UAAO,SAAS;IAClB;;CAGN,MAAM,WAAW,YAAY,KAAqB;EAC9C,MAAM,SAAS,KAAK,OAAO,UAAU;AACrC,MAAI,CAAC,OAAO,UACR;AAGJ,QAAM,IAAI,SAAe,SAAS,WAAW;AACzC,UAAO,KAAK,eACR,QACA,gBACC;AACD,QAAI,WAAW,wBAAwB;AACnC,cAAS;AACT;;AAGJ,QAAI,wBAAwB,YAAY,EAAE;AACtC,YAAO,IAAI,MAAM,YAAY,YAAY,CAAC;AAC1C;;AAGJ,WAAO,YAAY;KACrB;AAEF,UAAO,YAAY;IACrB;;CAGN,MAAM,UAAU,YAAY,KAAiD;AACzE,QAAM,KAAK,WAAW,UAAU;AAChC,SAAO,IAAI,SAAS,SAAS,WAAW;AACpC,oBAAiB;AACb,SAAK,QAAQ,UAAU,CAClB,MAAM,WAAW,QAAQ,OAAO,CAAC,CACjC,OAAO,QAAQ,OAAO,IAAI,CAAC;KAClC;IACJ;;CAGN,MAAM,eAA6D;EAC/D,MAAM,OAAO,KAAK,QAAQ,MAAM;EAChC,MAAM,WAAyD,EAAE;AAEjE,SAAO,MAAM;GACT,MAAM,MAAM,KAAK,MAAM;AACvB,OAAI,IAAI,KACJ;AAGJ,YAAS,KAAK,KAAK,UAAU,IAAI,MAAM,CAAC;;AAG5C,SAAO,QAAQ,IAAI,SAAS;;CAGhC,OAAO,YAAY,KAAwC;EACvD,IAAI,SAAS,KAAK,QAAQ,IAAI,UAAU;AACxC,MAAI,OACA,QAAO;AAGX,WAAS,KAAK,QAAQ,OAAO,WAAW,EACpC,OAAO,OAAyB;AAC5B,WAAQ,SAAS,CACZ,WAAW,KAAK,SAAS,CAAC,CAC1B,MAAM,UAAU;AACb,OAAG,EAAE,OAAO,CAAC;KACf,CACD,YAAY,IAAI,CAAC;KAE7B,CAAC;AAEF,OAAK,QAAQ,IAAI,WAAW,OAAO;AAEnC,SAAO;;CAGX,MAAM,YAAY,KAAK;EACnB,MAAM,SAAS,KAAK,QAAQ,IAAI,UAAU;AAE1C,MAAI,QAAQ;AACR,UAAO,YAAY;AACnB,QAAK,QAAQ,OAAO,UAAU;;;;;;ACtJ1C,IAAY,kBAAL,yBAAA,iBAAA;AACH,iBAAA,aAAA;AACA,iBAAA,aAAA;AACA,iBAAA,aAAA;AAEA,iBAAA,eAAA;AACA,iBAAA,iBAAA;;KACH;;;ACLD,SAAgB,mBAIZ,QACA,OAC4B;AAG5B,QAAO,UAFkB,MAAM,UAAU,GAAG,EAAE,CAAC,aAAa,GAAG,MAAM,UAAU,EAAE;;;;ACPrF,SAAgB,cACZ,OACqB;AACrB,QAAO,OAAO,UAAU,YACpB,OAAO,UAAU,YACjB,OAAO,UAAU;;AAGzB,SAAgB,gBACZ,OACA,QACuB;AACvB,KAAI,OAAO,WAAW,YAClB,QAAO,OAAO,UAAU;AAG5B,QAAO,OAAO,UAAU,cACpB,MAAM,UAAU"}