Skip to content

Commit

Permalink
minor upgrade to the hyperschema project
Browse files Browse the repository at this point in the history
  • Loading branch information
TheCactusBlue committed Jan 31, 2024
1 parent ab150e0 commit ae8043a
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 135 deletions.
7 changes: 4 additions & 3 deletions apps/typescript/client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ const mainService = new MainService(
);
(globalThis as any).client = mainService;

mainService.child.onTick((x) => {
console.log(`ticking ${x}`);
});
// mainService.child.onTick((x) => {
// console.log(`ticking ${x}`);
// });

function App() {
const [loaded, setLoaded] = useState(false);
Expand All @@ -33,6 +33,7 @@ function App() {
<div className="card">
<button
onClick={async () => {
console.log('click');
const res = await mainService.add({ x: 1, y: 2 });
console.log(res);
}}
Expand Down
10 changes: 1 addition & 9 deletions apps/typescript/client/src/hs-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,11 @@ export class ChildService {
add2(input: { x: number; y: number }): Promise<number> {
return this.client.call("child/add2", input);
}

onTick(cb: (data: number) => void): () => void {
return this.client.on("child/onTick", cb);
}
}

export class MainService extends RootService {
readonly PATH = "";
readonly child = new ChildService(this.client);
readonly child: ChildService;

constructor(protected client: HyperschemaClient) {
super();
Expand All @@ -52,8 +48,4 @@ export class MainService extends RootService {
hello(input: { person: Person }): Promise<string> {
return this.client.call("hello", input);
}

onTick(cb: (data: number) => void): () => void {
return this.client.on("onTick", cb);
}
}
36 changes: 12 additions & 24 deletions apps/typescript/server/src/hyperschema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,18 @@ export const ChildService = h.service({
return x + y;
}),

onTick: h.event(z.number()).emitter((emit, ctx) => {
console.log('are we ticking yet 2?');
let i = 0;
const interval = setInterval(() => {
i++;
console.log('tock ' + i);
emit(i);
}, 1000);
return () => {
clearInterval(interval);
};
}),
// onTick: h.event(z.number()).emitter((emit, ctx) => {
// console.log('are we ticking yet 2?');
// let i = 0;
// const interval = setInterval(() => {
// i++;
// console.log('tock ' + i);
// emit(i);
// }, 1000);
// return () => {
// clearInterval(interval);
// };
// }),
});

export const MainService = h
Expand All @@ -78,17 +78,5 @@ export const MainService = h
hello: h.fn({ person: Person }, z.string()).do(async ({ person }) => {
return `Hello, ${person.name}!`;
}),

onTick: h.event(z.number()).emitter((emit, ctx) => {
console.log('are we ticking yet?');
// console.log(`setting up for ${ctx.$meta.connId}...}`);
// const interval = setInterval(() => {
// emit(Math.random());
// }, 1000);
// return () => {
// console.log(`cleaning up for ${ctx.$meta.connId}.`);
// clearInterval(interval);
// };
}),
})
.root();
30 changes: 21 additions & 9 deletions apps/typescript/server/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { hostHyperRPC, writeTypeScriptClient } from '@hyperschema/core';
import {
HyperschemaServer,
SocketIOTransport,
TypeScriptWriter,
writeTypeScriptClient,
} from '@hyperschema/core';
import fastify from 'fastify';
import path from 'path';
import * as socketIO from 'socket.io';
Expand All @@ -9,18 +14,25 @@ const app = fastify();
app.get('/', async () => {
return { hello: 'world' };
});
const io = new socketIO.Server(app.server, {
cors: { origin: '*' },
});

hostHyperRPC(io, hs.MainService);
const hss = new HyperschemaServer({
system: hs,
root: hs.MainService,
transports: [
new SocketIOTransport(
new socketIO.Server(app.server, {
cors: { origin: '*' },
}),
),
],
writers: [
new TypeScriptWriter(path.join(__dirname, '../../client/src/hs-client.ts')),
],
});

