@elysiajs/eden
Advanced tools
Comparing version 0.1.0 to 0.2.0-rc.0
@@ -1,3 +0,15 @@ | ||
import type { Elysia } from 'elysia'; | ||
import { Eden } from './types'; | ||
/// <reference types="bun-types" /> | ||
import type { Elysia, TypedSchema } from 'elysia'; | ||
import type { Eden, EdenWSEvent } from './types'; | ||
export declare class EdenWS<Schema extends TypedSchema<any> = TypedSchema> { | ||
ws: WebSocket; | ||
url: string; | ||
constructor(url: string); | ||
send(data: Schema['body'] | Schema['body'][]): this; | ||
on<K extends keyof WebSocketEventMap>(type: K, listener: (event: EdenWSEvent<K, Schema['response']>) => void, options?: boolean | AddEventListenerOptions): this; | ||
off<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, options?: boolean | EventListenerOptions): this; | ||
addEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (event: EdenWSEvent<K, Schema['response']>) => void, options?: boolean | AddEventListenerOptions): this; | ||
removeEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, options?: boolean | EventListenerOptions): this; | ||
close(): this; | ||
} | ||
export declare const eden: <App extends Elysia<any>>(domain: string) => Eden<App>; |
@@ -1,1 +0,1 @@ | ||
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=t=>t.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),y=(t,e,r)=>{if(t.endsWith("/")||(t+="/"),e=g(e.replace(/index/g,"")),!r||!Object.keys(r).length)return`${t}${e}`;let n="";for(const[a,o]of Object.entries(r))n+=`${a}=${o}&`;return`${t}${e}?${n.slice(0,-1)}`},u=(t,e="")=>new Proxy(()=>{},{get(r,n,a){return u(t,`${e}/${n.toString()}`)},apply(r,n,[{$query:a,$fetch:o,...c}={$fetch:void 0,$query:void 0}]=[{}]){const l=e.lastIndexOf("/");return fetch(y(t,e.slice(0,l),a),{method:e.slice(l+1),headers:{"content-type":"application/json",...o==null?void 0:o.headers},body:Object.keys(c).length?JSON.stringify(c):void 0,...o}).then(async s=>{if(s.status>=300)throw new Error(await s.text());if(s.headers.get("content-type")==="application/json")return s.json();const i=await s.text();return Number.isNaN(+i)?i==="true"?!0:i==="false"?!1:i:+i})}}),f=t=>new Proxy({},{get(e,r,n){return u(t,r)}});exports.eden=f; | ||
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class d{constructor(e){this.ws=new WebSocket(e),this.url=e}send(e){return Array.isArray(e)?(e.forEach(t=>this.send(t)),this):(this.ws.send(typeof e=="object"?JSON.stringify(e):e.toString()),this)}on(e,t,s){return this.addEventListener(e,t,s)}off(e,t,s){return this.ws.removeEventListener(e,t,s),this}addEventListener(e,t,s){return this.ws.addEventListener(e,i=>{if(e==="message"){let r=i.data.toString();const o=r.charCodeAt(0);if(o===47||o===123)try{r=JSON.parse(r)}catch{}else Number.isNaN(+r)?r==="true"?r=!0:r==="fase"&&(r=!1):r=+r;t({...i,data:r})}else t(i)},s),this}removeEventListener(e,t,s){return this.off(e,t,s),this}close(){return this.ws.close(),this}}const g=n=>n.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),y=(n,e,t)=>{if(n.endsWith("/")||(n+="/"),e=g(e.replace(/index/g,"")),!t||!Object.keys(t).length)return`${n}${e}`;let s="";for(const[i,r]of Object.entries(t))s+=`${i}=${r}&`;return`${n}${e}?${s.slice(0,-1)}`},h=(n,e="")=>new Proxy(()=>{},{get(t,s,i){return h(n,`${e}/${s.toString()}`)},apply(t,s,[{$query:i,$fetch:r,...o}={$fetch:void 0,$query:void 0}]=[{}]){const u=e.lastIndexOf("/"),l=e.slice(u+1),f=y(n,e.slice(0,u),i);return l==="subscribe"?new d(f.replace(/^([^]+):\/\//,"ws://")):fetch(f,{method:l,headers:{"content-type":"application/json",...r==null?void 0:r.headers},body:Object.keys(o).length?JSON.stringify(o):void 0,...r}).then(async c=>{if(c.status>=300)throw new Error(await c.text());if(c.headers.get("content-type")==="application/json")return c.json();const a=await c.text();return Number.isNaN(+a)?a==="true"?!0:a==="false"?!1:a:+a})}}),v=n=>new Proxy({},{get(e,t,s){return h(n,t)}});exports.EdenWS=d;exports.eden=v; |
@@ -1,1 +0,1 @@ | ||
(function(r,s){typeof exports=="object"&&typeof module<"u"?s(exports):typeof define=="function"&&define.amd?define(["exports"],s):(r=typeof globalThis<"u"?globalThis:r||self,s(r["@elysia/eden"]={}))})(this,function(r){"use strict";const s=t=>t.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),y=(t,e,n)=>{if(t.endsWith("/")||(t+="/"),e=s(e.replace(/index/g,"")),!n||!Object.keys(n).length)return`${t}${e}`;let o="";for(const[c,i]of Object.entries(n))o+=`${c}=${i}&`;return`${t}${e}?${o.slice(0,-1)}`},a=(t,e="")=>new Proxy(()=>{},{get(n,o,c){return a(t,`${e}/${o.toString()}`)},apply(n,o,[{$query:c,$fetch:i,...f}={$fetch:void 0,$query:void 0}]=[{}]){const d=e.lastIndexOf("/");return fetch(y(t,e.slice(0,d),c),{method:e.slice(d+1),headers:{"content-type":"application/json",...i==null?void 0:i.headers},body:Object.keys(f).length?JSON.stringify(f):void 0,...i}).then(async u=>{if(u.status>=300)throw new Error(await u.text());if(u.headers.get("content-type")==="application/json")return u.json();const l=await u.text();return Number.isNaN(+l)?l==="true"?!0:l==="false"?!1:l:+l})}}),g=t=>new Proxy({},{get(e,n,o){return a(t,n)}});r.eden=g,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})}); | ||
(function(o,u){typeof exports=="object"&&typeof module<"u"?u(exports):typeof define=="function"&&define.amd?define(["exports"],u):(o=typeof globalThis<"u"?globalThis:o||self,u(o["@elysia/eden"]={}))})(this,function(o){"use strict";class u{constructor(e){this.ws=new WebSocket(e),this.url=e}send(e){return Array.isArray(e)?(e.forEach(t=>this.send(t)),this):(this.ws.send(typeof e=="object"?JSON.stringify(e):e.toString()),this)}on(e,t,n){return this.addEventListener(e,t,n)}off(e,t,n){return this.ws.removeEventListener(e,t,n),this}addEventListener(e,t,n){return this.ws.addEventListener(e,i=>{if(e==="message"){let r=i.data.toString();const c=r.charCodeAt(0);if(c===47||c===123)try{r=JSON.parse(r)}catch{}else Number.isNaN(+r)?r==="true"?r=!0:r==="fase"&&(r=!1):r=+r;t({...i,data:r})}else t(i)},n),this}removeEventListener(e,t,n){return this.off(e,t,n),this}close(){return this.ws.close(),this}}const g=s=>s.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),v=(s,e,t)=>{if(s.endsWith("/")||(s+="/"),e=g(e.replace(/index/g,"")),!t||!Object.keys(t).length)return`${s}${e}`;let n="";for(const[i,r]of Object.entries(t))n+=`${i}=${r}&`;return`${s}${e}?${n.slice(0,-1)}`},l=(s,e="")=>new Proxy(()=>{},{get(t,n,i){return l(s,`${e}/${n.toString()}`)},apply(t,n,[{$query:i,$fetch:r,...c}={$fetch:void 0,$query:void 0}]=[{}]){const d=e.lastIndexOf("/"),h=e.slice(d+1),y=v(s,e.slice(0,d),i);return h==="subscribe"?new u(y.replace(/^([^]+):\/\//,"ws://")):fetch(y,{method:h,headers:{"content-type":"application/json",...r==null?void 0:r.headers},body:Object.keys(c).length?JSON.stringify(c):void 0,...r}).then(async f=>{if(f.status>=300)throw new Error(await f.text());if(f.headers.get("content-type")==="application/json")return f.json();const a=await f.text();return Number.isNaN(+a)?a==="true"?!0:a==="false"?!1:a:+a})}}),p=s=>new Proxy({},{get(e,t,n){return l(s,t)}});o.EdenWS=u,o.eden=p,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"})}); |
/// <reference types="bun-types" /> | ||
import type { Elysia, SCHEMA, TypedRoute } from 'elysia'; | ||
import { EdenWS } from '.'; | ||
export declare type Eden<App extends Elysia<any>> = App['store'] extends { | ||
@@ -12,3 +13,5 @@ [key in typeof SCHEMA]: any; | ||
export declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; | ||
declare type TypedRouteToParams<Route extends TypedRoute> = (Route['body'] extends NonNullable<Route['body']> ? Route['body'] : {}) & (Route['query'] extends NonNullable<Route['query']> ? { | ||
declare type TypedRouteToParams<Route extends TypedRoute> = (Route['body'] extends NonNullable<Route['body']> ? Route['body'] extends Record<any, any> ? Route['body'] : { | ||
$body: Route['body']; | ||
} : {}) & (Route['query'] extends NonNullable<Route['query']> ? { | ||
$query: Route['query']; | ||
@@ -20,7 +23,15 @@ } : {}); | ||
[key in Path extends '' ? 'index' : Path extends `:${infer params}` ? string : Path | CamelCase<Path>]: Full extends keyof Server ? { | ||
[key in keyof Server[Full]]: keyof TypedRouteToParams<Server[Full][key]> extends never ? (params?: { | ||
[key in keyof Server[Full]]: keyof TypedRouteToParams<Server[Full][key]> extends never ? key extends 'subscribe' ? (params?: Server[Full][key]['query'] extends NonNullable<Server[Full][key]['query']> ? { | ||
$query: Server[Full][key]['query']; | ||
} : { | ||
$query?: EdenCall['$query']; | ||
}) => EdenWS<Server[Full][key]> : (params?: { | ||
$query?: EdenCall['$query']; | ||
$fetch?: EdenCall['$fetch']; | ||
}) => Promise<Server[Full][key]['response']> : (params: TypedRouteToParams<Server[Full][key]> & { | ||
}) => Promise<Server[Full][key]['response']> : key extends 'subscribe' ? (params?: Server[Full][key]['query'] extends NonNullable<Server[Full][key]['query']> ? { | ||
$query: Server[Full][key]['query']; | ||
} : { | ||
$query?: EdenCall['$query']; | ||
}) => EdenWS<Server[Full][key]> : (params: TypedRouteToParams<Server[Full][key]> & { | ||
$query?: EdenCall['$query']; | ||
$fetch?: EdenCall['$fetch']; | ||
@@ -31,2 +42,7 @@ }) => Promise<Server[Full][key]['response']>; | ||
declare type CamelCase<S extends string> = S extends `${infer P1}-${infer P2}${infer P3}` ? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}` : Lowercase<S>; | ||
export interface EdenWSOnMessage<Data = unknown> extends MessageEvent { | ||
data: Data; | ||
rawData: MessageEvent['data']; | ||
} | ||
export declare type EdenWSEvent<K extends keyof WebSocketEventMap, Data = unknown> = K extends 'message' ? EdenWSOnMessage<Data> : WebSocketEventMap[K]; | ||
export {}; |
{ | ||
"name": "@elysiajs/eden", | ||
"version": "0.1.0", | ||
"version": "0.2.0-rc.0", | ||
"description": "Fully type-safe Elysia client", | ||
@@ -37,10 +37,12 @@ "author": { | ||
"peerDependencies": { | ||
"elysia": ">= 0.1.0-rc.5" | ||
"elysia": ">= 0.1.0-rc.5", | ||
"@elysiajs/websocket": "^0.2.1" | ||
}, | ||
"devDependencies": { | ||
"@elysiajs/cors": "^0.1.0-rc.3", | ||
"@elysiajs/cors": "^0.1.0", | ||
"@elysiajs/websocket": "^0.2.1", | ||
"@sinclair/typebox": "^0.25.13", | ||
"@types/node": "^18.11.7", | ||
"bun-types": "^0.3.0", | ||
"elysia": "^0.1.0-rc.8", | ||
"elysia": "^0.1.2", | ||
"eslint": "^8.26.0", | ||
@@ -47,0 +49,0 @@ "rimraf": "^3.0.2", |
115
src/index.ts
@@ -1,6 +0,106 @@ | ||
import type { Elysia } from 'elysia' | ||
import type { Elysia, TypedSchema } from 'elysia' | ||
import type { HTTPMethod } from 'elysia' | ||
import { CreateEden, Eden, EdenCall, UnionToIntersection } from './types' | ||
import type { | ||
CreateEden, | ||
Eden, | ||
EdenCall, | ||
EdenWSEvent, | ||
UnionToIntersection | ||
} from './types' | ||
export class EdenWS<Schema extends TypedSchema<any> = TypedSchema> { | ||
ws: WebSocket | ||
url: string | ||
constructor(url: string) { | ||
this.ws = new WebSocket(url) | ||
this.url = url | ||
} | ||
send(data: Schema['body'] | Schema['body'][]) { | ||
if (Array.isArray(data)) { | ||
data.forEach((datum) => this.send(datum)) | ||
return this | ||
} | ||
this.ws.send( | ||
typeof data === 'object' ? JSON.stringify(data) : data.toString() | ||
) | ||
return this | ||
} | ||
on<K extends keyof WebSocketEventMap>( | ||
type: K, | ||
listener: (event: EdenWSEvent<K, Schema['response']>) => void, | ||
options?: boolean | AddEventListenerOptions | ||
) { | ||
return this.addEventListener(type, listener, options) | ||
} | ||
off<K extends keyof WebSocketEventMap>( | ||
type: K, | ||
listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, | ||
options?: boolean | EventListenerOptions | ||
) { | ||
this.ws.removeEventListener(type, listener, options) | ||
return this | ||
} | ||
addEventListener<K extends keyof WebSocketEventMap>( | ||
type: K, | ||
listener: (event: EdenWSEvent<K, Schema['response']>) => void, | ||
options?: boolean | AddEventListenerOptions | ||
) { | ||
this.ws.addEventListener( | ||
type, | ||
(ws) => { | ||
if (type === 'message') { | ||
let data = (ws as MessageEvent).data.toString() as any | ||
const start = data.charCodeAt(0) | ||
if (start === 47 || start === 123) | ||
try { | ||
data = JSON.parse(data) | ||
} catch {} | ||
else if (!Number.isNaN(+data)) data = +data | ||
else if (data === 'true') data = true | ||
else if (data === 'fase') data = false | ||
// @ts-ignore | ||
listener({ | ||
...ws, | ||
data | ||
}) | ||
} else { | ||
// @ts-ignore | ||
listener(ws) | ||
} | ||
}, | ||
options | ||
) | ||
return this | ||
} | ||
removeEventListener<K extends keyof WebSocketEventMap>( | ||
type: K, | ||
listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, | ||
options?: boolean | EventListenerOptions | ||
) { | ||
this.off(type, listener, options) | ||
return this | ||
} | ||
close() { | ||
this.ws.close() | ||
return this | ||
} | ||
} | ||
const camelToDash = (str: string) => | ||
@@ -43,6 +143,11 @@ str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`) | ||
) { | ||
const i = path.lastIndexOf('/') | ||
const i = path.lastIndexOf('/'), | ||
method = path.slice(i + 1), | ||
url = composePath(domain, path.slice(0, i), $query) | ||
return fetch(composePath(domain, path.slice(0, i), $query), { | ||
method: path.slice(i + 1), | ||
if (method === 'subscribe') | ||
return new EdenWS(url.replace(/^([^]+):\/\//, 'ws://')) | ||
return fetch(url, { | ||
method, | ||
headers: { | ||
@@ -49,0 +154,0 @@ 'content-type': 'application/json', |
import type { Elysia, SCHEMA, TypedRoute } from 'elysia' | ||
import { TObject } from '@sinclair/typebox' | ||
import { EdenWS } from '.' | ||
@@ -9,3 +11,2 @@ export type Eden<App extends Elysia<any>> = App['store'] extends { | ||
export interface EdenCall { | ||
@@ -24,3 +25,9 @@ [x: string]: any | ||
type TypedRouteToParams<Route extends TypedRoute> = | ||
(Route['body'] extends NonNullable<Route['body']> ? Route['body'] : {}) & | ||
(Route['body'] extends NonNullable<Route['body']> | ||
? Route['body'] extends Record<any, any> | ||
? Route['body'] | ||
: { | ||
$body: Route['body'] | ||
} | ||
: {}) & | ||
(Route['query'] extends NonNullable<Route['query']> | ||
@@ -53,6 +60,30 @@ ? { | ||
> extends never | ||
? (params?: { | ||
$query?: EdenCall['$query'] | ||
$fetch?: EdenCall['$fetch'] | ||
}) => Promise<Server[Full][key]['response']> | ||
? key extends 'subscribe' | ||
? ( | ||
params?: Server[Full][key]['query'] extends NonNullable< | ||
Server[Full][key]['query'] | ||
> | ||
? { | ||
$query: Server[Full][key]['query'] | ||
} | ||
: { | ||
$query?: EdenCall['$query'] | ||
} | ||
) => EdenWS<Server[Full][key]> | ||
: (params?: { | ||
$query?: EdenCall['$query'] | ||
$fetch?: EdenCall['$fetch'] | ||
}) => Promise<Server[Full][key]['response']> | ||
: key extends 'subscribe' | ||
? ( | ||
params?: Server[Full][key]['query'] extends NonNullable< | ||
Server[Full][key]['query'] | ||
> | ||
? { | ||
$query: Server[Full][key]['query'] | ||
} | ||
: { | ||
$query?: EdenCall['$query'] | ||
} | ||
) => EdenWS<Server[Full][key]> | ||
: ( | ||
@@ -74,2 +105,10 @@ params: TypedRouteToParams<Server[Full][key]> & { | ||
type A = CamelCase<'sign-in'> | ||
export interface EdenWSOnMessage<Data = unknown> extends MessageEvent { | ||
data: Data | ||
rawData: MessageEvent['data'] | ||
} | ||
export type EdenWSEvent< | ||
K extends keyof WebSocketEventMap, | ||
Data = unknown | ||
> = K extends 'message' ? EdenWSOnMessage<Data> : WebSocketEventMap[K] |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
22618
425
2
11