@mpgd/bridge 0.1.0 → 0.2.0

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/orpc.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { StandardUrl } from '@orpc/client/standard';
2
+ import { type RouterContractClient } from '@orpc/contract';
3
+ import { type BridgeRequest, type BridgeResponse } from './index';
4
+ export type BridgeRpcEndpoint = StandardUrl;
5
+ export type BridgeRpcPrefix = `/${string}`;
6
+ export declare const defaultBridgeRpcEndpoint = "/api/mpgd/rpc";
7
+ export declare const bridgeRpcContract: {
8
+ request: import("@orpc/contract").ProcedureContract<import("@orpc/contract").Schema<BridgeRequest<unknown>, BridgeRequest<unknown>>, import("@orpc/contract").Schema<BridgeResponse, BridgeResponse>, object>;
9
+ };
10
+ export type BridgeRpcContract = typeof bridgeRpcContract;
11
+ export type BridgeRpcClient = RouterContractClient<BridgeRpcContract>;
12
+ export type BridgeRpcRequestHandler = (request: BridgeRequest) => BridgeResponse | Promise<BridgeResponse>;
13
+ export type BridgeRpcRouter = ReturnType<typeof createBridgeRpcRouter>;
14
+ export interface CreateBridgeOrpcClientInput {
15
+ readonly url?: BridgeRpcEndpoint;
16
+ readonly fetch?: typeof fetch;
17
+ readonly headers?: Record<string, string>;
18
+ }
19
+ export interface CreateBridgeRpcFetchHandlerOptions {
20
+ readonly prefix?: BridgeRpcPrefix;
21
+ }
22
+ export declare function createBridgeOrpcClient(input?: CreateBridgeOrpcClientInput): BridgeRpcClient;
23
+ export declare function createBridgeRpcRouter(handleRequest: BridgeRpcRequestHandler): {
24
+ request: import("@orpc/server").ImplementedProcedure<import("@orpc/server").DefaultInitialContext & object, object, import("@orpc/contract").Schema<BridgeRequest<unknown>, BridgeRequest<unknown>>, import("@orpc/contract").Schema<BridgeResponse, BridgeResponse>, object>;
25
+ };
26
+ export declare function createBridgeRpcFetchHandler(router: BridgeRpcRouter, options?: CreateBridgeRpcFetchHandlerOptions): (request: Request) => Promise<Response>;
package/dist/orpc.js ADDED
@@ -0,0 +1,84 @@
1
+ import { createORPCClient } from '@orpc/client';
2
+ import { RPCLink } from '@orpc/client/fetch';
3
+ import { oc, type as orpcType } from '@orpc/contract';
4
+ import { implement } from '@orpc/server';
5
+ import { RPCHandler } from '@orpc/server/fetch';
6
+ import { assertBridgeRequest, createBridgeError, } from './index';
7
+ export const defaultBridgeRpcEndpoint = '/api/mpgd/rpc';
8
+ export const bridgeRpcContract = oc.router({
9
+ request: oc.input(orpcType()).output(orpcType()),
10
+ });
11
+ export function createBridgeOrpcClient(input = {}) {
12
+ const headers = input.headers;
13
+ const link = new RPCLink({
14
+ url: input.url ?? defaultBridgeRpcEndpoint,
15
+ ...(input.fetch === undefined ? {} : { fetch: input.fetch }),
16
+ ...(headers === undefined
17
+ ? {}
18
+ : {
19
+ headers: () => headers,
20
+ }),
21
+ });
22
+ return createORPCClient(link);
23
+ }
24
+ export function createBridgeRpcRouter(handleRequest) {
25
+ const contract = implement(bridgeRpcContract);
26
+ return contract.router({
27
+ request: contract.request.handler(({ input }) => {
28
+ let request;
29
+ try {
30
+ request = assertBridgeRequest(input);
31
+ }
32
+ catch (error) {
33
+ return createBridgeError(bridgeRequestIdFromInput(input), 'INVALID_BRIDGE_REQUEST', `Bridge RPC request failed runtime validation: ${errorMessage(error)}`, false);
34
+ }
35
+ return handleRequest(request);
36
+ }),
37
+ });
38
+ }
39
+ export function createBridgeRpcFetchHandler(router, options = {}) {
40
+ const rpcHandler = new RPCHandler(router);
41
+ const prefix = options.prefix ?? defaultBridgeRpcEndpoint;
42
+ return async (request) => {
43
+ try {
44
+ const result = await rpcHandler.handle(request, {
45
+ prefix,
46
+ context: {
47
+ request,
48
+ },
49
+ });
50
+ if (!result.matched) {
51
+ return new Response('Not Found', {
52
+ status: 404,
53
+ headers: {
54
+ 'content-type': 'text/plain',
55
+ },
56
+ });
57
+ }
58
+ return result.response;
59
+ }
60
+ catch (error) {
61
+ console.error('Bridge RPC internal error:', error);
62
+ return new Response(JSON.stringify({
63
+ error: 'BRIDGE_RPC_INTERNAL_ERROR',
64
+ }), {
65
+ status: 500,
66
+ headers: {
67
+ 'content-type': 'application/json',
68
+ },
69
+ });
70
+ }
71
+ };
72
+ }
73
+ function bridgeRequestIdFromInput(input) {
74
+ if (typeof input === 'object' && input !== null && 'id' in input) {
75
+ const id = input.id;
76
+ if (typeof id === 'string' && id.length > 0) {
77
+ return id;
78
+ }
79
+ }
80
+ return 'unknown';
81
+ }
82
+ function errorMessage(error) {
83
+ return error instanceof Error ? error.message : String(error);
84
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpgd/bridge",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Typed native bridge protocol for mpgd platform adapters.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -28,12 +28,19 @@
28
28
  ".": {
29
29
  "types": "./dist/index.d.ts",
30
30
  "default": "./dist/index.js"
31
+ },
32
+ "./orpc": {
33
+ "types": "./dist/orpc.d.ts",
34
+ "default": "./dist/orpc.js"
31
35
  }
32
36
  },
33
37
  "files": [
34
38
  "dist"
35
39
  ],
36
40
  "dependencies": {
41
+ "@orpc/client": "2.0.0-beta.14",
42
+ "@orpc/contract": "2.0.0-beta.14",
43
+ "@orpc/server": "2.0.0-beta.14",
37
44
  "typia": "rc"
38
45
  },
39
46
  "devDependencies": {
@@ -50,6 +57,6 @@
50
57
  "lint": "ttsc --noEmit",
51
58
  "format": "ttsc format",
52
59
  "fix": "ttsc fix",
53
- "test": "cd ../.. && node tools/run-ttsx.mjs packages/bridge/src/bridge-protocol.test.ts"
60
+ "test": "cd ../.. && node tools/run-ttsx.mjs packages/bridge/src/bridge-protocol.test.ts && node tools/run-ttsx.mjs packages/bridge/src/orpc.test.ts"
54
61
  }
55
62
  }