@arcote.tech/arc-host 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/host.d.ts +1 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +322 -172
- package/host.ts +93 -17
- package/index.ts +2 -4
- package/package.json +1 -1
package/host.ts
CHANGED
|
@@ -102,7 +102,7 @@ class RTCHost implements RealTimeCommunicationAdapter {
|
|
|
102
102
|
*/
|
|
103
103
|
private getDefaultAuthContext(ipAddress?: string): AuthContext {
|
|
104
104
|
return {
|
|
105
|
-
userId:
|
|
105
|
+
userId: undefined as any,
|
|
106
106
|
roles: [],
|
|
107
107
|
ipAddress,
|
|
108
108
|
};
|
|
@@ -282,6 +282,70 @@ class RTCHost implements RealTimeCommunicationAdapter {
|
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
private async handleRoute(req: Request) {
|
|
286
|
+
const url = new URL(req.url);
|
|
287
|
+
const method = req.method;
|
|
288
|
+
|
|
289
|
+
// Find matching route
|
|
290
|
+
let matchedRoute: any = null;
|
|
291
|
+
let routeParams: Record<string, string> = {};
|
|
292
|
+
|
|
293
|
+
for (const element of this.context.elements) {
|
|
294
|
+
// Check if element has matchesRoutePath method (ArcRoute)
|
|
295
|
+
if (typeof (element as any).matchesRoutePath === "function") {
|
|
296
|
+
const { matches, params } = (element as any).matchesRoutePath(
|
|
297
|
+
url.pathname,
|
|
298
|
+
);
|
|
299
|
+
if (matches) {
|
|
300
|
+
matchedRoute = element;
|
|
301
|
+
routeParams = params || {};
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (!matchedRoute) {
|
|
308
|
+
return new Response("Route not found", { status: 404 });
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const handler = matchedRoute.getHandler(method);
|
|
312
|
+
if (!handler) {
|
|
313
|
+
return new Response(`Method ${method} not allowed`, { status: 405 });
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
try {
|
|
317
|
+
// Extract token from Authorization header
|
|
318
|
+
const authHeader = req.headers.get("Authorization");
|
|
319
|
+
const token = authHeader?.replace("Bearer ", "");
|
|
320
|
+
|
|
321
|
+
const clientIp = this.getClientIpAddress(req);
|
|
322
|
+
let authContext: AuthContext;
|
|
323
|
+
|
|
324
|
+
if (token && !matchedRoute.isPublic) {
|
|
325
|
+
const payload = await this.verifyAuthToken(token);
|
|
326
|
+
if (!payload) {
|
|
327
|
+
return new Response("Invalid or expired token", { status: 401 });
|
|
328
|
+
}
|
|
329
|
+
authContext = this.tokenToAuthContext(payload, clientIp);
|
|
330
|
+
} else {
|
|
331
|
+
authContext = this.getDefaultAuthContext(clientIp);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Use the model's routes method to properly handle event publishing
|
|
335
|
+
const routes = this.model.routes(authContext);
|
|
336
|
+
const response = await routes[matchedRoute.name](
|
|
337
|
+
method,
|
|
338
|
+
req,
|
|
339
|
+
routeParams,
|
|
340
|
+
url,
|
|
341
|
+
);
|
|
342
|
+
return response;
|
|
343
|
+
} catch (error) {
|
|
344
|
+
console.error(`Error executing route ${matchedRoute.name}:`, error);
|
|
345
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
285
349
|
private setupServer() {
|
|
286
350
|
this.server = Bun.serve({
|
|
287
351
|
fetch: async (req, server) => {
|
|
@@ -328,6 +392,12 @@ class RTCHost implements RealTimeCommunicationAdapter {
|
|
|
328
392
|
return await this.handleQuery(req);
|
|
329
393
|
}
|
|
330
394
|
|
|
395
|
+
// Try to handle as a route
|
|
396
|
+
const routeResponse = await this.handleRoute(req);
|
|
397
|
+
if (routeResponse.status !== 404) {
|
|
398
|
+
return routeResponse;
|
|
399
|
+
}
|
|
400
|
+
|
|
331
401
|
return new Response("Not Found", { status: 404 });
|
|
332
402
|
},
|
|
333
403
|
websocket: {
|
|
@@ -344,25 +414,31 @@ class RTCHost implements RealTimeCommunicationAdapter {
|
|
|
344
414
|
}
|
|
345
415
|
|
|
346
416
|
private isPublicEndpoint(pathname: string): boolean {
|
|
347
|
-
//
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
417
|
+
// Iterate through all context elements and check if any match and are public
|
|
418
|
+
for (const element of this.context.elements) {
|
|
419
|
+
// Check if element has matchesCommandPath method (ArcCommand)
|
|
420
|
+
if (typeof (element as any).matchesCommandPath === "function") {
|
|
421
|
+
const { matches, isPublic } = (element as any).matchesCommandPath(
|
|
422
|
+
pathname,
|
|
423
|
+
);
|
|
424
|
+
if (matches) {
|
|
425
|
+
return isPublic;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
351
428
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
429
|
+
// Check if element has matchesRoutePath method (ArcRoute)
|
|
430
|
+
if (typeof (element as any).matchesRoutePath === "function") {
|
|
431
|
+
const { matches, isPublic } = (element as any).matchesRoutePath(
|
|
432
|
+
pathname,
|
|
433
|
+
);
|
|
434
|
+
if (matches) {
|
|
435
|
+
return isPublic;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
355
438
|
}
|
|
356
439
|
|
|
357
|
-
//
|
|
358
|
-
|
|
359
|
-
(element: any) => element.name === commandName,
|
|
360
|
-
);
|
|
361
|
-
|
|
362
|
-
// Check if it's an ArcCommand instance and if it's marked as public
|
|
363
|
-
return contextElement && "isPublic" in contextElement
|
|
364
|
-
? contextElement.isPublic === true
|
|
365
|
-
: false;
|
|
440
|
+
// Default to non-public if no matching element found
|
|
441
|
+
return false;
|
|
366
442
|
}
|
|
367
443
|
|
|
368
444
|
private async handleSync(lastDate: string | null) {
|
package/index.ts
CHANGED
|
@@ -3,11 +3,9 @@ import { rtcHostFactory } from "./host";
|
|
|
3
3
|
import { sqliteAdapterFactory } from "./sqliteAdapter";
|
|
4
4
|
|
|
5
5
|
export function hostLiveModel<C extends ArcContextAny>(
|
|
6
|
-
|
|
6
|
+
context: C,
|
|
7
7
|
options: { db: string; version: number },
|
|
8
8
|
) {
|
|
9
9
|
const dbAdapterFactory = sqliteAdapterFactory(options.db);
|
|
10
|
-
|
|
11
|
-
rtcHostFactory(context, dbAdapterFactory(context))();
|
|
12
|
-
});
|
|
10
|
+
rtcHostFactory(context, dbAdapterFactory(context))();
|
|
13
11
|
}
|