Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@elysiajs/websocket

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@elysiajs/websocket - npm Package Compare versions

Comparing version 0.1.1 to 0.2.0

18

dist/index.d.ts

@@ -1,3 +0,17 @@

import type { WebSocketHandler } from 'bun';
import { Elysia } from 'elysia';
/// <reference types="bun-types" />
import type { ServerWebSocket, WebSocketHandler } from 'bun';
import { Elysia, type TypedSchema, UnwrapSchema } from 'elysia';
import type { ElysiaWSContext } from './types';
export declare class ElysiaWS<WS extends ElysiaWSContext<any> = ElysiaWSContext, Schema extends TypedSchema = TypedSchema> {
raw: WS;
data: WS['data'];
isSubscribed: WS['isSubscribed'];
constructor(ws: WS);
publish(topic: string, data: UnwrapSchema<Schema['response']>, compress?: boolean): this;
send(data: UnwrapSchema<Schema['response']>): this;
subscribe(room: string): this;
unsubscribe(room: string): this;
cork(callback: (ws: ServerWebSocket<any>) => any): this;
close(): this;
}
export declare const websocket: (config?: Omit<WebSocketHandler, 'open' | 'message' | 'close' | 'drain'>) => (app: Elysia) => Elysia<import("elysia").ElysiaInstance<{

@@ -4,0 +18,0 @@ store: Record<typeof import("elysia").SCHEMA, {}>;

82

dist/index.js
import { Elysia, getPath, Router, createValidationError, getSchemaValidator } from 'elysia';
import { nanoid } from 'nanoid';
export class ElysiaWS {
constructor(ws) {
this.raw = ws;
this.data = ws.data;
this.isSubscribed = ws.isSubscribed;
}
publish(topic, data, compress) {
if (typeof data === 'object')
data = JSON.stringify(data);
this.raw.publish(topic, data, compress);
return this;
}
send(data) {
if (typeof data === 'object')
data = JSON.stringify(data);
this.raw.send(data);
return this;
}
subscribe(room) {
this.raw.subscribe(room);
return this;
}
unsubscribe(room) {
this.raw.unsubscribe(room);
return this;
}
cork(callback) {
this.raw.cork(callback);
return this;
}
close() {
this.raw.close();
return this;
}
}
export const websocket = (config) => (app) => {
app.websocketRouter = new Router();
if (!app.websocketRouter)
app.websocketRouter = new Router();
if (!app.config.serve)

@@ -12,5 +48,7 @@ app.config.serve = {

return;
const route = app.websocketRouter.find(getPath((ws?.data).request.url), (ws?.data).request.url.indexOf('?'))?.store['ws'];
const url = (ws?.data).request.url;
const index = url.indexOf('?');
const route = app.websocketRouter.find(getPath(url, index), index)?.store['subscribe'];
if (route && route.open)
route.open(ws);
route.open(new ElysiaWS(ws));
},

@@ -20,5 +58,10 @@ message(ws, message) {

return;
const route = app.websocketRouter.find(getPath((ws?.data).request.url), (ws?.data).request.url.indexOf('?'))?.store['ws'];
if (route && route.message) {
message = message.toString();
const url = (ws?.data).request.url;
const index = url.indexOf('?');
const route = app.websocketRouter.find(getPath(url, index), index)?.store['subscribe'];
if (!route?.message)
return;
message = message.toString();
const start = message.charCodeAt(0);
if (start === 47 || start === 123)
try {

@@ -28,9 +71,6 @@ message = JSON.parse(message);

catch (error) { }
if (ws.data.message &&
ws.data.message?.Check(message))
return void ws.send(createValidationError('message', ws.data
.message, message).cause);
route.message(ws, message);
}
return undefined;
if (ws.data.message?.Check(message) === false)
return void route.message(createValidationError('message', ws.data
.message, message).cause);
route.message(new ElysiaWS(ws), message);
},

@@ -41,5 +81,7 @@ close(ws, code, reason) {

const queryIndex = (ws?.data).request.url.indexOf('?');
const route = app.websocketRouter.find(getPath((ws?.data).request.url), queryIndex)?.store['ws'];
const url = (ws?.data).request.url;
const index = url.indexOf('?');
const route = app.websocketRouter.find(getPath(url, index), index)?.store['subscribe'];
if (route && route.close)
route.close(ws, code, reason);
route.close(new ElysiaWS(ws), code, reason);
},

@@ -49,5 +91,7 @@ drain(ws) {

return;
const route = app.websocketRouter.find(getPath((ws?.data).request.url), (ws?.data).request.url.indexOf('?'))?.store['ws'];
const url = (ws?.data).request.url;
const index = url.indexOf('?');
const route = app.websocketRouter.find(getPath(url, index), index)?.store['subscribe'];
if (route && route.drain)
route.drain(ws);
route.drain(new ElysiaWS(ws));
}

@@ -60,4 +104,4 @@ }

if (!this.websocketRouter)
throw new Error("Can't find WebSocket. Please register WebSocket plugin first");
this.websocketRouter.register(path)['ws'] = options;
this.websocketRouter = new Router();
this.websocketRouter.register(path)['subscribe'] = options;
return this.get(path, (context) => {

@@ -64,0 +108,0 @@ if (this.server.upgrade(context.request, {

@@ -7,2 +7,3 @@ /// <reference types="bun-types" />

import type { TypeCheck } from '@sinclair/typebox/compiler';
import { ElysiaWS } from '.';
export declare type WebSocketSchemaToRoute<Schema extends TypedSchema> = {

@@ -15,3 +16,3 @@ body: UnwrapSchema<Schema['body']> extends Record<string, any> ? UnwrapSchema<Schema['body']> : undefined;

};
export declare type ElysiaWebSocket<Schema extends TypedSchema = TypedSchema, Path extends string = string> = ServerWebSocket<Context<ExtractPath<Path> extends never ? WebSocketSchemaToRoute<Schema> : Omit<WebSocketSchemaToRoute<Schema>, 'params'> & {
export declare type ElysiaWSContext<Schema extends TypedSchema = TypedSchema, Path extends string = string> = ServerWebSocket<Context<ExtractPath<Path> extends never ? WebSocketSchemaToRoute<Schema> : Omit<WebSocketSchemaToRoute<Schema>, 'params'> & {
params: Record<ExtractPath<Path>, string>;

@@ -37,8 +38,8 @@ }> & {

headers?: HeadersInit | WebSocketHeaderHandler<Schema>;
open?: (ws: ElysiaWebSocket<Schema, Path>) => void | Promise<void>;
message?: (ws: ElysiaWebSocket<Schema, Path>, message: Schema['body'] extends NonNullable<Schema['body']> ? Static<NonNullable<Schema['body']>> : string) => any;
close?: (ws: ElysiaWebSocket<Schema, Path>) => any;
drain?: (ws: ElysiaWebSocket<Schema, Path>, code: number, reason: string) => any;
open?: (ws: ElysiaWS<ElysiaWSContext<Schema, Path>, Schema>) => void | Promise<void>;
message?: (ws: ElysiaWS<ElysiaWSContext<Schema, Path>, Schema>, message: Schema['body'] extends NonNullable<Schema['body']> ? Static<NonNullable<Schema['body']>> : string) => any;
close?: (ws: ElysiaWS<ElysiaWSContext<Schema, Path>, Schema>) => any;
drain?: (ws: ElysiaWS<ElysiaWSContext<Schema, Path>, Schema>, code: number, reason: string) => any;
}): Instance extends Elysia<infer Instance> ? ElysiaRoute<'subscribe', Schema, Instance, Path, Schema['response']> : this;
}
}
{
"name": "@elysiajs/websocket",
"version": "0.1.1",
"version": "0.2.0",
"description": "Plugin for Elysia that add support for websocket",

@@ -5,0 +5,0 @@ "author": {

@@ -1,2 +0,2 @@

import type { WebSocketHandler } from 'bun'
import type { ServerWebSocket, WebSocketHandler } from 'bun'

@@ -9,3 +9,5 @@ import {

getSchemaValidator,
type Context
type Context,
type TypedSchema,
UnwrapSchema
} from 'elysia'

@@ -15,4 +17,65 @@ import { nanoid } from 'nanoid'

import type { TSchema } from '@sinclair/typebox'
import type { ElysiaWebSocket } from './types'
import type { ElysiaWSContext } from './types'
export class ElysiaWS<
WS extends ElysiaWSContext<any> = ElysiaWSContext,
Schema extends TypedSchema = TypedSchema
> {
raw: WS
data: WS['data']
isSubscribed: WS['isSubscribed']
constructor(ws: WS) {
this.raw = ws
this.data = ws.data
this.isSubscribed = ws.isSubscribed
}
publish(
topic: string,
data: UnwrapSchema<Schema['response']>,
compress?: boolean
) {
// @ts-ignore
if (typeof data === 'object') data = JSON.stringify(data)
this.raw.publish(topic, data as string, compress)
return this
}
send(data: UnwrapSchema<Schema['response']>) {
// @ts-ignore
if (typeof data === 'object') data = JSON.stringify(data)
this.raw.send(data as string)
return this
}
subscribe(room: string) {
this.raw.subscribe(room)
return this
}
unsubscribe(room: string) {
this.raw.unsubscribe(room)
return this
}
cork(callback: (ws: ServerWebSocket<any>) => any) {
this.raw.cork(callback)
return this
}
close() {
this.raw.close()
return this
}
}
/**

@@ -38,3 +101,3 @@ * Register websocket config for Elysia

(app: Elysia) => {
app.websocketRouter = new Router()
if (!app.websocketRouter) app.websocketRouter = new Router()

@@ -48,28 +111,30 @@ if (!app.config.serve)

const url = (ws?.data as unknown as Context).request.url
const index = url.indexOf('?')
const route = app.websocketRouter.find(
getPath(
(ws?.data as unknown as Context).request.url
),
(
ws?.data as unknown as Context
).request.url.indexOf('?')
)?.store['ws']
getPath(url, index),
index
)?.store['subscribe']
if (route && route.open) route.open(ws)
if (route && route.open)
route.open(new ElysiaWS(ws as any))
},
message(ws, message) {
message(ws, message): void {
if (!ws.data) return
const url = (ws?.data as unknown as Context).request.url
const index = url.indexOf('?')
const route = app.websocketRouter.find(
getPath(
(ws?.data as unknown as Context).request.url
),
(
ws?.data as unknown as Context
).request.url.indexOf('?')
)?.store['ws']
getPath(url, index),
index
)?.store['subscribe']
if (route && route.message) {
message = message.toString()
if (!route?.message) return
message = message.toString()
const start = message.charCodeAt(0)
if (start === 47 || start === 123)
try {

@@ -79,22 +144,17 @@ message = JSON.parse(message)

if (
(ws.data as ElysiaWebSocket['data']).message &&
(
ws.data as ElysiaWebSocket['data']
).message?.Check(message)
if (
(ws.data as ElysiaWSContext['data']).message?.Check(
message
) === false
)
return void route.message(
createValidationError(
'message',
(ws.data as ElysiaWSContext['data'])
.message,
message
).cause as string
)
return void ws.send(
createValidationError(
'message',
(ws.data as ElysiaWebSocket['data'])
.message,
message
).cause as string
)
route.message(ws, message)
}
// ? noImplicitReturns
return undefined
route.message(new ElysiaWS(ws as any), message)
},

@@ -108,10 +168,12 @@ close(ws, code, reason) {

const url = (ws?.data as unknown as Context).request.url
const index = url.indexOf('?')
const route = app.websocketRouter.find(
getPath(
(ws?.data as unknown as Context).request.url
),
queryIndex
)?.store['ws']
getPath(url, index),
index
)?.store['subscribe']
if (route && route.close) route.close(ws, code, reason)
if (route && route.close)
route.close(new ElysiaWS(ws as any), code, reason)
},

@@ -121,12 +183,12 @@ drain(ws) {

const url = (ws?.data as unknown as Context).request.url
const index = url.indexOf('?')
const route = app.websocketRouter.find(
getPath(
(ws?.data as unknown as Context).request.url
),
(
ws?.data as unknown as Context
).request.url.indexOf('?')
)?.store['ws']
getPath(url, index),
index
)?.store['subscribe']
if (route && route.drain) route.drain(ws)
if (route && route.drain)
route.drain(new ElysiaWS(ws as any))
}

@@ -141,8 +203,5 @@ }

Elysia.prototype.ws = function (path, options) {
if (!this.websocketRouter)
throw new Error(
"Can't find WebSocket. Please register WebSocket plugin first"
)
if (!this.websocketRouter) this.websocketRouter = new Router()
this.websocketRouter.register(path)['ws'] = options
this.websocketRouter.register(path)['subscribe'] = options

@@ -162,3 +221,3 @@ return this.get(

message: getSchemaValidator(options.schema?.body)
} as ElysiaWebSocket['data']
} as ElysiaWSContext['data']
})

@@ -165,0 +224,0 @@ )

@@ -21,2 +21,3 @@ import type { ServerWebSocket, WebSocketHandler } from 'bun'

import type { TypeCheck } from '@sinclair/typebox/compiler'
import { ElysiaWS } from '.'

@@ -41,3 +42,3 @@ export type WebSocketSchemaToRoute<Schema extends TypedSchema> = {

export type ElysiaWebSocket<
export type ElysiaWSContext<
Schema extends TypedSchema = TypedSchema,

@@ -112,3 +113,3 @@ Path extends string = string

open?: (
ws: ElysiaWebSocket<Schema, Path>
ws: ElysiaWS<ElysiaWSContext<Schema, Path>, Schema>
) => void | Promise<void>

@@ -125,3 +126,3 @@

message?: (
ws: ElysiaWebSocket<Schema, Path>,
ws: ElysiaWS<ElysiaWSContext<Schema, Path>, Schema>,
message: Schema['body'] extends NonNullable<Schema['body']>

@@ -138,3 +139,5 @@ ? Static<NonNullable<Schema['body']>>

*/
close?: (ws: ElysiaWebSocket<Schema, Path>) => any
close?: (
ws: ElysiaWS<ElysiaWSContext<Schema, Path>, Schema>
) => any

@@ -147,3 +150,3 @@ /**

drain?: (
ws: ElysiaWebSocket<Schema, Path>,
ws: ElysiaWS<ElysiaWSContext<Schema, Path>, Schema>,
code: number,

@@ -154,5 +157,11 @@ reason: string

): Instance extends Elysia<infer Instance>
? ElysiaRoute<'subscribe', Schema, Instance, Path, Schema['response']>
? ElysiaRoute<
'subscribe',
Schema,
Instance,
Path,
Schema['response']
>
: this
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc