ai.matey.http 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.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/deno/adapter.js +173 -0
  3. package/dist/cjs/deno/adapter.js.map +1 -0
  4. package/dist/cjs/deno/handler.js +78 -0
  5. package/dist/cjs/deno/handler.js.map +1 -0
  6. package/dist/cjs/deno/index.js +26 -0
  7. package/dist/cjs/deno/index.js.map +1 -0
  8. package/dist/cjs/express/adapter.js +150 -0
  9. package/dist/cjs/express/adapter.js.map +1 -0
  10. package/dist/cjs/express/index.js +26 -0
  11. package/dist/cjs/express/index.js.map +1 -0
  12. package/dist/cjs/express/middleware.js +63 -0
  13. package/dist/cjs/express/middleware.js.map +1 -0
  14. package/dist/cjs/fastify/adapter.js +149 -0
  15. package/dist/cjs/fastify/adapter.js.map +1 -0
  16. package/dist/cjs/fastify/handler.js +54 -0
  17. package/dist/cjs/fastify/handler.js.map +1 -0
  18. package/dist/cjs/fastify/index.js +26 -0
  19. package/dist/cjs/fastify/index.js.map +1 -0
  20. package/dist/cjs/hono/adapter.js +172 -0
  21. package/dist/cjs/hono/adapter.js.map +1 -0
  22. package/dist/cjs/hono/index.js +26 -0
  23. package/dist/cjs/hono/index.js.map +1 -0
  24. package/dist/cjs/hono/middleware.js +75 -0
  25. package/dist/cjs/hono/middleware.js.map +1 -0
  26. package/dist/cjs/index.js +37 -0
  27. package/dist/cjs/index.js.map +1 -0
  28. package/dist/cjs/koa/adapter.js +153 -0
  29. package/dist/cjs/koa/adapter.js.map +1 -0
  30. package/dist/cjs/koa/index.js +26 -0
  31. package/dist/cjs/koa/index.js.map +1 -0
  32. package/dist/cjs/koa/middleware.js +58 -0
  33. package/dist/cjs/koa/middleware.js.map +1 -0
  34. package/dist/cjs/node/adapter.js +170 -0
  35. package/dist/cjs/node/adapter.js.map +1 -0
  36. package/dist/cjs/node/index.js +26 -0
  37. package/dist/cjs/node/index.js.map +1 -0
  38. package/dist/cjs/node/listener.js +98 -0
  39. package/dist/cjs/node/listener.js.map +1 -0
  40. package/dist/esm/deno/adapter.js +168 -0
  41. package/dist/esm/deno/adapter.js.map +1 -0
  42. package/dist/esm/deno/handler.js +75 -0
  43. package/dist/esm/deno/handler.js.map +1 -0
  44. package/dist/esm/deno/index.js +10 -0
  45. package/dist/esm/deno/index.js.map +1 -0
  46. package/dist/esm/express/adapter.js +145 -0
  47. package/dist/esm/express/adapter.js.map +1 -0
  48. package/dist/esm/express/index.js +10 -0
  49. package/dist/esm/express/index.js.map +1 -0
  50. package/dist/esm/express/middleware.js +60 -0
  51. package/dist/esm/express/middleware.js.map +1 -0
  52. package/dist/esm/fastify/adapter.js +144 -0
  53. package/dist/esm/fastify/adapter.js.map +1 -0
  54. package/dist/esm/fastify/handler.js +51 -0
  55. package/dist/esm/fastify/handler.js.map +1 -0
  56. package/dist/esm/fastify/index.js +10 -0
  57. package/dist/esm/fastify/index.js.map +1 -0
  58. package/dist/esm/hono/adapter.js +167 -0
  59. package/dist/esm/hono/adapter.js.map +1 -0
  60. package/dist/esm/hono/index.js +10 -0
  61. package/dist/esm/hono/index.js.map +1 -0
  62. package/dist/esm/hono/middleware.js +72 -0
  63. package/dist/esm/hono/middleware.js.map +1 -0
  64. package/dist/esm/index.js +21 -0
  65. package/dist/esm/index.js.map +1 -0
  66. package/dist/esm/koa/adapter.js +148 -0
  67. package/dist/esm/koa/adapter.js.map +1 -0
  68. package/dist/esm/koa/index.js +10 -0
  69. package/dist/esm/koa/index.js.map +1 -0
  70. package/dist/esm/koa/middleware.js +55 -0
  71. package/dist/esm/koa/middleware.js.map +1 -0
  72. package/dist/esm/node/adapter.js +165 -0
  73. package/dist/esm/node/adapter.js.map +1 -0
  74. package/dist/esm/node/index.js +10 -0
  75. package/dist/esm/node/index.js.map +1 -0
  76. package/dist/esm/node/listener.js +92 -0
  77. package/dist/esm/node/listener.js.map +1 -0
  78. package/dist/types/deno/adapter.d.ts +56 -0
  79. package/dist/types/deno/adapter.d.ts.map +1 -0
  80. package/dist/types/deno/handler.d.ts +38 -0
  81. package/dist/types/deno/handler.d.ts.map +1 -0
  82. package/dist/types/deno/index.d.ts +10 -0
  83. package/dist/types/deno/index.d.ts.map +1 -0
  84. package/dist/types/express/adapter.d.ts +46 -0
  85. package/dist/types/express/adapter.d.ts.map +1 -0
  86. package/dist/types/express/index.d.ts +10 -0
  87. package/dist/types/express/index.d.ts.map +1 -0
  88. package/dist/types/express/middleware.d.ts +39 -0
  89. package/dist/types/express/middleware.d.ts.map +1 -0
  90. package/dist/types/fastify/adapter.d.ts +46 -0
  91. package/dist/types/fastify/adapter.d.ts.map +1 -0
  92. package/dist/types/fastify/handler.d.ts +36 -0
  93. package/dist/types/fastify/handler.d.ts.map +1 -0
  94. package/dist/types/fastify/index.d.ts +10 -0
  95. package/dist/types/fastify/index.d.ts.map +1 -0
  96. package/dist/types/hono/adapter.d.ts +47 -0
  97. package/dist/types/hono/adapter.d.ts.map +1 -0
  98. package/dist/types/hono/index.d.ts +10 -0
  99. package/dist/types/hono/index.d.ts.map +1 -0
  100. package/dist/types/hono/middleware.d.ts +36 -0
  101. package/dist/types/hono/middleware.d.ts.map +1 -0
  102. package/dist/types/index.d.ts +15 -0
  103. package/dist/types/index.d.ts.map +1 -0
  104. package/dist/types/koa/adapter.d.ts +46 -0
  105. package/dist/types/koa/adapter.d.ts.map +1 -0
  106. package/dist/types/koa/index.d.ts +10 -0
  107. package/dist/types/koa/index.d.ts.map +1 -0
  108. package/dist/types/koa/middleware.d.ts +40 -0
  109. package/dist/types/koa/middleware.d.ts.map +1 -0
  110. package/dist/types/node/adapter.d.ts +57 -0
  111. package/dist/types/node/adapter.d.ts.map +1 -0
  112. package/dist/types/node/index.d.ts +10 -0
  113. package/dist/types/node/index.d.ts.map +1 -0
  114. package/dist/types/node/listener.d.ts +51 -0
  115. package/dist/types/node/listener.d.ts.map +1 -0
  116. package/package.json +160 -0
  117. package/readme.md +93 -0
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Deno HTTP Adapter
3
+ *
4
+ * Converts Deno Request/Response to GenericRequest/GenericResponse
5
+ *
6
+ * @module
7
+ */
8
+ /**
9
+ * Adapter that converts Deno Request to GenericRequest
10
+ */
11
+ export class DenoRequestAdapter {
12
+ request;
13
+ connInfo;
14
+ _body = null;
15
+ constructor(request, connInfo) {
16
+ this.request = request;
17
+ this.connInfo = connInfo;
18
+ }
19
+ get method() {
20
+ return this.request.method || 'GET';
21
+ }
22
+ get url() {
23
+ return this.request.url || '/';
24
+ }
25
+ get headers() {
26
+ const headers = {};
27
+ this.request.headers.forEach((value, key) => {
28
+ headers[key.toLowerCase()] = value;
29
+ });
30
+ return headers;
31
+ }
32
+ get body() {
33
+ // Return parsed body (must be set externally via setBody)
34
+ return this._body;
35
+ }
36
+ get params() {
37
+ // Params would need to be provided by routing layer
38
+ return undefined;
39
+ }
40
+ get query() {
41
+ // Parse query string from URL
42
+ const url = new URL(this.request.url);
43
+ const query = {};
44
+ url.searchParams.forEach((value, key) => {
45
+ query[key] = value;
46
+ });
47
+ return Object.keys(query).length > 0 ? query : undefined;
48
+ }
49
+ get ip() {
50
+ // Try to get IP from connection info or headers
51
+ if (this.connInfo?.remoteAddr?.hostname) {
52
+ return this.connInfo.remoteAddr.hostname;
53
+ }
54
+ const forwarded = this.request.headers.get('x-forwarded-for');
55
+ if (forwarded) {
56
+ return forwarded.split(',')[0]?.trim();
57
+ }
58
+ const realIp = this.request.headers.get('x-real-ip');
59
+ if (realIp) {
60
+ return realIp;
61
+ }
62
+ return undefined;
63
+ }
64
+ /**
65
+ * Set the parsed body (must be called before passing to handler)
66
+ */
67
+ setBody(body) {
68
+ this._body = body;
69
+ }
70
+ /**
71
+ * Get the underlying Deno request object
72
+ */
73
+ get raw() {
74
+ return this.request;
75
+ }
76
+ }
77
+ /**
78
+ * Adapter that converts GenericResponse methods to Deno Response
79
+ */
80
+ export class DenoResponseAdapter {
81
+ _statusCode = 200;
82
+ _headers = new Headers();
83
+ _sent = false;
84
+ _response = null;
85
+ constructor() { }
86
+ status(code) {
87
+ if (!this._sent) {
88
+ this._statusCode = code;
89
+ }
90
+ }
91
+ header(name, value) {
92
+ if (!this._sent) {
93
+ this._headers.set(name, value);
94
+ }
95
+ }
96
+ send(data) {
97
+ if (this._sent) {
98
+ return;
99
+ }
100
+ this._sent = true;
101
+ // Clone headers to ensure they're properly set
102
+ const headers = new Headers(this._headers);
103
+ // Handle empty string (e.g., for CORS preflight 204 responses)
104
+ if (data === '') {
105
+ // 204 No Content responses cannot have a body (not even empty string)
106
+ // Use null for 204, empty string for other status codes
107
+ this._response = new Response(this._statusCode === 204 ? null : '', {
108
+ status: this._statusCode,
109
+ headers,
110
+ });
111
+ return;
112
+ }
113
+ // Create JSON response
114
+ headers.set('Content-Type', 'application/json');
115
+ this._response = new Response(JSON.stringify(data), {
116
+ status: this._statusCode,
117
+ headers,
118
+ });
119
+ }
120
+ stream(generator) {
121
+ if (this._sent) {
122
+ return Promise.resolve();
123
+ }
124
+ this._sent = true;
125
+ // Create SSE stream
126
+ const stream = new ReadableStream({
127
+ async start(controller) {
128
+ try {
129
+ for await (const chunk of generator) {
130
+ const data = `data: ${JSON.stringify(chunk)}\n\n`;
131
+ controller.enqueue(new TextEncoder().encode(data));
132
+ }
133
+ // Send done marker
134
+ const done = 'data: [DONE]\n\n';
135
+ controller.enqueue(new TextEncoder().encode(done));
136
+ controller.close();
137
+ }
138
+ catch (error) {
139
+ console.error('Streaming error:', error);
140
+ controller.error(error);
141
+ }
142
+ },
143
+ });
144
+ // Set SSE headers
145
+ this._headers.set('Content-Type', 'text/event-stream');
146
+ this._headers.set('Cache-Control', 'no-cache');
147
+ this._headers.set('Connection', 'keep-alive');
148
+ this._response = new Response(stream, {
149
+ status: this._statusCode,
150
+ headers: this._headers,
151
+ });
152
+ return Promise.resolve();
153
+ }
154
+ isWritable() {
155
+ return !this._sent;
156
+ }
157
+ /**
158
+ * Get the generated Response object
159
+ */
160
+ getResponse() {
161
+ if (!this._response) {
162
+ // If no response was generated, create an error response
163
+ return new Response('Internal Server Error', { status: 500 });
164
+ }
165
+ return this._response;
166
+ }
167
+ }
168
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/deno/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Deno Handler
3
+ *
4
+ * HTTP request handler for Deno that uses the core handler.
5
+ *
6
+ * @module
7
+ */
8
+ import { CoreHTTPHandler } from 'ai.matey.http.core';
9
+ import { DenoRequestAdapter, DenoResponseAdapter } from './adapter.js';
10
+ /**
11
+ * Create Deno HTTP handler for handling AI chat requests
12
+ *
13
+ * @param bridge - Bridge instance
14
+ * @param options - HTTP listener options
15
+ * @returns Deno HTTP handler function
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { DenoHandler } from 'ai.matey.http/deno';
20
+ *
21
+ * const bridge = new Bridge(frontend, backend);
22
+ *
23
+ * // Create handler
24
+ * const handler = DenoHandler(bridge, {
25
+ * cors: true,
26
+ * streaming: true,
27
+ * });
28
+ *
29
+ * // Use with Deno.serve
30
+ * Deno.serve({ port: 3000 }, handler);
31
+ * ```
32
+ */
33
+ export function DenoHandler(bridge, options = {}) {
34
+ // Create core handler with all business logic
35
+ const { cors, ...restOptions } = options;
36
+ const coreHandler = new CoreHTTPHandler({
37
+ bridge,
38
+ cors: cors === false || cors === undefined ? undefined : cors === true ? {} : cors,
39
+ ...restOptions, // HTTPListenerOptions types are compatible with CoreHandlerOptions at runtime
40
+ });
41
+ // Return Deno HTTP handler
42
+ return async (request, connInfo) => {
43
+ try {
44
+ // Parse JSON body if present (but not for OPTIONS requests)
45
+ const contentType = request.headers.get('content-type') || '';
46
+ const method = request.method;
47
+ let body = null;
48
+ if (method !== 'OPTIONS' && contentType.includes('application/json')) {
49
+ try {
50
+ body = await request.json();
51
+ }
52
+ catch {
53
+ // If JSON parsing fails, leave body as null
54
+ }
55
+ }
56
+ // Create adapters
57
+ const genericReq = new DenoRequestAdapter(request, connInfo);
58
+ genericReq.setBody(body);
59
+ const genericRes = new DenoResponseAdapter();
60
+ // Handle request through core handler
61
+ await coreHandler.handle(genericReq, genericRes);
62
+ // Return the response generated by the adapter
63
+ return genericRes.getResponse();
64
+ }
65
+ catch (error) {
66
+ // Return error response
67
+ console.error('Deno handler error:', error);
68
+ return new Response(JSON.stringify({ error: 'Internal Server Error' }), {
69
+ status: 500,
70
+ headers: { 'Content-Type': 'application/json' },
71
+ });
72
+ }
73
+ };
74
+ }
75
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/deno/handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,WAAW,CACzB,MAAc,EACd,UAA+B,EAAE;IAEjC,8CAA8C;IAC9C,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IAEzC,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC;QACtC,MAAM;QACN,IAAI,EAAE,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;QAClF,GAAI,WAAmB,EAAE,8EAA8E;KACxG,CAAC,CAAC;IAEH,2BAA2B;IAC3B,OAAO,KAAK,EACV,OAAgB,EAChB,QAAiD,EAC9B,EAAE;QACrB,IAAI,CAAC;YACH,4DAA4D;YAC5D,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAC9B,IAAI,IAAI,GAAG,IAAI,CAAC;YAEhB,IAAI,MAAM,KAAK,SAAS,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBACrE,IAAI,CAAC;oBACH,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC9B,CAAC;gBAAC,MAAM,CAAC;oBACP,4CAA4C;gBAC9C,CAAC;YACH,CAAC;YAED,kBAAkB;YAClB,MAAM,UAAU,GAAG,IAAI,kBAAkB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC7D,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAEzB,MAAM,UAAU,GAAG,IAAI,mBAAmB,EAAE,CAAC;YAE7C,sCAAsC;YACtC,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAEjD,+CAA+C;YAC/C,OAAO,UAAU,CAAC,WAAW,EAAE,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,wBAAwB;YACxB,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;YAC5C,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,EAAE;gBACtE,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;aAChD,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Deno HTTP Adapter
3
+ *
4
+ * HTTP adapter for Deno
5
+ *
6
+ * @module
7
+ */
8
+ export * from './adapter.js';
9
+ export * from './handler.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/deno/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Express HTTP Adapter
3
+ *
4
+ * Converts Express Request/Response to GenericRequest/GenericResponse
5
+ *
6
+ * @module
7
+ */
8
+ import { sendSSEHeaders, sendSSEChunk, sendSSEDone } from 'ai.matey.http.core';
9
+ /**
10
+ * Adapter that converts Express Request to GenericRequest
11
+ */
12
+ export class ExpressRequestAdapter {
13
+ req;
14
+ constructor(req) {
15
+ this.req = req;
16
+ }
17
+ get method() {
18
+ return this.req.method || 'GET';
19
+ }
20
+ get url() {
21
+ return this.req.originalUrl || this.req.url || '/';
22
+ }
23
+ get headers() {
24
+ const headers = {};
25
+ for (const [key, value] of Object.entries(this.req.headers)) {
26
+ if (typeof value === 'string') {
27
+ headers[key.toLowerCase()] = value;
28
+ }
29
+ else if (Array.isArray(value)) {
30
+ headers[key.toLowerCase()] = value.join(', ');
31
+ }
32
+ }
33
+ return headers;
34
+ }
35
+ get body() {
36
+ // Express body is already parsed if body-parser middleware is used
37
+ return this.req.body ?? null;
38
+ }
39
+ get params() {
40
+ return this.req.params;
41
+ }
42
+ get query() {
43
+ // Express query can have arrays, so we need to stringify them
44
+ const query = {};
45
+ for (const [key, value] of Object.entries(this.req.query)) {
46
+ if (typeof value === 'string') {
47
+ query[key] = value;
48
+ }
49
+ else if (Array.isArray(value)) {
50
+ const primitives = value.filter((v) => typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean');
51
+ query[key] = primitives.map((v) => v.toString()).join(',');
52
+ }
53
+ else if (value !== undefined && typeof value !== 'object') {
54
+ query[key] = String(value);
55
+ }
56
+ }
57
+ return Object.keys(query).length > 0 ? query : undefined;
58
+ }
59
+ get ip() {
60
+ // Express provides multiple IP sources
61
+ return this.req.ip || this.req.socket?.remoteAddress;
62
+ }
63
+ /**
64
+ * Get the underlying Express request object
65
+ */
66
+ get raw() {
67
+ return this.req;
68
+ }
69
+ }
70
+ /**
71
+ * Adapter that converts GenericResponse methods to Express Response
72
+ */
73
+ export class ExpressResponseAdapter {
74
+ res;
75
+ _statusCode = 200;
76
+ _headersSent = false;
77
+ constructor(res) {
78
+ this.res = res;
79
+ }
80
+ status(code) {
81
+ this._statusCode = code;
82
+ if (!this._headersSent) {
83
+ this.res.status(code);
84
+ }
85
+ }
86
+ header(name, value) {
87
+ if (!this._headersSent) {
88
+ this.res.setHeader(name, value);
89
+ }
90
+ }
91
+ send(data) {
92
+ if (!this.isWritable()) {
93
+ return;
94
+ }
95
+ this._headersSent = true;
96
+ // Handle empty string (e.g., for CORS preflight 204 responses)
97
+ if (data === '') {
98
+ this.res.end();
99
+ return;
100
+ }
101
+ // Express has a built-in json() method
102
+ this.res.status(this._statusCode).json(data);
103
+ }
104
+ async stream(generator) {
105
+ if (!this.isWritable()) {
106
+ return;
107
+ }
108
+ this._headersSent = true;
109
+ // Get the underlying Node.js response for SSE
110
+ const nodeRes = this.res;
111
+ // Set SSE headers
112
+ sendSSEHeaders(nodeRes, {});
113
+ try {
114
+ // Stream chunks
115
+ for await (const chunk of generator) {
116
+ if (!this.isWritable()) {
117
+ break;
118
+ }
119
+ sendSSEChunk(nodeRes, chunk);
120
+ }
121
+ // Send done marker
122
+ if (this.isWritable()) {
123
+ sendSSEDone(nodeRes);
124
+ }
125
+ }
126
+ catch (error) {
127
+ // If error occurs during streaming, we can't change status code
128
+ // Just log and close
129
+ console.error('Streaming error:', error);
130
+ if (this.isWritable()) {
131
+ nodeRes.end();
132
+ }
133
+ }
134
+ }
135
+ isWritable() {
136
+ return !this.res.headersSent && this.res.writable;
137
+ }
138
+ /**
139
+ * Get the underlying Express response object
140
+ */
141
+ get raw() {
142
+ return this.res;
143
+ }
144
+ }
145
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/express/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Express HTTP Adapter
3
+ *
4
+ * HTTP adapter for Express.js
5
+ *
6
+ * @module
7
+ */
8
+ export * from './adapter.js';
9
+ export * from './middleware.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/express/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Express Middleware
3
+ *
4
+ * HTTP request middleware for Express that uses the core handler.
5
+ *
6
+ * @module
7
+ */
8
+ import { CoreHTTPHandler } from 'ai.matey.http.core';
9
+ import { ExpressRequestAdapter, ExpressResponseAdapter } from './adapter.js';
10
+ /**
11
+ * Create Express middleware for handling AI chat requests
12
+ *
13
+ * @param bridge - Bridge instance
14
+ * @param options - HTTP listener options
15
+ * @returns Express middleware function
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import express from 'express';
20
+ * import { ExpressMiddleware } from 'ai.matey.http/express';
21
+ *
22
+ * const app = express();
23
+ * const bridge = new Bridge(frontend, backend);
24
+ *
25
+ * // Use body parser middleware first
26
+ * app.use(express.json());
27
+ *
28
+ * // Add AI chat middleware
29
+ * app.use('/v1/messages', ExpressMiddleware(bridge, {
30
+ * cors: true,
31
+ * streaming: true,
32
+ * }));
33
+ *
34
+ * app.listen(3000);
35
+ * ```
36
+ */
37
+ export function ExpressMiddleware(bridge, options = {}) {
38
+ // Create core handler with all business logic
39
+ const { cors, ...restOptions } = options;
40
+ const coreHandler = new CoreHTTPHandler({
41
+ bridge,
42
+ cors: cors === false || cors === undefined ? undefined : cors === true ? {} : cors,
43
+ ...restOptions, // HTTPListenerOptions types are compatible with CoreHandlerOptions at runtime
44
+ });
45
+ // Return Express middleware
46
+ return async (req, res, next) => {
47
+ try {
48
+ // Create adapters
49
+ const genericReq = new ExpressRequestAdapter(req);
50
+ const genericRes = new ExpressResponseAdapter(res);
51
+ // Handle request through core handler
52
+ await coreHandler.handle(genericReq, genericRes);
53
+ }
54
+ catch (error) {
55
+ // Pass error to Express error handling middleware
56
+ next(error);
57
+ }
58
+ };
59
+ }
60
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/express/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,UAA+B,EAAE;IAEjC,8CAA8C;IAC9C,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IAEzC,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC;QACtC,MAAM;QACN,IAAI,EAAE,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;QAClF,GAAI,WAAmB,EAAE,8EAA8E;KACxG,CAAC,CAAC;IAEH,4BAA4B;IAC5B,OAAO,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAiB,EAAE;QAC9E,IAAI,CAAC;YACH,kBAAkB;YAClB,MAAM,UAAU,GAAG,IAAI,qBAAqB,CAAC,GAAG,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,IAAI,sBAAsB,CAAC,GAAG,CAAC,CAAC;YAEnD,sCAAsC;YACtC,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,kDAAkD;YAClD,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Fastify HTTP Adapter
3
+ *
4
+ * Converts Fastify Request/Reply to GenericRequest/GenericResponse
5
+ *
6
+ * @module
7
+ */
8
+ import { sendSSEHeaders, sendSSEChunk, sendSSEDone } from 'ai.matey.http.core';
9
+ /**
10
+ * Adapter that converts Fastify Request to GenericRequest
11
+ */
12
+ export class FastifyRequestAdapter {
13
+ request;
14
+ constructor(request) {
15
+ this.request = request;
16
+ }
17
+ get method() {
18
+ return this.request.method || 'GET';
19
+ }
20
+ get url() {
21
+ return this.request.url || '/';
22
+ }
23
+ get headers() {
24
+ const headers = {};
25
+ for (const [key, value] of Object.entries(this.request.headers)) {
26
+ if (typeof value === 'string') {
27
+ headers[key.toLowerCase()] = value;
28
+ }
29
+ else if (Array.isArray(value)) {
30
+ headers[key.toLowerCase()] = value.join(', ');
31
+ }
32
+ }
33
+ return headers;
34
+ }
35
+ get body() {
36
+ // Fastify automatically parses JSON body
37
+ return this.request.body ?? null;
38
+ }
39
+ get params() {
40
+ return this.request.params;
41
+ }
42
+ get query() {
43
+ // Fastify query can have arrays, so we need to stringify them
44
+ const query = {};
45
+ for (const [key, value] of Object.entries(this.request.query || {})) {
46
+ if (typeof value === 'string') {
47
+ query[key] = value;
48
+ }
49
+ else if (Array.isArray(value)) {
50
+ query[key] = value.join(',');
51
+ }
52
+ else if (value !== undefined) {
53
+ query[key] = String(value);
54
+ }
55
+ }
56
+ return Object.keys(query).length > 0 ? query : undefined;
57
+ }
58
+ get ip() {
59
+ // Fastify provides IP through request.ip
60
+ return this.request.ip || this.request.socket?.remoteAddress;
61
+ }
62
+ /**
63
+ * Get the underlying Fastify request object
64
+ */
65
+ get raw() {
66
+ return this.request;
67
+ }
68
+ }
69
+ /**
70
+ * Adapter that converts GenericResponse methods to Fastify Reply
71
+ */
72
+ export class FastifyResponseAdapter {
73
+ reply;
74
+ _statusCode = 200;
75
+ _headersSent = false;
76
+ constructor(reply) {
77
+ this.reply = reply;
78
+ }
79
+ status(code) {
80
+ this._statusCode = code;
81
+ if (!this._headersSent) {
82
+ this.reply.code(code);
83
+ }
84
+ }
85
+ header(name, value) {
86
+ if (!this._headersSent) {
87
+ this.reply.header(name, value);
88
+ }
89
+ }
90
+ send(data) {
91
+ if (!this.isWritable()) {
92
+ return;
93
+ }
94
+ this._headersSent = true;
95
+ // Handle empty string (e.g., for CORS preflight 204 responses)
96
+ if (data === '') {
97
+ this.reply.code(this._statusCode).send('');
98
+ return;
99
+ }
100
+ // Fastify automatically JSON-stringifies objects
101
+ this.reply.code(this._statusCode).send(data);
102
+ }
103
+ async stream(generator) {
104
+ if (!this.isWritable()) {
105
+ return;
106
+ }
107
+ this._headersSent = true;
108
+ // Get the underlying Node.js response for SSE
109
+ const nodeRes = this.reply.raw;
110
+ // Set SSE headers
111
+ sendSSEHeaders(nodeRes, {});
112
+ try {
113
+ // Stream chunks
114
+ for await (const chunk of generator) {
115
+ if (!this.isWritable()) {
116
+ break;
117
+ }
118
+ sendSSEChunk(nodeRes, chunk);
119
+ }
120
+ // Send done marker
121
+ if (this.isWritable()) {
122
+ sendSSEDone(nodeRes);
123
+ }
124
+ }
125
+ catch (error) {
126
+ // If error occurs during streaming, we can't change status code
127
+ // Just log and close
128
+ console.error('Streaming error:', error);
129
+ if (this.isWritable()) {
130
+ nodeRes.end();
131
+ }
132
+ }
133
+ }
134
+ isWritable() {
135
+ return !this.reply.sent && !this._headersSent;
136
+ }
137
+ /**
138
+ * Get the underlying Fastify reply object
139
+ */
140
+ get raw() {
141
+ return this.reply;
142
+ }
143
+ }
144
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/fastify/adapter.ts"],"names":[],"mappings":"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"}