@juspay/neurolink 13.8.16 → 13.8.17

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.
@@ -6,6 +6,7 @@ import { logger } from "../../utils/logger.js";
6
6
  import { AlreadyRunningError, ServerAdapterError, ServerStartError, ServerStopError, wrapError, } from "../errors.js";
7
7
  import { BaseServerAdapter } from "../abstract/baseServerAdapter.js";
8
8
  import { isErrorResponse } from "../utils/validation.js";
9
+ import { createBoundedBodyParser } from "../utils/expressBody.js";
9
10
  import { isRawBodyContentType, isWebResponse, readWebResponse, } from "../utils/rawBody.js";
10
11
  /**
11
12
  * Express-specific server adapter
@@ -41,8 +42,10 @@ export class ExpressServerAdapter extends BaseServerAdapter {
41
42
  const bodyLimit = this.config.bodyParser.maxSize ||
42
43
  this.config.bodyParser.jsonLimit ||
43
44
  "10mb";
44
- this.app.use(express.json({ limit: this.config.bodyParser.jsonLimit || bodyLimit }));
45
- this.app.use(express.urlencoded({ extended: true, limit: bodyLimit }));
45
+ const jsonLimit = this.config.bodyParser.jsonLimit || bodyLimit;
46
+ // body-parser drains a body it refuses, so each is read through a bound.
47
+ this.app.use(createBoundedBodyParser(express.json({ limit: jsonLimit }), jsonLimit));
48
+ this.app.use(createBoundedBodyParser(express.urlencoded({ extended: true, limit: bodyLimit }), bodyLimit));
46
49
  // Uploads (multipart, octet-stream, audio/*) reach the route as bytes.
47
50
  this.app.use(express.raw({
48
51
  type: (req) => isRawBodyContentType(req.headers["content-type"]),
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Bounded JSON and form body reads for the Express adapter.
3
+ *
4
+ * `express.json()` and `express.urlencoded()` (body-parser) refuse a body over
5
+ * their limit with a 413, but only after the whole request has been taken off
6
+ * the socket: a declared Content-Length over the limit is seen at once and the
7
+ * body is still drained, and a chunked body is read to its end. Nothing has
8
+ * authenticated the request at that point, so a client could make the server
9
+ * receive any amount of data for the price of one 413.
10
+ *
11
+ * `createBoundedBodyParser` wraps a body-parser middleware so the bytes are
12
+ * read here, up to the limit, and handed to that same middleware to parse. Which
13
+ * requests are parsed, charset handling, strict JSON, the qs options and the
14
+ * error each failure carries all stay body-parser's, because body-parser still
15
+ * makes those decisions: it is asked first, from the headers alone, whether it
16
+ * would read the request, and then parses the bytes it is given. What changes is
17
+ * who reads the socket and what happens at the limit. A body over the limit is
18
+ * refused without reading it (declared Content-Length) or at the limit (chunked,
19
+ * or a compressed body that inflates past it), and the connection is closed so
20
+ * the client stops sending.
21
+ *
22
+ * `express.raw()` (uploads) is not wrapped.
23
+ *
24
+ * @module server/utils/expressBody
25
+ */
26
+ import type { ServerNodeMiddleware } from "../../types/index.js";
27
+ /**
28
+ * Wrap a body-parser middleware (`express.json()`, `express.urlencoded()`) so a
29
+ * body is read only as far as `limit`. `limit` is the one the middleware was
30
+ * built with. A limit that cannot be read as a byte count here is left to the
31
+ * middleware alone.
32
+ */
33
+ export declare function createBoundedBodyParser(parser: ServerNodeMiddleware, limit: string | number | undefined): ServerNodeMiddleware;
@@ -0,0 +1,353 @@
1
+ /**
2
+ * Bounded JSON and form body reads for the Express adapter.
3
+ *
4
+ * `express.json()` and `express.urlencoded()` (body-parser) refuse a body over
5
+ * their limit with a 413, but only after the whole request has been taken off
6
+ * the socket: a declared Content-Length over the limit is seen at once and the
7
+ * body is still drained, and a chunked body is read to its end. Nothing has
8
+ * authenticated the request at that point, so a client could make the server
9
+ * receive any amount of data for the price of one 413.
10
+ *
11
+ * `createBoundedBodyParser` wraps a body-parser middleware so the bytes are
12
+ * read here, up to the limit, and handed to that same middleware to parse. Which
13
+ * requests are parsed, charset handling, strict JSON, the qs options and the
14
+ * error each failure carries all stay body-parser's, because body-parser still
15
+ * makes those decisions: it is asked first, from the headers alone, whether it
16
+ * would read the request, and then parses the bytes it is given. What changes is
17
+ * who reads the socket and what happens at the limit. A body over the limit is
18
+ * refused without reading it (declared Content-Length) or at the limit (chunked,
19
+ * or a compressed body that inflates past it), and the connection is closed so
20
+ * the client stops sending.
21
+ *
22
+ * `express.raw()` (uploads) is not wrapped.
23
+ *
24
+ * @module server/utils/expressBody
25
+ */
26
+ import { Readable } from "node:stream";
27
+ import * as zlib from "node:zlib";
28
+ import { tryParseByteLimit } from "./rawBody.js";
29
+ const noop = () => undefined;
30
+ /** The error body-parser raises for an over-limit body, which the adapter's error handler answers 413. */
31
+ function bodyParserError(status, message, type, details = {}) {
32
+ return Object.assign(new Error(message), {
33
+ status,
34
+ statusCode: status,
35
+ expose: status < 500,
36
+ type,
37
+ ...details,
38
+ });
39
+ }
40
+ const entityTooLarge = (limit, received) => bodyParserError(413, "request entity too large", "entity.too.large", {
41
+ limit,
42
+ ...(received === undefined ? {} : { received }),
43
+ });
44
+ /** A Content-Encoding body-parser inflates, and nothing else. */
45
+ function decompressorFor(encoding) {
46
+ switch (encoding) {
47
+ case "gzip":
48
+ return zlib.createGunzip;
49
+ case "deflate":
50
+ return zlib.createInflate;
51
+ case "br":
52
+ return zlib.createBrotliDecompress;
53
+ case "zstd":
54
+ // Node 22.15 and later.
55
+ return typeof zlib.createZstdDecompress === "function"
56
+ ? zlib.createZstdDecompress
57
+ : undefined;
58
+ default:
59
+ return undefined;
60
+ }
61
+ }
62
+ /** body-parser's own "already handled" test: the request has been read off, or cannot be. */
63
+ const isRequestFinished = (req) => ("upgrade" in req && req.upgrade === true) ||
64
+ !req.socket?.readable ||
65
+ (req.complete && !req.readable);
66
+ /** A request that is already in memory, to hand a body-parser middleware in place of the socket. */
67
+ function bufferedRequest(headers, bytes, body) {
68
+ let pushed = false;
69
+ const stream = new Readable({
70
+ read() {
71
+ if (!pushed) {
72
+ pushed = true;
73
+ if (bytes.length > 0) {
74
+ this.push(bytes);
75
+ }
76
+ this.push(null);
77
+ }
78
+ },
79
+ });
80
+ return Object.assign(stream, { headers, body });
81
+ }
82
+ /**
83
+ * Ask a body-parser middleware what it would do with this request, without
84
+ * giving it a body. It is run on an empty one: what it decides from the headers
85
+ * (not a body, not its type, a charset it refuses) comes back as it would
86
+ * have, and so does what it only finds out when it starts to read (a charset
87
+ * the decoder lacks). The Content-Encoding is left off because inflating is
88
+ * done here, and the Content-Length is zeroed so the declared size, which is
89
+ * checked here, does not stand in the way.
90
+ */
91
+ function askParser(parser, req, res) {
92
+ const headers = { ...req.headers };
93
+ delete headers["content-encoding"];
94
+ delete headers["transfer-encoding"];
95
+ if (req.headers["transfer-encoding"] !== undefined ||
96
+ req.headers["content-length"] !== undefined) {
97
+ headers["content-length"] = "0";
98
+ }
99
+ const before = "body" in req ? req.body : undefined;
100
+ const probe = bufferedRequest(headers, Buffer.alloc(0), before);
101
+ return new Promise((resolve) => {
102
+ let synchronous = true;
103
+ parser(probe, res, (error) => {
104
+ if (error !== undefined) {
105
+ resolve({ kind: "reject", error, beforeRead: synchronous });
106
+ }
107
+ else if (probe.body !== before) {
108
+ resolve({ kind: "parse" });
109
+ }
110
+ else {
111
+ resolve({ kind: "skip", body: probe.body });
112
+ }
113
+ });
114
+ synchronous = false;
115
+ });
116
+ }
117
+ /**
118
+ * How far past the limit the raw bytes of a compressed body may run. The limit
119
+ * is on what a body inflates to, but the bytes on the wire are capped too:
120
+ * empty gzip members inflate to nothing, and so do the zeros Node lets follow a
121
+ * complete gzip stream, so without a cap a stream of either is read until the
122
+ * client stops. The slack covers the framing a real encoder adds (deflate's
123
+ * stored blocks carry 5 bytes per 64 KiB).
124
+ */
125
+ const COMPRESSED_WIRE_SLACK = 64 * 1024;
126
+ /**
127
+ * Read a request body, refusing more than `maxBytes` (of what is inflated, when
128
+ * the request is compressed, with the raw bytes capped at `maxBytes` plus
129
+ * {@link COMPRESSED_WIRE_SLACK}). Reading stops at the limit and the request is
130
+ * left paused, not drained. Events rather than `for await`: leaving an async
131
+ * iterator early destroys the request, and its socket with it, before an answer
132
+ * can be sent.
133
+ */
134
+ function readBounded(req, maxBytes, decompressor) {
135
+ return new Promise((resolve, reject) => {
136
+ const source = decompressor ?? req;
137
+ const chunks = [];
138
+ const wireCap = maxBytes + COMPRESSED_WIRE_SLACK;
139
+ let received = 0;
140
+ let wire = 0;
141
+ // A compressed body is complete; the rest of the request is being read off.
142
+ let draining = false;
143
+ let settled = false;
144
+ const release = () => {
145
+ source.off("data", onData);
146
+ source.off("end", onEnd);
147
+ source.off("error", onFail);
148
+ req.off("data", onWire);
149
+ req.off("end", onRequestEnd);
150
+ req.off("error", onFail);
151
+ req.off("close", onClose);
152
+ };
153
+ const detachDecompressor = () => {
154
+ if (decompressor) {
155
+ req.unpipe(decompressor);
156
+ decompressor.on("error", noop);
157
+ decompressor.destroy();
158
+ }
159
+ };
160
+ const stop = () => {
161
+ detachDecompressor();
162
+ req.pause();
163
+ };
164
+ const settle = (outcome) => {
165
+ if (!settled) {
166
+ settled = true;
167
+ release();
168
+ outcome();
169
+ }
170
+ };
171
+ const finish = (closeConnection) => {
172
+ settle(() => resolve({ bytes: Buffer.concat(chunks), closeConnection }));
173
+ };
174
+ const aborted = () => bodyParserError(400, "request aborted", "request.aborted", {
175
+ code: "ECONNABORTED",
176
+ received,
177
+ });
178
+ function onData(chunk) {
179
+ const buffer = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
180
+ received += buffer.length;
181
+ if (received > maxBytes) {
182
+ settle(() => {
183
+ stop();
184
+ reject(entityTooLarge(maxBytes, received));
185
+ });
186
+ return;
187
+ }
188
+ chunks.push(buffer);
189
+ }
190
+ function onWire(chunk) {
191
+ wire += chunk.length;
192
+ if (wire <= wireCap) {
193
+ return;
194
+ }
195
+ if (draining) {
196
+ // The body is whole; what keeps arriving is not part of it.
197
+ req.pause();
198
+ finish(true);
199
+ return;
200
+ }
201
+ settle(() => {
202
+ stop();
203
+ reject(entityTooLarge(maxBytes, wire));
204
+ });
205
+ }
206
+ function onEnd() {
207
+ if (!decompressor) {
208
+ finish(false);
209
+ return;
210
+ }
211
+ // The rest of the request, if any, is not part of the body: read it off
212
+ // up to the cap, so the connection can be kept.
213
+ detachDecompressor();
214
+ if (req.complete) {
215
+ req.resume();
216
+ finish(false);
217
+ return;
218
+ }
219
+ draining = true;
220
+ source.off("data", onData);
221
+ source.off("end", onEnd);
222
+ source.off("error", onFail);
223
+ req.on("end", onRequestEnd);
224
+ req.resume();
225
+ }
226
+ function onRequestEnd() {
227
+ finish(false);
228
+ }
229
+ function onFail(error) {
230
+ if (draining) {
231
+ finish(true);
232
+ return;
233
+ }
234
+ settle(() => {
235
+ stop();
236
+ reject(error);
237
+ });
238
+ }
239
+ function onClose() {
240
+ // A request that arrived whole closes once it has been read, which for a
241
+ // compressed one can be before the inflating has finished.
242
+ if (req.complete) {
243
+ return;
244
+ }
245
+ if (draining) {
246
+ finish(true);
247
+ return;
248
+ }
249
+ settle(() => {
250
+ stop();
251
+ reject(aborted());
252
+ });
253
+ }
254
+ if (req.destroyed && !req.complete) {
255
+ settle(() => reject(aborted()));
256
+ return;
257
+ }
258
+ source.on("data", onData);
259
+ source.on("end", onEnd);
260
+ source.on("error", onFail);
261
+ req.on("close", onClose);
262
+ if (decompressor) {
263
+ req.on("error", onFail);
264
+ req.on("data", onWire);
265
+ req.pipe(decompressor);
266
+ }
267
+ });
268
+ }
269
+ /** Answer the request with `error` and close the connection, so a client still sending stops. */
270
+ function refuse(res, next, error) {
271
+ if (!res.headersSent) {
272
+ res.setHeader("Connection", "close");
273
+ }
274
+ next(error);
275
+ }
276
+ async function parseBounded(parser, maxBytes, req, res, next) {
277
+ try {
278
+ if (isRequestFinished(req)) {
279
+ next();
280
+ return;
281
+ }
282
+ const verdict = await askParser(parser, req, res);
283
+ if (verdict.kind === "skip") {
284
+ req.body = verdict.body;
285
+ next();
286
+ return;
287
+ }
288
+ if (verdict.kind === "reject" && verdict.beforeRead) {
289
+ refuse(res, next, verdict.error);
290
+ return;
291
+ }
292
+ const encoding = (req.headers["content-encoding"] || "identity").toLowerCase();
293
+ const inflate = encoding === "identity" ? undefined : decompressorFor(encoding);
294
+ if (encoding !== "identity" && !inflate) {
295
+ refuse(res, next, bodyParserError(415, `unsupported content encoding "${encoding}"`, "encoding.unsupported", { encoding }));
296
+ return;
297
+ }
298
+ // Compressed, the declared length is the compressed size, which says
299
+ // nothing about the body.
300
+ const declared = Number.parseInt(String(req.headers["content-length"]), 10);
301
+ if (!inflate && declared > maxBytes) {
302
+ refuse(res, next, entityTooLarge(maxBytes));
303
+ return;
304
+ }
305
+ if (verdict.kind === "reject") {
306
+ refuse(res, next, verdict.error);
307
+ return;
308
+ }
309
+ const before = "body" in req ? req.body : undefined;
310
+ let read;
311
+ try {
312
+ read = await readBounded(req, maxBytes, inflate?.());
313
+ }
314
+ catch (error) {
315
+ refuse(res, next, error);
316
+ return;
317
+ }
318
+ if (read.closeConnection && !res.headersSent) {
319
+ res.setHeader("Connection", "close");
320
+ }
321
+ const { bytes } = read;
322
+ const headers = { ...req.headers, "content-length": String(bytes.length) };
323
+ delete headers["content-encoding"];
324
+ delete headers["transfer-encoding"];
325
+ const replay = bufferedRequest(headers, bytes, before);
326
+ parser(replay, res, (error) => {
327
+ if (error !== undefined) {
328
+ next(error);
329
+ return;
330
+ }
331
+ req.body = replay.body;
332
+ next();
333
+ });
334
+ }
335
+ catch (error) {
336
+ next(error);
337
+ }
338
+ }
339
+ /**
340
+ * Wrap a body-parser middleware (`express.json()`, `express.urlencoded()`) so a
341
+ * body is read only as far as `limit`. `limit` is the one the middleware was
342
+ * built with. A limit that cannot be read as a byte count here is left to the
343
+ * middleware alone.
344
+ */
345
+ export function createBoundedBodyParser(parser, limit) {
346
+ const maxBytes = tryParseByteLimit(limit);
347
+ if (maxBytes === undefined) {
348
+ return parser;
349
+ }
350
+ return (req, res, next) => {
351
+ void parseBounded(parser, maxBytes, req, res, next);
352
+ };
353
+ }
@@ -2,6 +2,8 @@
2
2
  * Server Adapter Types
