@emeryld/rrroutes-server 2.4.2 → 2.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -14
- package/dist/index.cjs +204 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +194 -39
- package/dist/index.js.map +1 -1
- package/dist/routesV3.server.d.ts +36 -9
- package/dist/sockets/socket.server.sys.d.ts +1 -1
- package/package.json +8 -5
package/README.md
CHANGED
|
@@ -62,7 +62,6 @@ const leaves = resource('/api')
|
|
|
62
62
|
const registry = finalize(leaves)
|
|
63
63
|
|
|
64
64
|
// 2) Wire Express with ctx + derived upload middleware
|
|
65
|
-
const upload = multer({ storage: multer.memoryStorage() })
|
|
66
65
|
const app = express()
|
|
67
66
|
const server = createRRRoute(app, {
|
|
68
67
|
buildCtx: async (req) => ({
|
|
@@ -77,10 +76,8 @@ const server = createRRRoute(app, {
|
|
|
77
76
|
},
|
|
78
77
|
],
|
|
79
78
|
},
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
files && files.length > 0 ? [upload.fields(files)] : [],
|
|
83
|
-
},
|
|
79
|
+
multerOptions: (files) =>
|
|
80
|
+
files && files.length > 0 ? { storage: multer.memoryStorage() } : undefined,
|
|
84
81
|
validateOutput: true, // parse handler returns with outputSchema (default true)
|
|
85
82
|
debug: {
|
|
86
83
|
request: true,
|
|
@@ -153,13 +150,26 @@ bindExpressRoutes(
|
|
|
153
150
|
)
|
|
154
151
|
```
|
|
155
152
|
|
|
153
|
+
If you need access to the parsed params/query/body inside `buildCtx`, destructure them from the single argument:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
const server = createRRRoute(app, {
|
|
157
|
+
buildCtx: ({ params, query, body }) => ({
|
|
158
|
+
user: lookupUser(params.id),
|
|
159
|
+
verbose: query?.verbose === 'yes',
|
|
160
|
+
}),
|
|
161
|
+
})
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
> `buildCtx` now receives the `{ req, res, params, query, body }` object; the legacy `(req, res)` signature is no longer supported.
|
|
165
|
+
|
|
156
166
|
- `defineControllers<Registry, Ctx>()(map)` keeps literal `"METHOD /path"` keys accurate and infers params/query/body/output types per leaf.
|
|
157
167
|
- `registerControllers` accepts partial maps (missing routes are skipped); `bindAll` enforces completeness at compile time.
|
|
158
168
|
- `warnMissingControllers(router, registry, logger)` inspects the Express stack and warns for any leaf without a handler.
|
|
159
169
|
|
|
160
170
|
### Middleware order and ctx usage
|
|
161
171
|
|
|
162
|
-
Order: `
|
|
172
|
+
Order: `resolve` → `ctx` → `global.before` → `route.before` → handler.
|
|
163
173
|
|
|
164
174
|
```ts
|
|
165
175
|
import { getCtx, CtxRequestHandler } from '@emeryld/rrroutes-server'
|
|
@@ -174,6 +184,11 @@ const server = createRRRoute(app, {
|
|
|
174
184
|
globalMiddleware: { before: [audit] },
|
|
175
185
|
})
|
|
176
186
|
|
|
187
|
+
const routeBefore = ({ params, query, body, ctx, next }) => {
|
|
188
|
+
ctx.routesLogger?.debug?.('route.before payload', { params, query, body })
|
|
189
|
+
next()
|
|
190
|
+
}
|
|
191
|
+
|
|
177
192
|
// Inside any Express middleware (even outside route.before), use getCtx to retrieve typed ctx:
|
|
178
193
|
app.use((req, res, next) => {
|
|
179
194
|
const ctx = getCtx<Ctx>(res)
|
|
@@ -183,27 +198,36 @@ app.use((req, res, next) => {
|
|
|
183
198
|
```
|
|
184
199
|
|
|
185
200
|
- `CtxRequestHandler` receives `{ req, res, next, ctx }` with your typed ctx.
|
|
201
|
+
- `route.before` handlers now receive the same parsed `params`, `query`, and `body` payload as the handler, alongside `req`, `res`, and `ctx`.
|
|
186
202
|
- Need post-response hooks? Register a middleware that wires `res.on('finish', handler)` inside `route.before`/`global.before` instead of relying on a dedicated "after" stage.
|
|
187
203
|
|
|
188
|
-
###
|
|
204
|
+
### Upload parsing
|
|
189
205
|
|
|
190
|
-
|
|
206
|
+
Routes that declare `bodyFiles` automatically run Multer before `ctx` using shared memory storage. Override or disable that behavior with `multerOptions`.
|
|
191
207
|
|
|
192
208
|
```ts
|
|
193
209
|
import multer from 'multer'
|
|
194
210
|
import { FileField } from '@emeryld/rrroutes-contract'
|
|
195
211
|
|
|
196
|
-
const
|
|
212
|
+
const diskStorage = multer.diskStorage({
|
|
213
|
+
destination: 'tmp/uploads',
|
|
214
|
+
filename: (_req, file, cb) => cb(null, `${Date.now()}-${file.originalname}`),
|
|
215
|
+
})
|
|
197
216
|
|
|
198
217
|
const server = createRRRoute(app, {
|
|
199
218
|
buildCtx,
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
219
|
+
multerOptions: (files: FileField[] | undefined) =>
|
|
220
|
+
files?.length
|
|
221
|
+
? {
|
|
222
|
+
storage: diskStorage,
|
|
223
|
+
limits: { fileSize: 5 * 1024 * 1024 },
|
|
224
|
+
}
|
|
225
|
+
: false,
|
|
204
226
|
})
|
|
205
227
|
```
|
|
206
228
|
|
|
229
|
+
Return `false` from `multerOptions` when you want to skip Multer for a specific route even if `bodyFiles` are declared.
|
|
230
|
+
|
|
207
231
|
### Output validation and custom responders
|
|
208
232
|
|
|
209
233
|
- `validateOutput: true` parses handler return values with the leaf `outputSchema`. Set to `false` to skip.
|
|
@@ -330,7 +354,7 @@ process.on('SIGTERM', () => sockets.destroy())
|
|
|
330
354
|
- Post-response work should hook into `res.on('finish', handler)` from a middleware in the normal pipeline if you need to observe completed responses.
|
|
331
355
|
- `compilePath`/param parsing exceptions bubble to Express error handlers; wrap `buildCtx`/middleware in try/catch if you need custom error shapes.
|
|
332
356
|
- When `validateOutput` is true and no `outputSchema` exists, raw handler output is passed through.
|
|
333
|
-
- `
|
|
357
|
+
- `multerOptions` runs only when `leaf.cfg.bodyFiles` is a non-empty array; return `false` to disable the upload middleware for that route.
|
|
334
358
|
- Socket `emit` will throw on invalid payloads; handle errors around broadcast loops.
|
|
335
359
|
|
|
336
360
|
## Scripts
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -36,6 +46,7 @@ var import_rrroutes_contract2 = require("@emeryld/rrroutes-contract");
|
|
|
36
46
|
|
|
37
47
|
// src/routesV3.server.ts
|
|
38
48
|
var import_rrroutes_contract = require("@emeryld/rrroutes-contract");
|
|
49
|
+
var import_multer = __toESM(require("multer"), 1);
|
|
39
50
|
var serverDebugEventTypes = [
|
|
40
51
|
"register",
|
|
41
52
|
"request",
|
|
@@ -94,6 +105,59 @@ var decodeJsonLikeQueryValue = (value) => {
|
|
|
94
105
|
return value;
|
|
95
106
|
};
|
|
96
107
|
var CTX_SYMBOL = /* @__PURE__ */ Symbol.for("typedLeaves.ctx");
|
|
108
|
+
var REQUEST_PAYLOAD_SYMBOL = /* @__PURE__ */ Symbol.for(
|
|
109
|
+
"typedLeaves.requestPayload"
|
|
110
|
+
);
|
|
111
|
+
function isMulterFile(value) {
|
|
112
|
+
if (!isPlainObject(value)) return false;
|
|
113
|
+
const candidate = value;
|
|
114
|
+
return typeof candidate.fieldname === "string";
|
|
115
|
+
}
|
|
116
|
+
function collectMulterFiles(req) {
|
|
117
|
+
const files = [];
|
|
118
|
+
const pushValue = (value) => {
|
|
119
|
+
if (value === void 0 || value === null) return;
|
|
120
|
+
if (Array.isArray(value)) {
|
|
121
|
+
value.forEach(pushValue);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (isMulterFile(value)) {
|
|
125
|
+
files.push(value);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (isPlainObject(value)) {
|
|
129
|
+
Object.values(value).forEach(pushValue);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
pushValue(req.files);
|
|
133
|
+
pushValue(req.file);
|
|
134
|
+
return files;
|
|
135
|
+
}
|
|
136
|
+
function resolveBodyFilesFromRequest(req, fields) {
|
|
137
|
+
if (!fields?.length) return void 0;
|
|
138
|
+
const allowedNames = new Set(fields.map((field) => field.name));
|
|
139
|
+
const collected = collectMulterFiles(req);
|
|
140
|
+
if (collected.length === 0) return void 0;
|
|
141
|
+
const result = {};
|
|
142
|
+
for (const file of collected) {
|
|
143
|
+
if (!allowedNames.has(file.fieldname)) continue;
|
|
144
|
+
const bucket = result[file.fieldname] ?? [];
|
|
145
|
+
bucket.push(file);
|
|
146
|
+
result[file.fieldname] = bucket;
|
|
147
|
+
}
|
|
148
|
+
return Object.keys(result).length ? result : void 0;
|
|
149
|
+
}
|
|
150
|
+
function getRouteRequestPayload(res) {
|
|
151
|
+
const payload = res.locals[REQUEST_PAYLOAD_SYMBOL];
|
|
152
|
+
if (payload) {
|
|
153
|
+
return payload;
|
|
154
|
+
}
|
|
155
|
+
throw new Error("Request payload was not initialized before middleware");
|
|
156
|
+
}
|
|
157
|
+
function setRouteRequestPayload(res, payload) {
|
|
158
|
+
;
|
|
159
|
+
res.locals[REQUEST_PAYLOAD_SYMBOL] = payload;
|
|
160
|
+
}
|
|
97
161
|
function getCtx(res) {
|
|
98
162
|
return res.locals[CTX_SYMBOL];
|
|
99
163
|
}
|
|
@@ -111,6 +175,26 @@ function adaptCtxMw(mw) {
|
|
|
111
175
|
}
|
|
112
176
|
};
|
|
113
177
|
}
|
|
178
|
+
function adaptRouteBeforeMw(mw) {
|
|
179
|
+
return (req, res, next) => {
|
|
180
|
+
try {
|
|
181
|
+
const result = mw({
|
|
182
|
+
req,
|
|
183
|
+
res,
|
|
184
|
+
next,
|
|
185
|
+
ctx: getCtx(res),
|
|
186
|
+
...getRouteRequestPayload(res)
|
|
187
|
+
});
|
|
188
|
+
if (result && typeof result.then === "function") {
|
|
189
|
+
return result.catch((err) => next(err));
|
|
190
|
+
}
|
|
191
|
+
return result;
|
|
192
|
+
} catch (err) {
|
|
193
|
+
next(err);
|
|
194
|
+
return void 0;
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
114
198
|
function logHandlerDebugWithRoutesLogger(logger, event) {
|
|
115
199
|
if (!logger || event.type !== "handler") return;
|
|
116
200
|
const payload = [
|
|
@@ -125,6 +209,9 @@ function logHandlerDebugWithRoutesLogger(logger, event) {
|
|
|
125
209
|
;
|
|
126
210
|
(logger.debug ?? logger.verbose ?? logger.info ?? logger.log ?? logger.system)?.call(logger, ...payload);
|
|
127
211
|
}
|
|
212
|
+
var defaultMulterOptions = {
|
|
213
|
+
storage: import_multer.default.memoryStorage()
|
|
214
|
+
};
|
|
128
215
|
var defaultSend = (res, data) => {
|
|
129
216
|
res.json(data);
|
|
130
217
|
};
|
|
@@ -168,12 +255,22 @@ function createRRRoute(router, config) {
|
|
|
168
255
|
(mw) => adaptCtxMw(mw)
|
|
169
256
|
);
|
|
170
257
|
const registered = getRegisteredRouteStore(router);
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
258
|
+
const getMulterOptions = (fields) => {
|
|
259
|
+
if (!fields || fields.length === 0) return void 0;
|
|
260
|
+
const resolved = typeof config.multerOptions === "function" ? config.multerOptions(fields) : config.multerOptions;
|
|
261
|
+
if (resolved === false) return void 0;
|
|
262
|
+
return resolved ?? defaultMulterOptions;
|
|
263
|
+
};
|
|
264
|
+
const runMulterHandler = (handler, req, res) => {
|
|
265
|
+
return new Promise((resolve, reject) => {
|
|
266
|
+
handler(req, res, (err) => {
|
|
267
|
+
if (err) {
|
|
268
|
+
reject(err);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
resolve();
|
|
272
|
+
});
|
|
273
|
+
});
|
|
177
274
|
};
|
|
178
275
|
function register(leaf, def) {
|
|
179
276
|
const method = leaf.method;
|
|
@@ -201,8 +298,84 @@ function createRRRoute(router, config) {
|
|
|
201
298
|
const emit = (event) => activeEmit(event, debugName);
|
|
202
299
|
const isVerboseDebug = activeDebugMode === "complete";
|
|
203
300
|
emit({ type: "register", method: methodUpper, path });
|
|
204
|
-
const routeSpecific = (def?.before ?? []).map(
|
|
205
|
-
|
|
301
|
+
const routeSpecific = (def?.before ?? []).map(
|
|
302
|
+
(mw) => adaptRouteBeforeMw(mw)
|
|
303
|
+
);
|
|
304
|
+
const resolvePayloadMw = async (req, res, next) => {
|
|
305
|
+
const requestUrl = req.originalUrl ?? path;
|
|
306
|
+
const startedAt = Date.now();
|
|
307
|
+
let params;
|
|
308
|
+
let query;
|
|
309
|
+
let body;
|
|
310
|
+
let bodyFiles;
|
|
311
|
+
try {
|
|
312
|
+
if (leaf.cfg.bodyFiles && leaf.cfg.bodyFiles.length > 0) {
|
|
313
|
+
const uploadOptions = getMulterOptions(leaf.cfg.bodyFiles);
|
|
314
|
+
if (uploadOptions) {
|
|
315
|
+
const fieldDefs = leaf.cfg.bodyFiles.map(({ name, maxCount }) => ({
|
|
316
|
+
name,
|
|
317
|
+
maxCount
|
|
318
|
+
}));
|
|
319
|
+
const uploader = (0, import_multer.default)(uploadOptions).fields(fieldDefs);
|
|
320
|
+
await runMulterHandler(uploader, req, res);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
bodyFiles = resolveBodyFilesFromRequest(req, leaf.cfg.bodyFiles);
|
|
324
|
+
params = leaf.cfg.paramsSchema ? (0, import_rrroutes_contract.lowProfileParse)(leaf.cfg.paramsSchema, req.params) : Object.keys(req.params || {}).length ? req.params : void 0;
|
|
325
|
+
const hasQueryKeys = req.query && Object.keys(req.query || {}).length > 0;
|
|
326
|
+
const parsedQueryInput = leaf.cfg.querySchema && hasQueryKeys ? decodeJsonLikeQueryValue(req.query) : req.query;
|
|
327
|
+
if (leaf.cfg.querySchema) {
|
|
328
|
+
try {
|
|
329
|
+
query = (0, import_rrroutes_contract.lowProfileParse)(
|
|
330
|
+
leaf.cfg.querySchema,
|
|
331
|
+
parsedQueryInput
|
|
332
|
+
);
|
|
333
|
+
} catch (err) {
|
|
334
|
+
const parseError = new Error(
|
|
335
|
+
`Query parsing error: ${err.message ?? String(err)}`
|
|
336
|
+
);
|
|
337
|
+
parseError.raw = JSON.stringify(req.query);
|
|
338
|
+
parseError.cause = err;
|
|
339
|
+
throw parseError;
|
|
340
|
+
}
|
|
341
|
+
} else {
|
|
342
|
+
query = hasQueryKeys ? req.query : void 0;
|
|
343
|
+
}
|
|
344
|
+
body = leaf.cfg.bodySchema ? (0, import_rrroutes_contract.lowProfileParse)(leaf.cfg.bodySchema, req.body) : req.body !== void 0 ? req.body : void 0;
|
|
345
|
+
} catch (err) {
|
|
346
|
+
const payloadError = {
|
|
347
|
+
params,
|
|
348
|
+
query,
|
|
349
|
+
body,
|
|
350
|
+
bodyFiles
|
|
351
|
+
};
|
|
352
|
+
emit(
|
|
353
|
+
decorateDebugEvent(
|
|
354
|
+
isVerboseDebug,
|
|
355
|
+
{
|
|
356
|
+
type: "request",
|
|
357
|
+
stage: "error",
|
|
358
|
+
method: methodUpper,
|
|
359
|
+
path,
|
|
360
|
+
url: requestUrl,
|
|
361
|
+
durationMs: Date.now() - startedAt,
|
|
362
|
+
error: err
|
|
363
|
+
},
|
|
364
|
+
isVerboseDebug ? payloadError : void 0
|
|
365
|
+
)
|
|
366
|
+
);
|
|
367
|
+
next(err);
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const requestPayload = {
|
|
371
|
+
params,
|
|
372
|
+
query,
|
|
373
|
+
body,
|
|
374
|
+
bodyFiles
|
|
375
|
+
};
|
|
376
|
+
setRouteRequestPayload(res, requestPayload);
|
|
377
|
+
next();
|
|
378
|
+
};
|
|
206
379
|
const ctxMw = async (req, res, next) => {
|
|
207
380
|
const requestUrl = req.originalUrl ?? path;
|
|
208
381
|
const startedAt = Date.now();
|
|
@@ -214,7 +387,10 @@ function createRRRoute(router, config) {
|
|
|
214
387
|
url: requestUrl
|
|
215
388
|
});
|
|
216
389
|
try {
|
|
217
|
-
const ctx = await config.buildCtx(
|
|
390
|
+
const ctx = await config.buildCtx({
|
|
391
|
+
req,
|
|
392
|
+
res
|
|
393
|
+
});
|
|
218
394
|
res.locals[CTX_SYMBOL] = ctx;
|
|
219
395
|
emit({
|
|
220
396
|
type: "buildCtx",
|
|
@@ -239,9 +415,9 @@ function createRRRoute(router, config) {
|
|
|
239
415
|
}
|
|
240
416
|
};
|
|
241
417
|
const before = [
|
|
418
|
+
resolvePayloadMw,
|
|
242
419
|
ctxMw,
|
|
243
420
|
...globalBeforeMws,
|
|
244
|
-
...derived,
|
|
245
421
|
...routeSpecific
|
|
246
422
|
];
|
|
247
423
|
const wrapped = async (req, res, next) => {
|
|
@@ -254,9 +430,11 @@ function createRRRoute(router, config) {
|
|
|
254
430
|
path,
|
|
255
431
|
url: requestUrl
|
|
256
432
|
});
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
433
|
+
const requestPayload = getRouteRequestPayload(res);
|
|
434
|
+
const params = requestPayload.params;
|
|
435
|
+
const query = requestPayload.query;
|
|
436
|
+
const body = requestPayload.body;
|
|
437
|
+
const bodyFiles = requestPayload.bodyFiles;
|
|
260
438
|
let responsePayload;
|
|
261
439
|
let hasResponsePayload = false;
|
|
262
440
|
const downstreamNext = next;
|
|
@@ -274,26 +452,6 @@ function createRRRoute(router, config) {
|
|
|
274
452
|
}
|
|
275
453
|
};
|
|
276
454
|
try {
|
|
277
|
-
params = leaf.cfg.paramsSchema ? (0, import_rrroutes_contract.lowProfileParse)(leaf.cfg.paramsSchema, req.params) : Object.keys(req.params || {}).length ? req.params : void 0;
|
|
278
|
-
try {
|
|
279
|
-
const parsedQueryInput = leaf.cfg.querySchema && req.query ? decodeJsonLikeQueryValue(req.query) : req.query;
|
|
280
|
-
query = leaf.cfg.querySchema ? (0, import_rrroutes_contract.lowProfileParse)(leaf.cfg.querySchema, parsedQueryInput) : Object.keys(req.query || {}).length ? req.query : void 0;
|
|
281
|
-
} catch (e) {
|
|
282
|
-
emitWithCtx({
|
|
283
|
-
type: "request",
|
|
284
|
-
stage: "error",
|
|
285
|
-
method: methodUpper,
|
|
286
|
-
path,
|
|
287
|
-
url: requestUrl,
|
|
288
|
-
error: {
|
|
289
|
-
...e,
|
|
290
|
-
raw: JSON.stringify(req.query),
|
|
291
|
-
message: `Query parsing error: ${e.message}`
|
|
292
|
-
}
|
|
293
|
-
});
|
|
294
|
-
throw e;
|
|
295
|
-
}
|
|
296
|
-
body = leaf.cfg.bodySchema ? (0, import_rrroutes_contract.lowProfileParse)(leaf.cfg.bodySchema, req.body) : req.body !== void 0 ? req.body : void 0;
|
|
297
455
|
const handlerStartedAt = Date.now();
|
|
298
456
|
emitWithCtx(
|
|
299
457
|
{
|
|
@@ -302,7 +460,7 @@ function createRRRoute(router, config) {
|
|
|
302
460
|
method: methodUpper,
|
|
303
461
|
path
|
|
304
462
|
},
|
|
305
|
-
isVerboseDebug ? { params, query, body } : void 0
|
|
463
|
+
isVerboseDebug ? { params, query, body, bodyFiles } : void 0
|
|
306
464
|
);
|
|
307
465
|
let result;
|
|
308
466
|
try {
|
|
@@ -313,7 +471,8 @@ function createRRRoute(router, config) {
|
|
|
313
471
|
ctx,
|
|
314
472
|
params,
|
|
315
473
|
query,
|
|
316
|
-
body
|
|
474
|
+
body,
|
|
475
|
+
bodyFiles
|
|
317
476
|
});
|
|
318
477
|
emitWithCtx(
|
|
319
478
|
{
|
|
@@ -327,6 +486,7 @@ function createRRRoute(router, config) {
|
|
|
327
486
|
params,
|
|
328
487
|
query,
|
|
329
488
|
body,
|
|
489
|
+
bodyFiles,
|
|
330
490
|
...result !== void 0 ? { output: result } : {}
|
|
331
491
|
} : void 0
|
|
332
492
|
);
|
|
@@ -340,7 +500,7 @@ function createRRRoute(router, config) {
|
|
|
340
500
|
durationMs: Date.now() - handlerStartedAt,
|
|
341
501
|
error: e
|
|
342
502
|
},
|
|
343
|
-
isVerboseDebug ? { params, query, body } : void 0
|
|
503
|
+
isVerboseDebug ? { params, query, body, bodyFiles } : void 0
|
|
344
504
|
);
|
|
345
505
|
throw e;
|
|
346
506
|
}
|
|
@@ -361,6 +521,7 @@ function createRRRoute(router, config) {
|
|
|
361
521
|
params,
|
|
362
522
|
query,
|
|
363
523
|
body,
|
|
524
|
+
bodyFiles,
|
|
364
525
|
...hasResponsePayload ? { output: responsePayload } : {}
|
|
365
526
|
} : void 0
|
|
366
527
|
);
|
|
@@ -375,7 +536,7 @@ function createRRRoute(router, config) {
|
|
|
375
536
|
durationMs: Date.now() - startedAt,
|
|
376
537
|
error: err
|
|
377
538
|
},
|
|
378
|
-
isVerboseDebug ? { params, query, body } : void 0
|
|
539
|
+
isVerboseDebug ? { params, query, body, bodyFiles } : void 0
|
|
379
540
|
);
|
|
380
541
|
next(err);
|
|
381
542
|
}
|
|
@@ -502,8 +663,12 @@ function createBuiltInConnectionHandlers(opts) {
|
|
|
502
663
|
const pingEvent = "sys:ping";
|
|
503
664
|
const pongEvent = "sys:pong";
|
|
504
665
|
const heartbeatEnabled = heartbeat?.enabled !== false;
|
|
505
|
-
const joinPayloadSchema = buildRoomPayloadSchema(
|
|
506
|
-
|
|
666
|
+
const joinPayloadSchema = buildRoomPayloadSchema(
|
|
667
|
+
config.joinMetaMessage
|
|
668
|
+
);
|
|
669
|
+
const leavePayloadSchema = buildRoomPayloadSchema(
|
|
670
|
+
config.leaveMetaMessage
|
|
671
|
+
);
|
|
507
672
|
const pingPayloadSchema = config.pingPayload;
|
|
508
673
|
const pongPayloadSchema = config.pongPayload;
|
|
509
674
|
const sysEvents = sys;
|