mirror of
https://github.com/geoffsee/open-gsio.git
synced 2025-09-08 22:56:46 +00:00
wip
This commit is contained in:

committed by
Geoff Seemueller

parent
21d6c8604e
commit
554096abb2
15
packages/router/package.json
Normal file
15
packages/router/package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "@open-gsio/router",
|
||||
"type": "module",
|
||||
"module": "src/index.ts",
|
||||
"scripts": {
|
||||
"tests": "vitest run",
|
||||
"tests:coverage": "vitest run --coverage.enabled=true"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@open-gsio/services": "workspace:*",
|
||||
"itty-router": "^5.0.18",
|
||||
"mobx": "^6.13.5",
|
||||
"mobx-state-tree": "^6.0.1"
|
||||
}
|
||||
}
|
17
packages/router/src/__tests__/router.test.ts
Normal file
17
packages/router/src/__tests__/router.test.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
|
||||
import { createRouter } from '../router.ts';
|
||||
|
||||
// Mock the vike/server module
|
||||
vi.mock('vike/server', () => ({
|
||||
renderPage: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('api-router', () => {
|
||||
// Test that the router is created successfully
|
||||
it('creates a router', () => {
|
||||
const router = createRouter();
|
||||
expect(router).toBeDefined();
|
||||
expect(typeof router.handle).toBe('function');
|
||||
});
|
||||
});
|
5
packages/router/src/index.ts
Normal file
5
packages/router/src/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { createRouter } from './router.ts';
|
||||
|
||||
export default {
|
||||
Router: createRouter,
|
||||
};
|
70
packages/router/src/request-context.ts
Normal file
70
packages/router/src/request-context.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import {
|
||||
ChatService,
|
||||
ContactService,
|
||||
AssetService,
|
||||
MetricsService,
|
||||
TransactionService,
|
||||
FeedbackService,
|
||||
} from '@open-gsio/services';
|
||||
import { types, type Instance, getMembers } from 'mobx-state-tree';
|
||||
|
||||
const RequestContext = types
|
||||
.model('RequestContext', {
|
||||
chatService: ChatService,
|
||||
contactService: types.optional(ContactService, {}),
|
||||
assetService: types.optional(AssetService, {}),
|
||||
metricsService: types.optional(MetricsService, {}),
|
||||
transactionService: types.optional(TransactionService, {}),
|
||||
feedbackService: types.optional(FeedbackService, {}),
|
||||
})
|
||||
.actions(self => {
|
||||
const services = Object.keys(getMembers(self).properties);
|
||||
|
||||
return {
|
||||
setEnv(env: Env) {
|
||||
services.forEach(service => {
|
||||
// @ts-expect-error - override indexing type error
|
||||
if (typeof self[service]?.setEnv === 'function') {
|
||||
// @ts-expect-error - override indexing type error
|
||||
self[service].setEnv(env);
|
||||
}
|
||||
});
|
||||
},
|
||||
setCtx(ctx: ExecutionContext) {
|
||||
services.forEach(service => {
|
||||
// @ts-expect-error - override indexing type error
|
||||
if (typeof self[service]?.setCtx === 'function') {
|
||||
// @ts-expect-error - override indexing type error
|
||||
self[service].setCtx(ctx);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export type RequestContextInstance = Instance<typeof RequestContext>;
|
||||
|
||||
const createRequestContext = (env: Env, ctx: any) => {
|
||||
const instance = RequestContext.create({
|
||||
contactService: ContactService.create({}),
|
||||
assetService: AssetService.create({}),
|
||||
transactionService: TransactionService.create({}),
|
||||
feedbackService: FeedbackService.create({}),
|
||||
metricsService: MetricsService.create({
|
||||
isCollectingMetrics: true,
|
||||
}),
|
||||
chatService: ChatService.create({
|
||||
openAIApiKey: env.OPENAI_API_KEY,
|
||||
openAIBaseURL: env.OPENAI_API_ENDPOINT,
|
||||
activeStreams: undefined,
|
||||
maxTokens: 16384,
|
||||
systemPrompt:
|
||||
'You are an assistant designed to provide accurate, concise, and context-aware responses while demonstrating your advanced reasoning capabilities.',
|
||||
}),
|
||||
});
|
||||
instance.setEnv(env);
|
||||
instance.setCtx(ctx);
|
||||
return instance;
|
||||
};
|
||||
|
||||
export { createRequestContext };
|
84
packages/router/src/router.ts
Normal file
84
packages/router/src/router.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { Router, withParams } from 'itty-router';
|
||||
|
||||
import { createRequestContext } from './request-context.ts';
|
||||
|
||||
export function createRouter() {
|
||||
return (
|
||||
Router()
|
||||
.get('/assets/*', (r, e, c) => {
|
||||
const { assetService } = createRequestContext(e, c);
|
||||
return assetService.handleStaticAssets(r, e, c);
|
||||
})
|
||||
|
||||
.post('/api/contact', (r, e, c) => {
|
||||
const { contactService } = createRequestContext(e, c);
|
||||
return contactService.handleContact(r);
|
||||
})
|
||||
|
||||
.post('/api/chat', (r, e, c) => {
|
||||
const { chatService } = createRequestContext(e, c);
|
||||
return chatService.handleChatRequest(r);
|
||||
})
|
||||
|
||||
.get('/api/streams/:streamId', withParams, async ({ streamId }, env, ctx) => {
|
||||
const { chatService } = createRequestContext(env, ctx);
|
||||
return chatService.handleSseStream(streamId); // Handles SSE for streamId
|
||||
})
|
||||
|
||||
.get('/api/models', async (req, env, ctx) => {
|
||||
const { chatService } = createRequestContext(env, ctx);
|
||||
return chatService.getSupportedModels();
|
||||
})
|
||||
|
||||
.post('/api/feedback', async (r, e, c) => {
|
||||
const { feedbackService } = createRequestContext(e, c);
|
||||
return feedbackService.handleFeedback(r);
|
||||
})
|
||||
|
||||
.post('/api/tx', async (r, e, c) => {
|
||||
const { transactionService } = createRequestContext(e, c);
|
||||
return transactionService.handleTransact(r);
|
||||
})
|
||||
|
||||
// used for file handling, can be enabled but is not fully implemented in this fork.
|
||||
// .post('/api/documents', async (r, e, c) => {
|
||||
// const {documentService} = createServerContext(e, c);
|
||||
// return documentService.handlePutDocument(r)
|
||||
// })
|
||||
//
|
||||
// .get('/api/documents', async (r, e, c) => {
|
||||
// const {documentService} = createServerContext(e, c);
|
||||
// return documentService.handleGetDocument(r)
|
||||
// })
|
||||
|
||||
.get('/api/metrics*', async (r, e, c) => {
|
||||
const { metricsService } = createRequestContext(e, c);
|
||||
return metricsService.handleMetricsRequest(r);
|
||||
})
|
||||
|
||||
.post('/api/metrics*', async (r, e, c) => {
|
||||
const { metricsService } = createRequestContext(e, c);
|
||||
return metricsService.handleMetricsRequest(r);
|
||||
})
|
||||
|
||||
// renders the app
|
||||
.all('^(?!/api/)(?!/assets/).*$', async (r, e, c) => {
|
||||
const { assetService } = createRequestContext(e, c);
|
||||
|
||||
// First attempt to serve pre-rendered HTML
|
||||
const preRenderedHtml = await assetService.handleStaticAssets(r, e);
|
||||
if (preRenderedHtml !== null) {
|
||||
return preRenderedHtml;
|
||||
}
|
||||
|
||||
// If no pre-rendered HTML, attempt SSR
|
||||
const ssrResponse = await assetService.handleSsr(r.url, r.headers, e);
|
||||
if (ssrResponse !== null) {
|
||||
return ssrResponse;
|
||||
}
|
||||
|
||||
// Finally, proxy to static assets if nothing else matched
|
||||
return assetService.handleStaticAssets(r, e);
|
||||
})
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user