3
3
  * Comprehensive type system for NeuroLink server adapters
4
4
  */
5
+ import type { IncomingHttpHeaders, IncomingMessage, ServerResponse as NodeServerResponse } from "node:http";
6
+ import type { Readable } from "node:stream";
5
7
  import type { ExternalServerManager } from "../mcp/externalServerManager.js";
6
8
  import type { MCPToolRegistry } from "../mcp/toolRegistry.js";
7
9
  import type { NeuroLink } from "../neurolink.js";
@@ -185,6 +187,53 @@ export type RequiredBodyParserConfig = {
185
187
  rawMaxSize: string;
186
188
  urlEncoded: boolean;
187
189
  };
190
+ /**
191
+ * The request a body-parser middleware is handed in place of the real one: a
192
+ * stream of bytes that were already read, with the headers the parser decides
193
+ * from. `body` is where the parser leaves its result, as on a real request.
194
+ */
195
+ export type ServerBufferedRequest = Readable & {
196
+ headers: IncomingHttpHeaders;
197
+ body: unknown;
198
+ };
199
+ /**
200
+ * A body read as far as its limit: the bytes, and whether the connection is to
201
+ * be closed after the answer. That is the case when a compressed body was
202
+ * complete but the request kept sending past the cap on raw bytes, which are
203
+ * then left unread.
204
+ */
205
+ export type ServerBoundedBodyRead = {
206
+ bytes: Buffer;
207
+ closeConnection: boolean;
208
+ };
209
+ /** A Node request as a body-parser middleware sees it: `body` is where it leaves what it parsed. */
210
+ export type ServerParsedNodeRequest = IncomingMessage & {
211
+ body?: unknown;
212
+ };
213
+ /**
214
+ * A body-parser middleware (`express.json()`, `express.urlencoded()`) as
215
+ * body-parser types it: Node's request and response, and a `next` that takes
216
+ * an error. Typed without Express, which is an optional peer, so the published
217
+ * declarations do not import it.
218
+ */
219
+ export type ServerNodeMiddleware = (req: ServerParsedNodeRequest, res: NodeServerResponse, next: (error?: unknown) => void) => void;
220
+ /**
221
+ * What a body-parser middleware decides about a request, asked before any of
222
+ * its body is read: leave it alone, parse it, or refuse it. A refusal made
223
+ * before the parser would read anything has `beforeRead` set; one the parser
224
+ * only reaches once it starts to read (a charset the decoder cannot handle)
225
+ * has not.
226
+ */
227
+ export type ServerBodyParserVerdict = {
228
+ kind: "skip";
229
+ body: unknown;
230
+ } | {
231
+ kind: "parse";
232
+ } | {
233
+ kind: "reject";
234
+ error: unknown;
235
+ beforeRead: boolean;
236
+ };
188
237
  /**
189
238
  * Logging configuration
190
239
  */