(async function main() {
console.log('generating hyperschema...');
await writeTypeScriptClient(
path.join(__dirname, '../../client/src/hs-client.ts'),
hs,
);
await hss.start({ generate: true });
console.log('generated hyperschema!');
await app.listen({
port: 3100,
Expand Down
89 changes: 0 additions & 89 deletions packages/typescript/hyperschema-core/src/hrpc/transport/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { HyperRPCService } from '..';
import { BaseError } from '../../errors';

export function processError(err: unknown) {
Expand All @@ -14,3 +15,7 @@ export function processError(err: unknown) {
}
return { message: 'Unknown Error' };
}

export interface AbstractTransportEngine {
mount(service: HyperRPCService<any>): void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import * as socketIO from 'socket.io';

import { HyperRPCService, MetaObject } from '..';
import { AbstractTransportEngine, processError } from './logic';

function setupServiceEvents(socket: socketIO.Socket, service: HyperRPCService) {
const cleanupFns: (() => void)[] = [];

// setup service events
Object.entries(service.events).forEach(([name, event]) => {
if (event.emitterSetup) {
const eventPath = service.path === '' ? name : `${service.path}/${name}`;
const cleanup = event.emitterSetup((x) => {
socket.emit(eventPath, event.eventType.parse(x));
}, socket.data);
if (cleanup) {
cleanupFns.push(cleanup);
}
}
});

// setup child service events
Object.values(service.subservices).forEach((childService) => {
setupServiceEvents(socket, childService);
});

socket.on('disconnect', () => {
cleanupFns.forEach((fn) => fn());
});
}

export class SocketIOTransport implements AbstractTransportEngine {
io: socketIO.Server;
constructor(io: socketIO.Server) {
this.io = io;
}

mount(service: HyperRPCService): void {
this.io.use((socket, next) => {
const meta: MetaObject = {
connId: socket.id,
authToken: socket.handshake.auth.token,
};

// merge the context into socket.data
service.hyperRPC
.contextFn({ $meta: meta })
.then((res: any) => {
Object.keys(res).forEach((k) => {
socket.data.$meta = meta;
socket.data[k] = res[k];
});
next();
})
.catch(next);
});
this.io.on('connection', async (socket) => {
socket.onAny(
(fullPath: string, args: unknown, callback: (resp: any) => void) => {
try {
const path = fullPath.split('/');
const functionName = path.pop()!;
const endpointSvc = path.reduce(
(acc, x) => acc.subservices[x],
service,
);

const fn = endpointSvc.functions[functionName];
fn.call(socket.data, args)
.then((ok) => callback({ ok }))
.catch((err) => callback({ err: processError(err) }));
} catch (err) {
callback({ err: processError(err) });
}
},
);

setupServiceEvents(socket, service);
socket.emit('ready');
});
}
}
40 changes: 39 additions & 1 deletion packages/typescript/hyperschema-core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,44 @@
import { HyperRPCService } from './hrpc';
import { AbstractTransportEngine } from './hrpc/transport/logic';
import { HyperschemaWriter } from './writers';

export * from './reflector';
export * from './hrpc';
export * from './hrpc/transport';
export * from './hrpc/transport/socketio';
export * from './errors';
export * from './generator';
export * from './writers';
export * from './types';

export interface HyperschemaServerOptions {
system: any;
root: HyperRPCService<any>;
transports?: AbstractTransportEngine[];
writers?: HyperschemaWriter[];
}

export interface HyperschemaStartOption {
generate?: boolean;
}

export class HyperschemaServer {
system: any;
root: HyperRPCService<any>;
transports: AbstractTransportEngine[];
writers: HyperschemaWriter[];

constructor(options: HyperschemaServerOptions) {
this.system = options.system;
this.root = options.root;
this.transports = options.transports || [];

this.transports.forEach((t) => t.mount(this.root));
this.writers = options.writers || [];
}

async start(options: HyperschemaStartOption = {}) {
if (options.generate) {
await Promise.all(this.writers.map((w) => w.write(this.system)));
}
}
}
23 changes: 23 additions & 0 deletions packages/typescript/hyperschema-core/src/writers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { writeTypeScriptClient } from '../generator';
import { writeHyperschema } from '../reflector';

// Writers write the Hyperschema defintions to a file (or any other output)
export interface HyperschemaWriter {
write(hs: any): Promise<void>;
}

export class JSONWriter implements HyperschemaWriter {
constructor(public path: string) {}

async write(hs: any) {
writeHyperschema(this.path, hs);
}
}

export class TypeScriptWriter implements HyperschemaWriter {
constructor(public path: string) {}

async write(hs: any) {
writeTypeScriptClient(this.path, hs);
}
}

0 comments on commit ae8043a

Please sign in to comment.