mates-fullstack 1.0.0-beta.1

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 (202) hide show
  1. package/README.md +311 -0
  2. package/dist/arctic-auth.d.ts +101 -0
  3. package/dist/arctic-auth.d.ts.map +1 -0
  4. package/dist/arctic-auth.js +538 -0
  5. package/dist/arctic-auth.js.map +1 -0
  6. package/dist/asset-manifest.d.ts +14 -0
  7. package/dist/asset-manifest.d.ts.map +1 -0
  8. package/dist/asset-manifest.js +102 -0
  9. package/dist/asset-manifest.js.map +1 -0
  10. package/dist/browser.d.ts +18 -0
  11. package/dist/browser.d.ts.map +1 -0
  12. package/dist/browser.js +25 -0
  13. package/dist/browser.js.map +1 -0
  14. package/dist/build-esbuild.d.ts +29 -0
  15. package/dist/build-esbuild.d.ts.map +1 -0
  16. package/dist/build-esbuild.js +699 -0
  17. package/dist/build-esbuild.js.map +1 -0
  18. package/dist/build-prod.d.ts +126 -0
  19. package/dist/build-prod.d.ts.map +1 -0
  20. package/dist/build-prod.js +1014 -0
  21. package/dist/build-prod.js.map +1 -0
  22. package/dist/cli-new.d.ts +14 -0
  23. package/dist/cli-new.d.ts.map +1 -0
  24. package/dist/cli-new.js +637 -0
  25. package/dist/cli-new.js.map +1 -0
  26. package/dist/client.d.ts +43 -0
  27. package/dist/client.d.ts.map +1 -0
  28. package/dist/client.js +130 -0
  29. package/dist/client.js.map +1 -0
  30. package/dist/cors.d.ts +16 -0
  31. package/dist/cors.d.ts.map +1 -0
  32. package/dist/cors.js +60 -0
  33. package/dist/cors.js.map +1 -0
  34. package/dist/ctx.d.ts +78 -0
  35. package/dist/ctx.d.ts.map +1 -0
  36. package/dist/ctx.js +280 -0
  37. package/dist/ctx.js.map +1 -0
  38. package/dist/dev-watcher.d.ts +23 -0
  39. package/dist/dev-watcher.d.ts.map +1 -0
  40. package/dist/dev-watcher.js +136 -0
  41. package/dist/dev-watcher.js.map +1 -0
  42. package/dist/docs-generator.d.ts +69 -0
  43. package/dist/docs-generator.d.ts.map +1 -0
  44. package/dist/docs-generator.js +557 -0
  45. package/dist/docs-generator.js.map +1 -0
  46. package/dist/docs-page.d.ts +20 -0
  47. package/dist/docs-page.d.ts.map +1 -0
  48. package/dist/docs-page.js +1152 -0
  49. package/dist/docs-page.js.map +1 -0
  50. package/dist/download.d.ts +78 -0
  51. package/dist/download.d.ts.map +1 -0
  52. package/dist/download.js +202 -0
  53. package/dist/download.js.map +1 -0
  54. package/dist/env-loader.d.ts +76 -0
  55. package/dist/env-loader.d.ts.map +1 -0
  56. package/dist/env-loader.js +213 -0
  57. package/dist/env-loader.js.map +1 -0
  58. package/dist/errors.d.ts +146 -0
  59. package/dist/errors.d.ts.map +1 -0
  60. package/dist/errors.js +386 -0
  61. package/dist/errors.js.map +1 -0
  62. package/dist/head.d.ts +31 -0
  63. package/dist/head.d.ts.map +1 -0
  64. package/dist/head.js +245 -0
  65. package/dist/head.js.map +1 -0
  66. package/dist/index.d.ts +30 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +30 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/internal-prefixes.d.ts +16 -0
  71. package/dist/internal-prefixes.d.ts.map +1 -0
  72. package/dist/internal-prefixes.js +16 -0
  73. package/dist/internal-prefixes.js.map +1 -0
  74. package/dist/internal.d.ts +25 -0
  75. package/dist/internal.d.ts.map +1 -0
  76. package/dist/internal.js +25 -0
  77. package/dist/internal.js.map +1 -0
  78. package/dist/jwt.d.ts +166 -0
  79. package/dist/jwt.d.ts.map +1 -0
  80. package/dist/jwt.js +261 -0
  81. package/dist/jwt.js.map +1 -0
  82. package/dist/log.d.ts +44 -0
  83. package/dist/log.d.ts.map +1 -0
  84. package/dist/log.js +66 -0
  85. package/dist/log.js.map +1 -0
  86. package/dist/logger.d.ts +76 -0
  87. package/dist/logger.d.ts.map +1 -0
  88. package/dist/logger.js +138 -0
  89. package/dist/logger.js.map +1 -0
  90. package/dist/main-runner.d.ts +59 -0
  91. package/dist/main-runner.d.ts.map +1 -0
  92. package/dist/main-runner.js +157 -0
  93. package/dist/main-runner.js.map +1 -0
  94. package/dist/mates-auth.d.ts +82 -0
  95. package/dist/mates-auth.d.ts.map +1 -0
  96. package/dist/mates-auth.js +323 -0
  97. package/dist/mates-auth.js.map +1 -0
  98. package/dist/middleware.d.ts +30 -0
  99. package/dist/middleware.d.ts.map +1 -0
  100. package/dist/middleware.js +67 -0
  101. package/dist/middleware.js.map +1 -0
  102. package/dist/project-resolver.d.ts +102 -0
  103. package/dist/project-resolver.d.ts.map +1 -0
  104. package/dist/project-resolver.js +271 -0
  105. package/dist/project-resolver.js.map +1 -0
  106. package/dist/rate-limit.d.ts +37 -0
  107. package/dist/rate-limit.d.ts.map +1 -0
  108. package/dist/rate-limit.js +109 -0
  109. package/dist/rate-limit.js.map +1 -0
  110. package/dist/redirect.d.ts +84 -0
  111. package/dist/redirect.d.ts.map +1 -0
  112. package/dist/redirect.js +105 -0
  113. package/dist/redirect.js.map +1 -0
  114. package/dist/renderer.d.ts +91 -0
  115. package/dist/renderer.d.ts.map +1 -0
  116. package/dist/renderer.js +630 -0
  117. package/dist/renderer.js.map +1 -0
  118. package/dist/request-logger.d.ts +12 -0
  119. package/dist/request-logger.d.ts.map +1 -0
  120. package/dist/request-logger.js +55 -0
  121. package/dist/request-logger.js.map +1 -0
  122. package/dist/rest.d.ts +25 -0
  123. package/dist/rest.d.ts.map +1 -0
  124. package/dist/rest.js +93 -0
  125. package/dist/rest.js.map +1 -0
  126. package/dist/router.d.ts +71 -0
  127. package/dist/router.d.ts.map +1 -0
  128. package/dist/router.js +222 -0
  129. package/dist/router.js.map +1 -0
  130. package/dist/rpc-registry.d.ts +84 -0
  131. package/dist/rpc-registry.d.ts.map +1 -0
  132. package/dist/rpc-registry.js +271 -0
  133. package/dist/rpc-registry.js.map +1 -0
  134. package/dist/rpc-runner.d.ts +82 -0
  135. package/dist/rpc-runner.d.ts.map +1 -0
  136. package/dist/rpc-runner.js +564 -0
  137. package/dist/rpc-runner.js.map +1 -0
  138. package/dist/sanitize.d.ts +61 -0
  139. package/dist/sanitize.d.ts.map +1 -0
  140. package/dist/sanitize.js +193 -0
  141. package/dist/sanitize.js.map +1 -0
  142. package/dist/security-headers.d.ts +114 -0
  143. package/dist/security-headers.d.ts.map +1 -0
  144. package/dist/security-headers.js +121 -0
  145. package/dist/security-headers.js.map +1 -0
  146. package/dist/server-fn.d.ts +323 -0
  147. package/dist/server-fn.d.ts.map +1 -0
  148. package/dist/server-fn.js +373 -0
  149. package/dist/server-fn.js.map +1 -0
  150. package/dist/server-public.d.ts +13 -0
  151. package/dist/server-public.d.ts.map +1 -0
  152. package/dist/server-public.js +12 -0
  153. package/dist/server-public.js.map +1 -0
  154. package/dist/server-timeout.d.ts +38 -0
  155. package/dist/server-timeout.d.ts.map +1 -0
  156. package/dist/server-timeout.js +46 -0
  157. package/dist/server-timeout.js.map +1 -0
  158. package/dist/server.d.ts +100 -0
  159. package/dist/server.d.ts.map +1 -0
  160. package/dist/server.js +1218 -0
  161. package/dist/server.js.map +1 -0
  162. package/dist/socket-router.d.ts +153 -0
  163. package/dist/socket-router.d.ts.map +1 -0
  164. package/dist/socket-router.js +612 -0
  165. package/dist/socket-router.js.map +1 -0
  166. package/dist/sso.d.ts +90 -0
  167. package/dist/sso.d.ts.map +1 -0
  168. package/dist/sso.js +261 -0
  169. package/dist/sso.js.map +1 -0
  170. package/dist/ssr-context.d.ts +49 -0
  171. package/dist/ssr-context.d.ts.map +1 -0
  172. package/dist/ssr-context.js +85 -0
  173. package/dist/ssr-context.js.map +1 -0
  174. package/dist/ssr-globals.d.ts +32 -0
  175. package/dist/ssr-globals.d.ts.map +1 -0
  176. package/dist/ssr-globals.js +1010 -0
  177. package/dist/ssr-globals.js.map +1 -0
  178. package/dist/ssr-template.d.ts +73 -0
  179. package/dist/ssr-template.d.ts.map +1 -0
  180. package/dist/ssr-template.js +507 -0
  181. package/dist/ssr-template.js.map +1 -0
  182. package/dist/stack-mapper.d.ts +25 -0
  183. package/dist/stack-mapper.d.ts.map +1 -0
  184. package/dist/stack-mapper.js +139 -0
  185. package/dist/stack-mapper.js.map +1 -0
  186. package/dist/stream.d.ts +89 -0
  187. package/dist/stream.d.ts.map +1 -0
  188. package/dist/stream.js +299 -0
  189. package/dist/stream.js.map +1 -0
  190. package/dist/upload.d.ts +69 -0
  191. package/dist/upload.d.ts.map +1 -0
  192. package/dist/upload.js +110 -0
  193. package/dist/upload.js.map +1 -0
  194. package/dist/validate.d.ts +58 -0
  195. package/dist/validate.d.ts.map +1 -0
  196. package/dist/validate.js +89 -0
  197. package/dist/validate.js.map +1 -0
  198. package/dist/verify-package.d.ts +3 -0
  199. package/dist/verify-package.d.ts.map +1 -0
  200. package/dist/verify-package.js +128 -0
  201. package/dist/verify-package.js.map +1 -0
  202. package/package.json +79 -0