@@ -7811,7 +7811,7 @@
7811
7811
  {"objectID":"dee68d2efd01a80eb4a442ec7f72d40d414182b8ee8036638126c7e48f9a745c","title":"4. Respect Retry-After Headers","url":"/docs/guides/server-adapters/errors#4-respect-retry-after-headers","content":"When handling RateLimitError, honor the retryAfterMs:","hierarchy":{"lvl0":"Guides","lvl1":"Error Handling","lvl2":"4. Respect Retry-After Headers","lvl3":""}},
7812
7812
  {"objectID":"af5a0269b91a605247991a222cba64afe694b0045fa4a74aa70a7aba01040a9c","title":"5. Log Appropriately by Severity","url":"/docs/guides/server-adapters/errors#5-log-appropriately-by-severity","content":"5. Log Appropriately by Severity","hierarchy":{"lvl0":"Guides","lvl1":"Error Handling","lvl2":"5. Log Appropriately by Severity","lvl3":""}},
7813
7813
  {"objectID":"6de13080daf8a055a6de3bee97117d3618cbc7b3f61be0c48f17e957ff0b4a88","title":"Related Documentation","url":"/docs/guides/server-adapters/errors#related-documentation","content":"Server Adapters Overview - Getting started with server adapters\nSecurity Best Practices - Authentication and authorization\nConfiguration Reference - Full configuration options\nDeployment Guide - Production deployment strategies","hierarchy":{"lvl0":"Guides","lvl1":"Error Handling","lvl2":"Related Documentation","lvl3":""}},
7814
- {"objectID":"d86a2f773105827bac17ead4d527ff7188a4489c218c4208152663b89b14565c","title":"Express Adapter","url":"/docs/guides/server-adapters/express","content":"Express Adapter\n\nThe most popular Node.js web framework\n\nExpress is a minimal and flexible Node.js web framework that provides a robust set of features for building web applications and APIs. It has the largest ecosystem of middleware and is widely used in production.\n\nWhy Express?\n\n| Feature | Benefit |\n| --------------------- | ----------------------------------------------- |\n| Mature ecosystem | Thousands of middleware packages available |\n| Well-documented | Extensive documentation and community resources |\n| Familiar API | Most Node.js developers already know Express |\n| Flexible | Unopinionated, adapt to any architecture |\n| Production-proven | Powers millions of applications worldwide |\n| Easy migration | Integrate NeuroLink into existing Express apps |\n\nExpress is ideal when you have an existing Express application or prefer its familiar middleware patterns.\n\nCLI Usage\n\nStart an Express server via CLI:\n\nQuick Start\n\nInstallation\n\nExpress must be installed separately alongside NeuroLink:\n\nBasic Usage\n\nTest the Server\n\nAccessing the Express App\n\nFor advanced customization, you can access the underlying Express application:\n\nConfiguration Options\n\nFull Configuration Example\n\nMiddleware Integration\n\nUsing NeuroLink Middleware\n\nUsing Express-Native Middleware\n\nStreaming Responses\n\nExpress supports streaming through Server-Sent Events (SSE):\n\nCustom Streaming Route\n\nAbort Signal Handling\n\nThe abort signal middleware allows detecting when clients disconnect during long-running requests. NeuroLink provides both a universal middleware and an Express-specific implementation.\n\nUsing Abort Signal Middleware\n\nUse Cases\n\nThe abort signal middleware is useful for:\nLong-running AI generation - Cancel generation when client disconnects\nStreaming responses - Stop producing chunks when client leaves\nDatabase queries - Cancel queries that support abort signals\nExternal API calls - Pass signal to fetch/axios for cancellation\n\nNative Express Approach\n\nFor simpler cases, you can use Express's native socket events:\n\nFor streaming requests, the adapter automatically detects client disconnection and stops the stream to avoid unnecessary processing.\n\nError Handling\n\nCustom Error Handler\n\nIntegrating with Existing Express Apps\n\nIf you already have an Express application, you can integrate NeuroLink routes:\n\nTesting\n\nUnit Testing with Supertest\n\nProduction Checklist\n[ ] Configure environment variables securely\n[ ] Set appropriate CORS origins (not *)\n[ ] Enable rate limiting with reasonable limits\n[ ] Add authentication middleware\n[ ] Configure request timeouts\n[ ] Set body size limits\n[ ] Enable compression (gzip/brotli)\n[ ] Add security headers (helmet)\n[ ] Configure logging with appropriate level\n[ ] Set up health check monitoring\n[ ] Configure error tracking (Sentry, etc.)\n[ ] Use a process manager (PM2, systemd)\n\nRelated Documentation\nServer Adapters Overview - Getting started with server adapters\nConfiguration Reference - Full configuration options\nHono Adapter - Compare with Hono adapter\nFastify Adapter - Compare with Fastify adapter\nSecurity Best Practices - Authentication patterns\n\nAdditional Resources\nExpress Documentation - Official Express documentation\nExpress Middleware - Popular middleware packages\nExpress Security Best Practices - Security guidelines\n\nNeed Help? Join our GitHub Discussions or open an issue.","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"","lvl3":""}},
7814
+ {"objectID":"d86a2f773105827bac17ead4d527ff7188a4489c218c4208152663b89b14565c","title":"Express Adapter","url":"/docs/guides/server-adapters/express","content":"Express Adapter\n\nThe most popular Node.js web framework\n\nExpress is a minimal and flexible Node.js web framework that provides a robust set of features for building web applications and APIs. It has the largest ecosystem of middleware and is widely used in production.\n\nWhy Express?\n\n| Feature | Benefit |\n| --------------------- | ----------------------------------------------- |\n| Mature ecosystem | Thousands of middleware packages available |\n| Well-documented | Extensive documentation and community resources |\n| Familiar API | Most Node.js developers already know Express |\n| Flexible | Unopinionated, adapt to any architecture |\n| Production-proven | Powers millions of applications worldwide |\n| Easy migration | Integrate NeuroLink into existing Express apps |\n\nExpress is ideal when you have an existing Express application or prefer its familiar middleware patterns.\n\nCLI Usage\n\nStart an Express server via CLI:\n\nQuick Start\n\nInstallation\n\nExpress must be installed separately alongside NeuroLink:\n\nBasic Usage\n\nTest the Server\n\nAccessing the Express App\n\nFor advanced customization, you can access the underlying Express application:\n\nConfiguration Options\n\nFull Configuration Example\n\nRequest body limits\n\nbodyParser.jsonLimit bounds JSON bodies and bodyParser.maxSize bounds url-encoded forms. Both default to 10mb, and raising either one is honoured. Uploads (multipart/form-data, application/octet-stream, audio/*) are bounded by bodyParser.rawMaxSize, which defaults to maxSize when that is set and to 64mb otherwise.\n\nA JSON or url-encoded form body over its limit is answered 413 with error.code set to PAYLOAD_TOO_LARGE and error.message set to request entity too large, before any middleware or route runs, and the connection is closed so the client stops sending. The body is not read past the limit: a declared Content-Length over the limit is refused without reading the body, and a body sent without one (chunked) is read only as far as the limit. For a compressed body (Content-Encoding: gzip, deflate, br or zstd) the limit applies to the inflated size, and reading stops once the body has inflated past it.\n\nThe bytes are still parsed by express.json() and express.urlencoded() (body-parser), so which requests are parsed, how charsets are decoded, strict JSON, and the qs parsing of forms are unchanged. Anything body-parser refuses other than a body that is too large (a malformed or scalar JSON body, an unsupported charset or Content-Encoding, too many form parameters) is answered 500 with error.code set to INTERNAL_ERROR, as before.\n\nMiddleware Integration\n\nUsing NeuroLink Middleware\n\nUsing Express-Native Middleware\n\nStreaming Responses\n\nExpress supports streaming through Server-Sent Events (SSE):\n\nCustom Streaming Route\n\nAbort Signal Handling\n\nThe abort signal middleware allows detecting when clients disconnect during long-running requests. NeuroLink provides both a universal middleware and an Express-specific implementation.\n\nUsing Abort Signal Middleware\n\nUse Cases\n\nThe abort signal middleware is useful for:\nLong-running AI generation - Cancel generation when client disconnects\nStreaming responses - Stop producing chunks when client leaves\nDatabase queries - Cancel queries that support abort signals\nExternal API calls - Pass signal to fetch/axios for cancellation\n\nNative Express Approach\n\nFor simpler cases, you can use Express's native socket events:\n\nFor streaming requests, the adapter automatically detects client disconnection and stops the stream to avoid unnecessary processing.\n\nError Handling\n\nCustom Error Handler\n\nIntegrating with Existing Express Apps\n\nIf you already have an Express application, you can integrate NeuroLink routes:\n\nTesting\n\nUnit Testing with Supertest\n\nProduction Checklist\n[ ] Configure environment variables securely\n[ ] Set appropriate CORS origins (not *)\n[ ] Enable rate limiting with reasonable limits\n[ ] Add authentication middleware\n[ ] Configure request timeouts\n[ ] Set body size limits\n[ ] Enable compression (gzip/brotli)\n[ ] Add security headers (helmet)\n[ ] Configure logging with appropriate level\n[ ] Set up health check monitoring\n[ ] Configure error tracking (Sentry, etc.)\n[ ] Use a process manager (PM2, systemd)\n\nRelated Documentation\nServer Adapters Overview - Getting started with server adapters\nConfiguration Reference - Full configuration options\nHono Adapter - Compare with Hono adapter\nFastify Adapter - Compare with Fastify adapter\nSecurity Best Practices - Authentication patterns\n\nAdditional Resources\nExpress Documentation - Official Express documentation\nExpress Middleware - Popular middleware packages\nExpress Security Best Practices - Security guidelines\n\nNeed Help? Join our GitHub Discussions or open an issue.","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"","lvl3":""}},
7815
7815
  {"objectID":"3a0b46a625e8077c402e2fae808252ee0b790e25915b781aab36e0043e0c95ff","title":"Express Adapter","url":"/docs/guides/server-adapters/express#express-adapter","content":"The most popular Node.js web framework\n\nExpress is a minimal and flexible Node.js web framework that provides a robust set of features for building web applications and APIs. It has the largest ecosystem of middleware and is widely used in production.","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"Express Adapter","lvl3":""}},
7816
7816
  {"objectID":"05122ccefbae0eefb95cc5da06fccfdf4d33b0d5afa177ae7b75f9745d2a23cf","title":"Why Express?","url":"/docs/guides/server-adapters/express#why-express","content":"| Feature | Benefit |\n| --------------------- | ----------------------------------------------- |\n| Mature ecosystem | Thousands of middleware packages available |\n| Well-documented | Extensive documentation and community resources |\n| Familiar API | Most Node.js developers already know Express |\n| Flexible | Unopinionated, adapt to any architecture |\n| Production-proven | Powers millions of applications worldwide |\n| Easy migration | Integrate NeuroLink into existing Express apps |\n\nExpress is ideal when you have an existing Express application or prefer its familiar middleware patterns.","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"Why Express?","lvl3":""}},
7817
7817
  {"objectID":"a509b1b55a5ad6b22c14631c5be63ad50e2d0c1fd7895d7fc7ed3e89c96b31de","title":"CLI Usage","url":"/docs/guides/server-adapters/express#cli-usage","content":"Start an Express server via CLI:","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"CLI Usage","lvl3":""}},
@@ -7820,6 +7820,7 @@
7820
7820
  {"objectID":"c8665ba8299a709bf777f2fea4a5c30034f120434206161f412de05e70046f83","title":"Test the Server","url":"/docs/guides/server-adapters/express#test-the-server","content":"Test the Server","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"Test the Server","lvl3":""}},
7821
7821
  {"objectID":"43d29d1695eb139f97358faa91162964159fb4687d5ab7d49a961cec1a6c257e","title":"Accessing the Express App","url":"/docs/guides/server-adapters/express#accessing-the-express-app","content":"For advanced customization, you can access the underlying Express application:","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"Accessing the Express App","lvl3":""}},
7822
7822
  {"objectID":"e287cd8271a5e9e82a98ba6038721c91c3d49b8a7c6fd588f9b5309953f1c489","title":"Full Configuration Example","url":"/docs/guides/server-adapters/express#full-configuration-example","content":"Full Configuration Example","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"Full Configuration Example","lvl3":""}},
7823
+ {"objectID":"27bf2e9da638509164e8ac21d64b5e36f101deaa75f464fcadcb3e4f4057ced2","title":"Request body limits","url":"/docs/guides/server-adapters/express#request-body-limits","content":"bodyParser.jsonLimit bounds JSON bodies and bodyParser.maxSize bounds url-encoded forms. Both default to 10mb, and raising either one is honoured. Uploads (multipart/form-data, application/octet-stream, audio/*) are bounded by bodyParser.rawMaxSize, which defaults to maxSize when that is set and to 64mb otherwise.\n\nA JSON or url-encoded form body over its limit is answered 413 with error.code set to PAYLOAD_TOO_LARGE and error.message set to request entity too large, before any middleware or route runs, and the connection is closed so the client stops sending. The body is not read past the limit: a declared Content-Length over the limit is refused without reading the body, and a body sent without one (chunked) is read only as far as the limit. For a compressed body (Content-Encoding: gzip, deflate, br or zstd) the limit applies to the inflated size, and reading stops once the body has inflated past it.\n\nThe bytes are still parsed by express.json() and express.urlencoded() (body-parser), so which requests are parsed, how charsets are decoded, strict JSON, and the qs parsing of forms are unchanged. Anything body-parser refuses other than a body that is too large (a malformed or scalar JSON body, an unsupported charset or Content-Encoding, too many form parameters) is answered 500 with error.code set to INTERNAL_ERROR, as before.","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"Request body limits","lvl3":""}},
7823
7824
  {"objectID":"05db65d092e325a4ae7bbd23890cc3f6ca3e61561a196d00f3199c158851cc4e","title":"Using NeuroLink Middleware","url":"/docs/guides/server-adapters/express#using-neurolink-middleware","content":"Using NeuroLink Middleware","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"Using NeuroLink Middleware","lvl3":""}},
7824
7825
  {"objectID":"b4c7f350e63e32f17c10ecaade63856d9baac07c72d93a07083e10c1cac4fc01","title":"Using Express-Native Middleware","url":"/docs/guides/server-adapters/express#using-express-native-middleware","content":"Using Express-Native Middleware","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"Using Express-Native Middleware","lvl3":""}},
7825
7826
  {"objectID":"3ef5b221323ada6a9627c762b6f84cad3c88454030f6b5496da6a84dba4801a0","title":"Streaming Responses","url":"/docs/guides/server-adapters/express#streaming-responses","content":"Express supports streaming through Server-Sent Events (SSE):","hierarchy":{"lvl0":"Guides","lvl1":"Express Adapter","lvl2":"Streaming Responses","lvl3":""}},
@@ -7859,7 +7860,7 @@
7859
7860
  {"objectID":"ce64f640074b8e60ee4bd472c5c1e5a246d0c373e06b5c046eae0db635733ba5","title":"Production Checklist","url":"/docs/guides/server-adapters/fastify#production-checklist","content":"[ ] Configure environment variables securely\n[ ] Set appropriate CORS origins (not *)\n[ ] Enable rate limiting with reasonable limits\n[ ] Add authentication middleware\n[ ] Configure request timeouts\n[ ] Set body size limits\n[ ] Enable compression (@fastify/compress)\n[ ] Add security headers (@fastify/helmet)\n[ ] Configure logging with appropriate level\n[ ] Set up health check monitoring\n[ ] Configure error tracking (Sentry, etc.)\n[ ] Use schema validation for all routes\n[ ] Enable JSON schema compilation caching","hierarchy":{"lvl0":"Guides","lvl1":"Fastify Adapter","lvl2":"Production Checklist","lvl3":""}},
7860
7861
  {"objectID":"96060a0ae3f9dfb112daf783ff1f49d405316b318d40fdb38c9e9b3a3f4dc377","title":"Related Documentation","url":"/docs/guides/server-adapters/fastify#related-documentation","content":"Server Adapters Overview - Getting started with server adapters\nConfiguration Reference - Full configuration options\nHono Adapter - Compare with Hono adapter\nExpress Adapter - Compare with Express adapter\nSecurity Best Practices - Authentication patterns","hierarchy":{"lvl0":"Guides","lvl1":"Fastify Adapter","lvl2":"Related Documentation","lvl3":""}},
7861
7862
  {"objectID":"84a68aab0ea6da1d4500a0e89cffad25af13dfb8f7c11c0466d2a5cc2160f2c2","title":"Additional Resources","url":"/docs/guides/server-adapters/fastify#additional-resources","content":"Fastify Documentation - Official Fastify documentation\nFastify Plugins - Official and community plugins\nFastify Performance - Performance tuning\n\nNeed Help? Join our GitHub Discussions or open an issue.","hierarchy":{"lvl0":"Guides","lvl1":"Fastify Adapter","lvl2":"Additional Resources","lvl3":""}},
7862
- {"objectID":"cd85d95041216458a7ff86a558a33685239f0e7c062584b10c910a1071c70385","title":"Hono Adapter","url":"/docs/guides/server-adapters/hono","content":"Hono Adapter\n\nThe recommended framework for NeuroLink server adapters\n\nHono is a lightweight, ultrafast web framework designed for the edge. It runs on virtually any JavaScript runtime including Node.js, Deno, Bun, Cloudflare Workers, and more.\n\nWhy Hono?\n\n| Feature | Benefit |\n| ----------------------- | ------------------------------------------------------------------------- |\n| Multi-runtime | Deploy to Node.js, Deno, Bun, Cloudflare Workers, Vercel Edge, AWS Lambda |\n| Ultrafast | Minimal overhead, optimized router with RegExpRouter |\n| TypeScript-first | Full type safety out of the box |\n| Tiny footprint | ~14KB minified, no dependencies |\n| Built-in middleware | CORS, compression, ETag, secure headers included |\n| Web Standards | Uses Fetch API, Request/Response objects |\n\nHono is the default and recommended framework for NeuroLink server adapters.\n\nCLI Usage\n\nStart a Hono server via CLI:\n\nQuick Start\n\nInstallation\n\nHono is included with NeuroLink - no additional installation required.\n\nBasic Usage\n\nTest the Server\n\nAccessing the Hono App\n\nFor advanced customization, you can access the underlying Hono instance:\n\nConfiguration Options\n\nFull Configuration Example\n\nRequest body limits\n\nbodyParser.jsonLimit bounds JSON bodies and bodyParser.maxSize bounds url-encoded forms. Both default to 10mb, as on the Express, Fastify and Koa adapters, and raising either one is honoured. Uploads (multipart/form-data, application/octet-stream, audio/*) are bounded by bodyParser.rawMaxSize, which defaults to maxSize when that is set and to 64mb otherwise.\n\nA JSON or url-encoded form body over its limit is answered 413 with error.code set to PAYLOAD_TOO_LARGE, before any middleware or route runs. A declared Content-Length over the limit is refused without reading the body, and a body sent without one is read only as far as the limit. An upload over the limit still reaches its route, which answers in its own wire format.\n\nMiddleware Integration\n\nUsing NeuroLink Middleware\n\nUsing Hono Built-in Middleware\n\nStreaming Responses\n\nHono has excellent streaming support, which NeuroLink leverages for real-time AI responses:\n\nCustom Streaming Route\n\nError Handling\n\nCustom Error Handler\n\nPerformance Tips\nUse the RegExpRouter (Default)\n\nHono uses RegExpRouter by default, which is the fastest router. No configuration needed.\nEnable Compression\nUse ETag for Caching\nMinimize Middleware Chain\n\nOnly use middleware where needed:\nUse Streaming for Long Responses\n\nAlways use the streaming endpoint for AI generation to avoid timeouts:\n\nEdge Runtime Deployment\n\nCloudflare Workers\n\nVercel Edge Functions\n\nDeno Deploy\n\nTesting\n\nUnit Testing with Hono Test Client\n\nProduction Checklist\n[ ] Configure environment variables securely\n[ ] Set appropriate CORS origins (not *)\n[ ] Enable rate limiting with reasonable limits\n[ ] Add authentication middleware\n[ ] Configure request timeouts\n[ ] Set body size limits\n[ ] Enable compression\n[ ] Add security headers\n[ ] Configure logging with appropriate level\n[ ] Set up health check monitoring\n[ ] Configure error tracking (Sentry, etc.)\n\nRelated Documentation\nServer Adapters Overview - Getting started with server adapters\nConfiguration Reference - Full configuration options\nExpress Adapter - Compare with Express adapter\nSecurity Best Practices - Authentication patterns\nStreaming Guide - Real-time streaming with SSE and NDJSON\n\nAdditional Resources\nHono Documentation - Official Hono documentation\nHono Middleware - Built-in middleware\nHono Examples - Example applications\n\nNeed Help? Join our GitHub Discussions or open an issue.","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"","lvl3":""}},
7863
+ {"objectID":"cd85d95041216458a7ff86a558a33685239f0e7c062584b10c910a1071c70385","title":"Hono Adapter","url":"/docs/guides/server-adapters/hono","content":"Hono Adapter\n\nThe recommended framework for NeuroLink server adapters\n\nHono is a lightweight, ultrafast web framework designed for the edge. It runs on virtually any JavaScript runtime including Node.js, Deno, Bun, Cloudflare Workers, and more.\n\nWhy Hono?\n\n| Feature | Benefit |\n| ----------------------- | ------------------------------------------------------------------------- |\n| Multi-runtime | Deploy to Node.js, Deno, Bun, Cloudflare Workers, Vercel Edge, AWS Lambda |\n| Ultrafast | Minimal overhead, optimized router with RegExpRouter |\n| TypeScript-first | Full type safety out of the box |\n| Tiny footprint | ~14KB minified, no dependencies |\n| Built-in middleware | CORS, compression, ETag, secure headers included |\n| Web Standards | Uses Fetch API, Request/Response objects |\n\nHono is the default and recommended framework for NeuroLink server adapters.\n\nCLI Usage\n\nStart a Hono server via CLI:\n\nQuick Start\n\nInstallation\n\nHono is included with NeuroLink - no additional installation required.\n\nBasic Usage\n\nTest the Server\n\nAccessing the Hono App\n\nFor advanced customization, you can access the underlying Hono instance:\n\nConfiguration Options\n\nFull Configuration Example\n\nRequest body limits\n\nbodyParser.jsonLimit bounds JSON bodies and bodyParser.maxSize bounds url-encoded forms. Both default to 10mb, as on the Express, Fastify and Koa adapters, and raising either one is honoured. Uploads (multipart/form-data, application/octet-stream, audio/*) are bounded by bodyParser.rawMaxSize, which defaults to maxSize when that is set and to 64mb otherwise.\n\nA JSON or url-encoded form body over its limit is answered 413 with error.code set to PAYLOAD_TOO_LARGE, before any middleware or route runs. A declared Content-Length over the limit is refused without reading the body, and a body sent without one is read only as far as the limit. An upload over the limit still reaches its route, which answers in its own wire format.\n\nThe Express adapter stops at the limit the same way (see \"Request body limits\" in its guide). Its 413 carries the message request entity too large, where Hono's names the limit in bytes.\n\nMiddleware Integration\n\nUsing NeuroLink Middleware\n\nUsing Hono Built-in Middleware\n\nStreaming Responses\n\nHono has excellent streaming support, which NeuroLink leverages for real-time AI responses:\n\nCustom Streaming Route\n\nError Handling\n\nCustom Error Handler\n\nPerformance Tips\nUse the RegExpRouter (Default)\n\nHono uses RegExpRouter by default, which is the fastest router. No configuration needed.\nEnable Compression\nUse ETag for Caching\nMinimize Middleware Chain\n\nOnly use middleware where needed:\nUse Streaming for Long Responses\n\nAlways use the streaming endpoint for AI generation to avoid timeouts:\n\nEdge Runtime Deployment\n\nCloudflare Workers\n\nVercel Edge Functions\n\nDeno Deploy\n\nTesting\n\nUnit Testing with Hono Test Client\n\nProduction Checklist\n[ ] Configure environment variables securely\n[ ] Set appropriate CORS origins (not *)\n[ ] Enable rate limiting with reasonable limits\n[ ] Add authentication middleware\n[ ] Configure request timeouts\n[ ] Set body size limits\n[ ] Enable compression\n[ ] Add security headers\n[ ] Configure logging with appropriate level\n[ ] Set up health check monitoring\n[ ] Configure error tracking (Sentry, etc.)\n\nRelated Documentation\nServer Adapters Overview - Getting started with server adapters\nConfiguration Reference - Full configuration options\nExpress Adapter - Compare with Express adapter\nSecurity Best Practices - Authentication patterns\nStreaming Guide - Real-time streaming with SSE and NDJSON\n\nAdditional Resources\nHono Documentation - Official Hono documentation\nHono Middleware - Built-in middleware\nHono Examples - Example applications\n\nNeed Help? Join our GitHub Discussions or open an issue.","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"","lvl3":""}},
7863
7864
  {"objectID":"4f52a63fa59e73e486b75c6e70853fb82c660686cdf13261394fc63c32c40a66","title":"Hono Adapter","url":"/docs/guides/server-adapters/hono#hono-adapter","content":"The recommended framework for NeuroLink server adapters\n\nHono is a lightweight, ultrafast web framework designed for the edge. It runs on virtually any JavaScript runtime including Node.js, Deno, Bun, Cloudflare Workers, and more.","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"Hono Adapter","lvl3":""}},
7864
7865
  {"objectID":"c53bb661bf4d428d1292350b9eae21f7c2d881f171414cc705135e3e360d3521","title":"Why Hono?","url":"/docs/guides/server-adapters/hono#why-hono","content":"| Feature | Benefit |\n| ----------------------- | ------------------------------------------------------------------------- |\n| Multi-runtime | Deploy to Node.js, Deno, Bun, Cloudflare Workers, Vercel Edge, AWS Lambda |\n| Ultrafast | Minimal overhead, optimized router with RegExpRouter |\n| TypeScript-first | Full type safety out of the box |\n| Tiny footprint | ~14KB minified, no dependencies |\n| Built-in middleware | CORS, compression, ETag, secure headers included |\n| Web Standards | Uses Fetch API, Request/Response objects |\n\nHono is the default and recommended framework for NeuroLink server adapters.","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"Why Hono?","lvl3":""}},
7865
7866
  {"objectID":"4a6a19f4b89aa1306c9c1c381201916f7a706160c87f5e8dbf11e7f2cc60764f","title":"CLI Usage","url":"/docs/guides/server-adapters/hono#cli-usage","content":"Start a Hono server via CLI:","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"CLI Usage","lvl3":""}},
@@ -7868,7 +7869,7 @@
7868
7869
  {"objectID":"ac05717bef2259e66cdf32c6288f05234f2bcfdb7368a47650ed142a0a388a55","title":"Test the Server","url":"/docs/guides/server-adapters/hono#test-the-server","content":"Test the Server","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"Test the Server","lvl3":""}},
7869
7870
  {"objectID":"65a842ab7e90d7989760c8a34c85e7567c556472b5b3d94a0c62ccc93a613156","title":"Accessing the Hono App","url":"/docs/guides/server-adapters/hono#accessing-the-hono-app","content":"For advanced customization, you can access the underlying Hono instance:","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"Accessing the Hono App","lvl3":""}},
7870
7871
  {"objectID":"0f064fccc3e1e74bc76e8e15f3bf58fc0a6fb19c5287de8d9477a3c660a1b562","title":"Full Configuration Example","url":"/docs/guides/server-adapters/hono#full-configuration-example","content":"Full Configuration Example","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"Full Configuration Example","lvl3":""}},
7871
- {"objectID":"f2750d8ff58dea504fb6e6d82dd41be7772022260c0badf9be197729e5921f1c","title":"Request body limits","url":"/docs/guides/server-adapters/hono#request-body-limits","content":"bodyParser.jsonLimit bounds JSON bodies and bodyParser.maxSize bounds url-encoded forms. Both default to 10mb, as on the Express, Fastify and Koa adapters, and raising either one is honoured. Uploads (multipart/form-data, application/octet-stream, audio/*) are bounded by bodyParser.rawMaxSize, which defaults to maxSize when that is set and to 64mb otherwise.\n\nA JSON or url-encoded form body over its limit is answered 413 with error.code set to PAYLOAD_TOO_LARGE, before any middleware or route runs. A declared Content-Length over the limit is refused without reading the body, and a body sent without one is read only as far as the limit. An upload over the limit still reaches its route, which answers in its own wire format.","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"Request body limits","lvl3":""}},
7872
+ {"objectID":"f2750d8ff58dea504fb6e6d82dd41be7772022260c0badf9be197729e5921f1c","title":"Request body limits","url":"/docs/guides/server-adapters/hono#request-body-limits","content":"bodyParser.jsonLimit bounds JSON bodies and bodyParser.maxSize bounds url-encoded forms. Both default to 10mb, as on the Express, Fastify and Koa adapters, and raising either one is honoured. Uploads (multipart/form-data, application/octet-stream, audio/*) are bounded by bodyParser.rawMaxSize, which defaults to maxSize when that is set and to 64mb otherwise.\n\nA JSON or url-encoded form body over its limit is answered 413 with error.code set to PAYLOAD_TOO_LARGE, before any middleware or route runs. A declared Content-Length over the limit is refused without reading the body, and a body sent without one is read only as far as the limit. An upload over the limit still reaches its route, which answers in its own wire format.\n\nThe Express adapter stops at the limit the same way (see \"Request body limits\" in its guide). Its 413 carries the message request entity too large, where Hono's names the limit in bytes.","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"Request body limits","lvl3":""}},
7872
7873
  {"objectID":"821ac3bdd68d125a2aef04f014beab93f8b62f2148bcece2ccc375cd2d09925b","title":"Using NeuroLink Middleware","url":"/docs/guides/server-adapters/hono#using-neurolink-middleware","content":"Using NeuroLink Middleware","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"Using NeuroLink Middleware","lvl3":""}},
7873
7874
  {"objectID":"354e2b56d0fe0720a8dadeb912ee44e5412ff034874daf270f8c96ce6a011b54","title":"Using Hono Built-in Middleware","url":"/docs/guides/server-adapters/hono#using-hono-built-in-middleware","content":"Using Hono Built-in Middleware","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"Using Hono Built-in Middleware","lvl3":""}},
7874
7875
  {"objectID":"87222251107cdbe1386180da56d88d17b161d2b7b2aafc76f031006fa81fc0dd","title":"Streaming Responses","url":"/docs/guides/server-adapters/hono#streaming-responses","content":"Hono has excellent streaming support, which NeuroLink leverages for real-time AI responses:","hierarchy":{"lvl0":"Guides","lvl1":"Hono Adapter","lvl2":"Streaming Responses","lvl3":""}},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "13.8.16",
3
+ "version": "13.8.17",
4
4
  "packageManager": "pnpm@10.28.2",
5
5
  "description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
6
6
  "author": {