@@ -0,0 +1,271 @@
1
+ /**
2
+ * mates-fullstack — rpc-registry.ts
3
+ *
4
+ * Scans server/api/ and registers every exported async function as an RPC endpoint.
5
+ *
6
+ * URL derivation:
7
+ * server/api/users.ts + getUsers → POST /api/users/getUsers
8
+ * server/api/posts/index.ts + getPosts → POST /api/posts/getPosts
9
+ * server/api/auth.ts + login → POST /api/auth/login
10
+ *
11
+ * The URL is also the test/Postman endpoint:
12
+ * POST /api/users/getUsers
13
+ * Content-Type: application/json
14
+ * { "page": 0 }
15
+ *
16
+ * Rules for what gets registered:
17
+ * ✅ Exported async functions
18
+ * ✅ Plain exported functions (warned but registered)
19
+ * ❌ default export (page component convention)
20
+ * ❌ Non-function exports (types, constants)
21
+ * ❌ Reserved names: loader, meta, layout, staticPaths, onConnect, onDisconnect
22
+ * ❌ Functions named "then" or "catch" (conflicts with Promise protocol)
23
+ * ❌ Files starting with _ or containing .test. / .spec.
24
+ *
25
+ * Dev mode:
26
+ * Files are re-imported with a cache-busting timestamp on every rescan.
27
+ * The watcher triggers a rescan on file add/remove/rename.
28
+ * Content edits are picked up because the cache-bust forces a fresh import.
29
+ */
30
+ import fs from "node:fs";
31
+ import path from "node:path";
32
+ import { devError, devWarn } from "./log.js";
33
+ // ─── Reserved export names ────────────────────────────────────────────────────
34
+ /**
35
+ * Export names that must never be registered as RPC functions.
36
+ * These are framework-level exports consumed by the SSR runtime or
37
+ * WebSocket handlers.
38
+ */
39
+ const RESERVED_NAMES = new Set([
40
+ "default", // page component / module default
41
+ "loader", // SSR data loader
42
+ "meta", // page <head> metadata
43
+ "layout", // page layout wrapper
44
+ "staticPaths", // SSG static path list
45
+ "onConnect", // WebSocket lifecycle
46
+ "onDisconnect", // WebSocket lifecycle
47
+ "then", // conflicts with Promise protocol
48
+ "catch", // conflicts with Promise protocol
49
+ "finally", // conflicts with Promise protocol
50
+ ]);
51
+ // ─── Registry ─────────────────────────────────────────────────────────────────
52
+ /** url → RpcEntry */
53
+ const _registry = new Map();
54
+ /** Absolute path of the currently scanned apiDir */
55
+ let _apiDir = null;
56
+ // ─── Public API ───────────────────────────────────────────────────────────────
57
+ /**
58
+ * Scan server/api/ and populate the registry.
59
+ * Call once at startup. In dev mode, call again after file changes
60
+ * or use watchRpcFunctions() for automatic rescanning.
61
+ */
62
+ export async function scanRpcFunctions(apiDir, dev = false) {
63
+ if (!fs.existsSync(apiDir))
64
+ return;
65
+ _apiDir = apiDir;
66
+ _registry.clear();
67
+ const files = _collectFiles(apiDir);
68
+ for (const filePath of files) {
69
+ // Security: ensure resolved path stays inside apiDir
70
+ const absApi = path.resolve(apiDir);
71
+ const absFile = path.resolve(filePath);
72
+ if (!absFile.startsWith(absApi + path.sep) && absFile !== absApi) {
73
+ continue;
74
+ }
75
+ await _registerFile(apiDir, filePath, dev);
76
+ }
77
+ }
78
+ /**
79
+ * Look up a registered RPC function by its URL.
80
+ * Returns null if not found.
81
+ *
82
+ * @example
83
+ * lookupRpcFn("/api/users/getUsers")
84
+ */
85
+ export function lookupRpcFn(url) {
86
+ // Normalize: strip query string if present
87
+ const pathname = url.split("?")[0];
88
+ return _registry.get(pathname) ?? null;
89
+ }
90
+ /**
91
+ * Returns all registered RPC entries.
92
+ * Used by the docs generator and startup logging.
93
+ */
94
+ export function listRpcFunctions() {
95
+ return Array.from(_registry.values());
96
+ }
97
+ /**
98
+ * Returns the number of registered RPC functions.
99
+ */
100
+ export function rpcRegistrySize() {
101
+ return _registry.size;
102
+ }
103
+ /**
104
+ * Clear the registry. Used before a rescan or in tests.
105
+ */
106
+ export function clearRpcRegistry() {
107
+ _registry.clear();
108
+ _apiDir = null;
109
+ }
110
+ /**
111
+ * Watch server/api/ for file changes and trigger a rescan.
112
+ * Returns a cleanup function that stops the watcher.
113
+ *
114
+ * Only responds to file add/remove/rename events — content edits are
115
+ * handled by the cache-bust import in dev mode.
116
+ */
117
+ export function watchRpcFunctions(apiDir, onChange) {
118
+ if (!fs.existsSync(apiDir))
119
+ return () => { };
120
+ let debounce = null;
121
+ const watcher = fs.watch(apiDir, { recursive: true }, (event, filename) => {
122
+ if (!filename)
123
+ return;
124
+ if (!_isApiFile(path.basename(filename)))
125
+ return;
126
+ if (debounce)
127
+ clearTimeout(debounce);
128
+ debounce = setTimeout(async () => {
129
+ await scanRpcFunctions(apiDir, true);
130
+ onChange(event, filename);
131
+ }, 50);
132
+ });
133
+ return () => {
134
+ if (debounce)
135
+ clearTimeout(debounce);
136
+ watcher.close();
137
+ };
138
+ }
139
+ // ─── URL derivation ───────────────────────────────────────────────────────────
140
+ /**
141
+ * Derive the RPC URL for a function exported from a file.
142
+ *
143
+ * Examples (apiDir = /project/server/api):
144
+ * /project/server/api/users.ts + getUsers → /api/users/getUsers
145
+ * /project/server/api/posts/index.ts + getPosts → /api/posts/getPosts
146
+ * /project/server/api/auth.ts + login → /api/auth/login
147
+ */
148
+ export function deriveRpcUrl(apiDir, filePath, fnName) {
149
+ const rel = path.relative(apiDir, filePath);
150
+ const withoutExt = rel.replace(/\.(ts|js|tsx|jsx)$/, "");
151
+ // Normalize path separators to forward slash
152
+ let modulePath = withoutExt.split(path.sep).join("/");
153
+ // Drop trailing "index" — posts/index → posts
154
+ if (modulePath.endsWith("/index")) {
155
+ modulePath = modulePath.slice(0, -6);
156
+ }
157
+ else if (modulePath === "index") {
158
+ modulePath = "";
159
+ }
160
+ // Build: /api/{modulePath}/{fnName}
161
+ const parts = ["api"];
162
+ if (modulePath)
163
+ parts.push(modulePath);
164
+ parts.push(fnName);
165
+ return "/" + parts.join("/");
166
+ }
167
+ // ─── Internal ─────────────────────────────────────────────────────────────────
168
+ async function _registerFile(apiDir, filePath, dev) {
169
+ // In dev mode, cache-bust so updated implementations are picked up
170
+ const importSpecifier = dev ? `${filePath}?t=${Date.now()}` : filePath;
171
+ let mod;
172
+ try {
173
+ mod = await import(importSpecifier);
174
+ }
175
+ catch (err) {
176
+ const message = `failed to import ${path.relative(apiDir, filePath)}: ${err?.message ?? err}`;
177
+ if (!dev)
178
+ throw new Error(message);
179
+ // In dev, log and keep the server alive so the developer can fix the file.
180
+ devError(message);
181
+ return;
182
+ }
183
+ let registered = 0;
184
+ const urlsSeen = new Set();
185
+ for (const [exportName, exportValue] of Object.entries(mod)) {
186
+ // Skip reserved names
187
+ if (RESERVED_NAMES.has(exportName))
188
+ continue;
189
+ // Skip non-functions
190
+ if (typeof exportValue !== "function")
191
+ continue;
192
+ // Skip non-async functions with a warning
193
+ // (async check: constructor.name === "AsyncFunction")
194
+ const isAsync = exportValue.constructor?.name === "AsyncFunction";
195
+ if (!isAsync) {
196
+ devWarn(`${path.relative(apiDir, filePath)}: ` +
197
+ `export "${exportName}" is not async — skipped. ` +
198
+ `RPC functions must be async.`);
199
+ continue;
200
+ }
201
+ const url = deriveRpcUrl(apiDir, filePath, exportName);
202
+ // Collision detection: two functions mapping to the same URL
203
+ if (_registry.has(url)) {
204
+ const existing = _registry.get(url);
205
+ if (existing.filePath !== filePath) {
206
+ // Different files, same URL — warn, first one wins
207
+ devWarn(`URL collision: ${url} is registered by both ` +
208
+ `"${path.relative(apiDir, existing.filePath)}" and ` +
209
+ `"${path.relative(apiDir, filePath)}" — ` +
210
+ `first registration wins.`);
211
+ continue;
212
+ }
213
+ // Same file, same URL — shouldn't happen but skip silently
214
+ continue;
215
+ }
216
+ urlsSeen.add(url);
217
+ _registry.set(url, {
218
+ url,
219
+ filePath,
220
+ fnName: exportName,
221
+ fn: exportValue,
222
+ });
223
+ registered++;
224
+ }
225
+ // Warn if file only has HTTP method exports (GET/POST/etc.) — wrong folder
226
+ if (registered === 0) {
227
+ const httpMethods = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"];
228
+ const hasHttpExports = Object.keys(mod).some((k) => httpMethods.includes(k));
229
+ if (hasHttpExports) {
230
+ devWarn(`${path.relative(apiDir, filePath)} exports HTTP methods ` +
231
+ `(GET/POST/etc.) but no RPC functions. ` +
232
+ `mates-fullstack only exposes RPC functions from server/api/.`);
233
+ }
234
+ }
235
+ }
236
+ /**
237
+ * Recursively collect all api files under a directory.
238
+ */
239
+ function _collectFiles(dir) {
240
+ const results = [];
241
+ _walk(dir, results);
242
+ return results;
243
+ }
244
+ function _walk(dir, out) {
245
+ let entries;
246
+ try {
247
+ entries = fs.readdirSync(dir, { withFileTypes: true });
248
+ }
249
+ catch {
250
+ return;
251
+ }
252
+ for (const entry of entries) {
253
+ const full = path.join(dir, entry.name);
254
+ if (entry.isDirectory()) {
255
+ _walk(full, out);
256
+ }
257
+ else if (_isApiFile(entry.name)) {
258
+ out.push(full);
259
+ }
260
+ }
261
+ }
262
+ function _isApiFile(filename) {
263
+ if (filename.startsWith("_"))
264
+ return false;
265
+ if (filename.startsWith("."))
266
+ return false;
267
+ if (filename.includes(".test.") || filename.includes(".spec."))
268
+ return false;
269
+ return /\.(ts|js|tsx|jsx)$/.test(filename);
270
+ }
271
+ //# sourceMappingURL=rpc-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-registry.js","sourceRoot":"","sources":["../src/rpc-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * mates-fullstack — rpc-runner.ts
3
+ *
4
+ * Executes a registered RPC function for an incoming HTTP request.
5
+ *
6
+ * Execution pipeline per request:
7
+ * 1. Read + size-check request body
8
+ * 2. Parse payload (JSON or multipart/form-data)
9
+ * 3. Create Context from request headers
10
+ * 4. Run onRequest hooks (registered in server/main.ts)
11
+ * - throws → error response sent, onResponse SKIPPED
12
+ * - returns Response → that response sent, onResponse RUNS
13
+ * - returns nothing → continue
14
+ * 5. Run entry.fn(payload, ctx)
15
+ * - throws → error response sent, onResponse SKIPPED
16
+ * - returns data → onResponse hooks run, then response sent
17
+ * 6. Detect return type → route to correct response writer:
18
+ * - StreamResponse → SSE
19
+ * - Download → binary attachment
20
+ * - void/null/undefined → {} 200
21
+ * - anything else → JSON 200
22
+ * 7. Run onResponse hooks (with data + ctx)
23
+ * 8. Apply ctx.resHeaders to the response
24
+ *
25
+ * Error handling:
26
+ * - Redirect throw → 302 JSON { __type: "Redirect", url, status }
27
+ * - ServerError throw → 4xx/5xx JSON { __type, message, status, code, ...}
28
+ * - Plain Error throw → 500, message hidden in production
29
+ * - Unknown throw → 500, "Internal Server Error"
30
+ *
31
+ * Body limits:
32
+ * - JSON: 1MB default (MAX_JSON_BYTES)
33
+ * - Multipart: 10MB default (MAX_UPLOAD_BYTES)
34
+ */
35
+ /// <reference types="node" />
36
+ import type { IncomingMessage, ServerResponse } from "node:http";
37
+ import type { RpcEntry } from "./rpc-registry.js";
38
+ export interface RpcRunnerConfig {
39
+ /** Maximum JSON request body size. Default: 1MB */
40
+ maxJsonBytes?: number;
41
+ /** Maximum allowed object depth in JSON payloads. Default: 50 */
42
+ maxJsonDepth?: number;
43
+ /** Maximum allowed array length in JSON payloads. Default: 10_000 */
44
+ maxArrayLength?: number;
45
+ /** Maximum allowed length for any string value. Default: 100_000 */
46
+ maxStringLength?: number;
47
+ /** Maximum multipart/form-data upload size. Default: 10MB */
48
+ maxUploadBytes?: number;
49
+ /** Maximum number of multipart parts. Default: 200 */
50
+ maxMultipartParts?: number;
51
+ }
52
+ /**
53
+ * Configure RPC runner limits. Call once at startup.
54
+ * All values are optional — only provided values override the defaults.
55
+ */
56
+ export declare function configureRpcRunner(config: RpcRunnerConfig): void;
57
+ /** Request timeout in milliseconds: 30 seconds */
58
+ export declare const DEFAULT_TIMEOUT_MS = 30000;
59
+ /**
60
+ * Handle a single RPC request end-to-end.
61
+ * Never throws under any circumstances.
62
+ * All errors — including unexpected framework bugs — produce a JSON error response.
63
+ */
64
+ export declare function runRpcRequest(req: IncomingMessage, res: ServerResponse, entry: RpcEntry, dev: boolean, timeoutMs?: number,
65
+ /** Pre-populated ctx from the outer request handler. When supplied, auth
66
+ * and other middleware state already applied via onRequest are shared. */
67
+ sharedCtx?: import("./ctx.js").Context): Promise<void>;
68
+ /**
69
+ * Read and parse the request body.
70
+ *
71
+ * Handles:
72
+ * - application/json → JSON.parse
73
+ * - multipart/form-data → FormData-like object with File entries
74
+ * - no content-type → attempt JSON parse, fallback to {}
75
+ * - empty body → {}
76
+ *
77
+ * Throws with .status set for:
78
+ * - Body too large (413)
79
+ * - Malformed JSON (400)
80
+ */
81
+ export declare function parseRpcBody(req: IncomingMessage): Promise<unknown>;
82
+ //# sourceMappingURL=rpc-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-runner.d.ts","sourceRoot":"","sources":["../src/rpc-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AA2BlD,MAAM,WAAW,eAAe;IAC9B,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAWD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAahE;AA0CD,kDAAkD;AAClD,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAIzC;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,QAAQ,EACf,GAAG,EAAE,OAAO,EACZ,SAAS,SAAqB;AAC9B;0EAC0E;AAC1E,SAAS,CAAC,EAAE,OAAO,UAAU,EAAE,OAAO,GACrC,OAAO,CAAC,IAAI,CAAC,CA4Cf;AA0ID;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAEzE"}