@xrystal/dto 26.6.27-v12
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 +724 -0
- package/dist/adapters/elysia.cjs +820 -0
- package/dist/adapters/elysia.d.ts +138 -0
- package/dist/adapters/elysia.js +816 -0
- package/dist/adapters/express.cjs +789 -0
- package/dist/adapters/express.d.ts +49 -0
- package/dist/adapters/express.js +785 -0
- package/dist/adapters/index.d.ts +7 -0
- package/dist/adapters/node.cjs +790 -0
- package/dist/adapters/node.d.ts +27 -0
- package/dist/adapters/node.js +786 -0
- package/dist/adapters/shared.d.ts +11 -0
- package/dist/adapters/socketio.cjs +767 -0
- package/dist/adapters/socketio.d.ts +31 -0
- package/dist/adapters/socketio.js +763 -0
- package/dist/adapters/websocket.cjs +759 -0
- package/dist/adapters/websocket.d.ts +31 -0
- package/dist/adapters/websocket.js +754 -0
- package/dist/core/assemble-log.d.ts +1 -0
- package/dist/core/assemble-queue.d.ts +1 -0
- package/dist/core/assemble.d.ts +9 -0
- package/dist/core/builder.d.ts +49 -0
- package/dist/core/config.d.ts +10 -0
- package/dist/core/context.d.ts +5 -0
- package/dist/core/hooks.d.ts +8 -0
- package/dist/core/index.cjs +1002 -0
- package/dist/core/index.d.ts +14 -0
- package/dist/core/index.js +986 -0
- package/dist/core/log-dto.d.ts +1 -0
- package/dist/core/metadata.d.ts +6 -0
- package/dist/core/plugins.d.ts +10 -0
- package/dist/core/presets.d.ts +32 -0
- package/dist/core/queue-dto.d.ts +1 -0
- package/dist/core/response-dto.d.ts +1 -0
- package/dist/core/schema-utils.d.ts +1 -0
- package/dist/dto/index.cjs +909 -0
- package/dist/dto/index.d.ts +6 -0
- package/dist/dto/index.js +898 -0
- package/dist/dto/log/assemble.d.ts +3 -0
- package/dist/dto/log/builder.d.ts +41 -0
- package/dist/dto/log/index.cjs +152 -0
- package/dist/dto/log/index.d.ts +3 -0
- package/dist/dto/log/index.js +149 -0
- package/dist/dto/log/types.d.ts +26 -0
- package/dist/dto/queue/assemble.d.ts +2 -0
- package/dist/dto/queue/builder.d.ts +35 -0
- package/dist/dto/queue/index.cjs +154 -0
- package/dist/dto/queue/index.d.ts +3 -0
- package/dist/dto/queue/index.js +151 -0
- package/dist/dto/queue/types.d.ts +34 -0
- package/dist/dto/response/assemble.d.ts +1 -0
- package/dist/dto/response/dto.d.ts +39 -0
- package/dist/dto/response/index.cjs +179 -0
- package/dist/dto/response/index.d.ts +2 -0
- package/dist/dto/response/index.js +176 -0
- package/dist/dto/runtime/dto.cjs +1318 -0
- package/dist/dto/runtime/dto.d.ts +64 -0
- package/dist/dto/runtime/dto.js +1315 -0
- package/dist/dto/shared/base-dto.d.ts +12 -0
- package/dist/dto/shared/schema-utils.d.ts +1 -0
- package/dist/enums/node-env.d.ts +5 -0
- package/dist/errors/codes.d.ts +15 -0
- package/dist/errors/error.d.ts +32 -0
- package/dist/errors/index.d.ts +2 -0
- package/dist/index.cjs +1482 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +1433 -0
- package/dist/types/builder.d.ts +15 -0
- package/dist/types/codes.d.ts +7 -0
- package/dist/types/context.d.ts +16 -0
- package/dist/types/hooks.d.ts +7 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/log.d.ts +1 -0
- package/dist/types/metadata.d.ts +7 -0
- package/dist/types/options.d.ts +24 -0
- package/dist/types/plugin.d.ts +35 -0
- package/dist/types/queue.d.ts +1 -0
- package/dist/types/response.d.ts +43 -0
- package/dist/utils/constants/http.d.ts +2 -0
- package/dist/utils/constants/index.d.ts +3 -0
- package/dist/utils/constants/security-headers.d.ts +1 -0
- package/dist/utils/constants/status-codes.d.ts +35 -0
- package/dist/utils/helpers/index.d.ts +2 -0
- package/dist/utils/helpers/request-id.d.ts +3 -0
- package/dist/utils/helpers/uuid.d.ts +2 -0
- package/dist/utils/index.d.ts +2 -0
- package/package.json +130 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1433 @@
|
|
|
1
|
+
import { Elysia } from 'elysia';
|
|
2
|
+
|
|
3
|
+
// src/enums/node-env.ts
|
|
4
|
+
var NodeEnvEnum = /* @__PURE__ */ ((NodeEnvEnum2) => {
|
|
5
|
+
NodeEnvEnum2["DEV"] = "dev";
|
|
6
|
+
NodeEnvEnum2["TEST"] = "test";
|
|
7
|
+
NodeEnvEnum2["PROD"] = "prod";
|
|
8
|
+
return NodeEnvEnum2;
|
|
9
|
+
})(NodeEnvEnum || {});
|
|
10
|
+
|
|
11
|
+
// src/types/plugin.ts
|
|
12
|
+
function definePlugin(plugin) {
|
|
13
|
+
return plugin;
|
|
14
|
+
}
|
|
15
|
+
function mergePlugins(...groups) {
|
|
16
|
+
return groups.flatMap((group) => group ?? []);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/utils/constants/status-codes.ts
|
|
20
|
+
var StatusCodes = {
|
|
21
|
+
SUCCESSFUL: {
|
|
22
|
+
OK: 200,
|
|
23
|
+
CREATED: 201,
|
|
24
|
+
ACCEPTED: 202,
|
|
25
|
+
NO_CONTENT: 204
|
|
26
|
+
},
|
|
27
|
+
REDIRECTION: {
|
|
28
|
+
MOVED_PERMANENTLY: 301,
|
|
29
|
+
FOUND: 302,
|
|
30
|
+
NOT_MODIFIED: 304
|
|
31
|
+
},
|
|
32
|
+
CLIENT_ERROR: {
|
|
33
|
+
BAD_REQUEST: 400,
|
|
34
|
+
UNAUTHORIZED: 401,
|
|
35
|
+
FORBIDDEN: 403,
|
|
36
|
+
NOT_FOUND: 404,
|
|
37
|
+
METHOD_NOT_ALLOWED: 405,
|
|
38
|
+
CONFLICT: 409,
|
|
39
|
+
GONE: 410,
|
|
40
|
+
PAYLOAD_TOO_LARGE: 413,
|
|
41
|
+
UNSUPPORTED_MEDIA_TYPE: 415,
|
|
42
|
+
UNPROCESSABLE_ENTITY: 422,
|
|
43
|
+
TOO_MANY_REQUESTS: 429
|
|
44
|
+
},
|
|
45
|
+
SERVER_ERROR: {
|
|
46
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
47
|
+
NOT_IMPLEMENTED: 501,
|
|
48
|
+
BAD_GATEWAY: 502,
|
|
49
|
+
SERVICE_UNAVAILABLE: 503,
|
|
50
|
+
GATEWAY_TIMEOUT: 504
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// src/errors/codes.ts
|
|
55
|
+
var DefaultCodes = {
|
|
56
|
+
SUCCESS: 0,
|
|
57
|
+
CLIENT: 1,
|
|
58
|
+
SERVER: 2,
|
|
59
|
+
VALIDATION: 3
|
|
60
|
+
};
|
|
61
|
+
function createCodeRegistry(overrides = {}) {
|
|
62
|
+
return { ...DefaultCodes, ...overrides };
|
|
63
|
+
}
|
|
64
|
+
function isSuccessCode(code, codes) {
|
|
65
|
+
return code === codes.SUCCESS;
|
|
66
|
+
}
|
|
67
|
+
function resolveCodeFromHttpStatus(statusCode, codes) {
|
|
68
|
+
if (statusCode >= 200 && statusCode < 300) return codes.SUCCESS;
|
|
69
|
+
if (statusCode === 422) return codes.VALIDATION;
|
|
70
|
+
if (statusCode >= 400 && statusCode < 500) return codes.CLIENT;
|
|
71
|
+
if (statusCode >= 500) return codes.SERVER;
|
|
72
|
+
if (statusCode >= 300 && statusCode < 400) return codes.SUCCESS;
|
|
73
|
+
return codes.CLIENT;
|
|
74
|
+
}
|
|
75
|
+
function defaultMessageForCode(code, codes) {
|
|
76
|
+
if (code === codes.SUCCESS) return "Operation successful";
|
|
77
|
+
if (code === codes.CLIENT) return "Client error";
|
|
78
|
+
if (code === codes.SERVER) return "Internal server error";
|
|
79
|
+
if (code === codes.VALIDATION) return "Validation failed";
|
|
80
|
+
return "Operation failed";
|
|
81
|
+
}
|
|
82
|
+
function resolveStatusFromCode(code, codes) {
|
|
83
|
+
return isSuccessCode(code, codes);
|
|
84
|
+
}
|
|
85
|
+
function lookupCode(codes, key, fallback) {
|
|
86
|
+
return codes[key] ?? fallback;
|
|
87
|
+
}
|
|
88
|
+
function inferHttpStatusFromCode(code, codes) {
|
|
89
|
+
if (code === void 0) return StatusCodes.SUCCESSFUL.OK;
|
|
90
|
+
if (code === codes.SUCCESS) return StatusCodes.SUCCESSFUL.OK;
|
|
91
|
+
if (code === codes.VALIDATION) return StatusCodes.CLIENT_ERROR.UNPROCESSABLE_ENTITY;
|
|
92
|
+
if (code === codes.SERVER) return StatusCodes.SERVER_ERROR.INTERNAL_SERVER_ERROR;
|
|
93
|
+
if (code === codes.CLIENT) return StatusCodes.CLIENT_ERROR.BAD_REQUEST;
|
|
94
|
+
return StatusCodes.CLIENT_ERROR.BAD_REQUEST;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/errors/error.ts
|
|
98
|
+
var ResponseError = class extends Error {
|
|
99
|
+
code;
|
|
100
|
+
httpStatus;
|
|
101
|
+
payload;
|
|
102
|
+
constructor(options = {}) {
|
|
103
|
+
const codes = createCodeRegistry(options.codes);
|
|
104
|
+
const code = options.code ?? codes.SERVER;
|
|
105
|
+
const message = options.message ?? defaultMessageForCode(code, codes);
|
|
106
|
+
super(message, { cause: options.cause });
|
|
107
|
+
this.name = "ResponseError";
|
|
108
|
+
this.code = code;
|
|
109
|
+
this.httpStatus = options.httpStatus ?? codeToDefaultHttpStatus(code, codes);
|
|
110
|
+
if (options.payload !== void 0) {
|
|
111
|
+
this.payload = options.payload;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
toJSON() {
|
|
115
|
+
return {
|
|
116
|
+
name: this.name,
|
|
117
|
+
message: this.message,
|
|
118
|
+
code: this.code,
|
|
119
|
+
httpStatus: this.httpStatus,
|
|
120
|
+
payload: this.payload
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
var ClientError = class extends ResponseError {
|
|
125
|
+
constructor(message, options = {}) {
|
|
126
|
+
const codes = createCodeRegistry(options.codes);
|
|
127
|
+
super({
|
|
128
|
+
...options,
|
|
129
|
+
message: message ?? defaultMessageForCode(codes.CLIENT, codes),
|
|
130
|
+
code: codes.CLIENT,
|
|
131
|
+
httpStatus: options.httpStatus ?? 400,
|
|
132
|
+
codes
|
|
133
|
+
});
|
|
134
|
+
this.name = "ClientError";
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
var ServerError = class extends ResponseError {
|
|
138
|
+
constructor(message, options = {}) {
|
|
139
|
+
const codes = createCodeRegistry(options.codes);
|
|
140
|
+
super({
|
|
141
|
+
...options,
|
|
142
|
+
message: message ?? defaultMessageForCode(codes.SERVER, codes),
|
|
143
|
+
code: codes.SERVER,
|
|
144
|
+
httpStatus: options.httpStatus ?? 500,
|
|
145
|
+
codes
|
|
146
|
+
});
|
|
147
|
+
this.name = "ServerError";
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
var ValidationError = class extends ResponseError {
|
|
151
|
+
constructor(message, options = {}) {
|
|
152
|
+
const codes = createCodeRegistry(options.codes);
|
|
153
|
+
super({
|
|
154
|
+
...options,
|
|
155
|
+
message: message ?? defaultMessageForCode(codes.VALIDATION, codes),
|
|
156
|
+
code: codes.VALIDATION,
|
|
157
|
+
httpStatus: options.httpStatus ?? 422,
|
|
158
|
+
codes
|
|
159
|
+
});
|
|
160
|
+
this.name = "ValidationError";
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
function isResponseError(value) {
|
|
164
|
+
return value instanceof ResponseError;
|
|
165
|
+
}
|
|
166
|
+
function codeToDefaultHttpStatus(code, codes) {
|
|
167
|
+
if (code === codes.SUCCESS) return 200;
|
|
168
|
+
if (code === codes.CLIENT) return 400;
|
|
169
|
+
if (code === codes.SERVER) return 500;
|
|
170
|
+
if (code === codes.VALIDATION) return 422;
|
|
171
|
+
return 500;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/core/assemble.ts
|
|
175
|
+
function assembleResponseBody(input) {
|
|
176
|
+
const ordered = {
|
|
177
|
+
status: input.status,
|
|
178
|
+
message: input.message
|
|
179
|
+
};
|
|
180
|
+
if (input.payload !== void 0 && Object.keys(input.payload).length > 0) {
|
|
181
|
+
ordered.payload = input.payload;
|
|
182
|
+
}
|
|
183
|
+
ordered.code = input.code;
|
|
184
|
+
return ordered;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/dto/log/assemble.ts
|
|
188
|
+
function assembleLogBody(input) {
|
|
189
|
+
const ordered = {
|
|
190
|
+
level: input.level,
|
|
191
|
+
service: input.service
|
|
192
|
+
};
|
|
193
|
+
if (input.message !== void 0) {
|
|
194
|
+
ordered.message = input.message;
|
|
195
|
+
}
|
|
196
|
+
if (input.payload !== void 0 && Object.keys(input.payload).length > 0) {
|
|
197
|
+
ordered.payload = input.payload;
|
|
198
|
+
}
|
|
199
|
+
if (input.code !== void 0) {
|
|
200
|
+
ordered.code = input.code;
|
|
201
|
+
}
|
|
202
|
+
ordered.timestamp = input.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
203
|
+
if (input.id !== void 0) {
|
|
204
|
+
ordered.id = input.id;
|
|
205
|
+
}
|
|
206
|
+
ordered.env = input.env;
|
|
207
|
+
return ordered;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/dto/queue/assemble.ts
|
|
211
|
+
function assembleQueueMessage(metadata, payload) {
|
|
212
|
+
const orderedMetadata = {
|
|
213
|
+
source: metadata.source,
|
|
214
|
+
eventType: metadata.eventType,
|
|
215
|
+
timestamp: metadata.timestamp,
|
|
216
|
+
correlationId: metadata.correlationId
|
|
217
|
+
};
|
|
218
|
+
if (metadata.userId !== void 0) {
|
|
219
|
+
orderedMetadata.userId = metadata.userId;
|
|
220
|
+
}
|
|
221
|
+
if (metadata.extraData !== void 0) {
|
|
222
|
+
orderedMetadata.extraData = metadata.extraData;
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
metadata: orderedMetadata,
|
|
226
|
+
payload
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/dto/shared/schema-utils.ts
|
|
231
|
+
function assertRequiredFields(input, fields, label = "Missing required fields") {
|
|
232
|
+
const missing = fields.filter((field) => {
|
|
233
|
+
const value = input[field];
|
|
234
|
+
return value === void 0 || value === null || value === "";
|
|
235
|
+
});
|
|
236
|
+
if (missing.length > 0) {
|
|
237
|
+
throw new Error(`${label}: ${missing.join(", ")}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// src/dto/shared/base-dto.ts
|
|
242
|
+
var BaseDTO = class {
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// src/dto/response/dto.ts
|
|
246
|
+
var ResponseDTO = class _ResponseDTO extends BaseDTO {
|
|
247
|
+
_status;
|
|
248
|
+
_message;
|
|
249
|
+
_code;
|
|
250
|
+
_payload = {};
|
|
251
|
+
static status(value) {
|
|
252
|
+
return new _ResponseDTO().status(value);
|
|
253
|
+
}
|
|
254
|
+
static message(value) {
|
|
255
|
+
return new _ResponseDTO().message(value);
|
|
256
|
+
}
|
|
257
|
+
static code(value) {
|
|
258
|
+
return new _ResponseDTO().code(value);
|
|
259
|
+
}
|
|
260
|
+
static data(data) {
|
|
261
|
+
return new _ResponseDTO().data(data);
|
|
262
|
+
}
|
|
263
|
+
static payload(partial) {
|
|
264
|
+
return new _ResponseDTO().payload(partial);
|
|
265
|
+
}
|
|
266
|
+
static schema(input = {}, codes = DefaultCodes) {
|
|
267
|
+
return new _ResponseDTO().schema(input, codes);
|
|
268
|
+
}
|
|
269
|
+
status(value) {
|
|
270
|
+
this._status = value;
|
|
271
|
+
return this;
|
|
272
|
+
}
|
|
273
|
+
message(msg) {
|
|
274
|
+
this._message = msg;
|
|
275
|
+
return this;
|
|
276
|
+
}
|
|
277
|
+
code(code) {
|
|
278
|
+
this._code = code;
|
|
279
|
+
return this;
|
|
280
|
+
}
|
|
281
|
+
data(data) {
|
|
282
|
+
if (data === void 0) {
|
|
283
|
+
delete this._payload.data;
|
|
284
|
+
} else {
|
|
285
|
+
this._payload.data = data;
|
|
286
|
+
}
|
|
287
|
+
return this;
|
|
288
|
+
}
|
|
289
|
+
payload(partial) {
|
|
290
|
+
this._payload = { ...this._payload, ...partial };
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
setMeta(meta) {
|
|
294
|
+
this._payload.meta = { ...this._payload.meta ?? {}, ...meta };
|
|
295
|
+
return this;
|
|
296
|
+
}
|
|
297
|
+
paginate(total, page, limit) {
|
|
298
|
+
if (limit <= 0) {
|
|
299
|
+
throw new Error("ResponseDTO.paginate: limit must be greater than 0");
|
|
300
|
+
}
|
|
301
|
+
this._payload.pagination = {
|
|
302
|
+
total,
|
|
303
|
+
page,
|
|
304
|
+
limit,
|
|
305
|
+
totalPages: Math.ceil(total / limit),
|
|
306
|
+
hasNext: page * limit < total
|
|
307
|
+
};
|
|
308
|
+
return this;
|
|
309
|
+
}
|
|
310
|
+
schema(input = {}, codes = DefaultCodes) {
|
|
311
|
+
const { status, message, code, payload } = input;
|
|
312
|
+
if (code !== void 0) {
|
|
313
|
+
this.code(code);
|
|
314
|
+
}
|
|
315
|
+
if (status !== void 0) {
|
|
316
|
+
this.status(status);
|
|
317
|
+
} else if (code !== void 0) {
|
|
318
|
+
this.status(resolveStatusFromCode(code, codes));
|
|
319
|
+
}
|
|
320
|
+
if (message !== void 0) {
|
|
321
|
+
this.message(message);
|
|
322
|
+
}
|
|
323
|
+
if (payload !== void 0) {
|
|
324
|
+
this._payload = { ...payload };
|
|
325
|
+
}
|
|
326
|
+
return this;
|
|
327
|
+
}
|
|
328
|
+
getCode() {
|
|
329
|
+
return this._code;
|
|
330
|
+
}
|
|
331
|
+
getMessage() {
|
|
332
|
+
return this._message;
|
|
333
|
+
}
|
|
334
|
+
setCodeFromHttpStatus(httpStatusCode, codes) {
|
|
335
|
+
if (this._code === void 0) {
|
|
336
|
+
this._code = resolveCodeFromHttpStatus(httpStatusCode, codes);
|
|
337
|
+
}
|
|
338
|
+
return this;
|
|
339
|
+
}
|
|
340
|
+
transformData(fn) {
|
|
341
|
+
const next = new _ResponseDTO();
|
|
342
|
+
next._status = this._status;
|
|
343
|
+
next._message = this._message;
|
|
344
|
+
next._code = this._code;
|
|
345
|
+
next._payload = { ...this._payload };
|
|
346
|
+
if (this._payload.data !== void 0) {
|
|
347
|
+
next._payload.data = fn(this._payload.data);
|
|
348
|
+
}
|
|
349
|
+
return next;
|
|
350
|
+
}
|
|
351
|
+
build(options = {}) {
|
|
352
|
+
const codes = options.codes ?? DefaultCodes;
|
|
353
|
+
const code = this._code ?? (options.httpStatusCode !== void 0 ? resolveCodeFromHttpStatus(options.httpStatusCode, codes) : codes.SUCCESS);
|
|
354
|
+
const status = this._status ?? isSuccessCode(code, codes);
|
|
355
|
+
const message = this._message ?? defaultMessageForCode(code, codes);
|
|
356
|
+
if (options.withDefaultBody === false) {
|
|
357
|
+
return assembleResponseBody({ status, message, code });
|
|
358
|
+
}
|
|
359
|
+
const payload = this.buildPayload();
|
|
360
|
+
return assembleResponseBody({
|
|
361
|
+
status,
|
|
362
|
+
message,
|
|
363
|
+
payload,
|
|
364
|
+
code
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
buildPayload() {
|
|
368
|
+
const entries = Object.entries(this._payload).filter(([, value]) => value !== void 0);
|
|
369
|
+
if (entries.length === 0) return void 0;
|
|
370
|
+
return Object.fromEntries(entries);
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
// src/dto/log/builder.ts
|
|
375
|
+
var LogDTO = class _LogDTO extends BaseDTO {
|
|
376
|
+
_level;
|
|
377
|
+
_service;
|
|
378
|
+
_env;
|
|
379
|
+
_message;
|
|
380
|
+
_payload = {};
|
|
381
|
+
_code;
|
|
382
|
+
_timestamp;
|
|
383
|
+
_id;
|
|
384
|
+
static level(value) {
|
|
385
|
+
return new _LogDTO().level(value);
|
|
386
|
+
}
|
|
387
|
+
static service(value) {
|
|
388
|
+
return new _LogDTO().service(value);
|
|
389
|
+
}
|
|
390
|
+
static env(value) {
|
|
391
|
+
return new _LogDTO().env(value);
|
|
392
|
+
}
|
|
393
|
+
static message(value) {
|
|
394
|
+
return new _LogDTO().message(value);
|
|
395
|
+
}
|
|
396
|
+
static code(value) {
|
|
397
|
+
return new _LogDTO().code(value);
|
|
398
|
+
}
|
|
399
|
+
static timestamp(value) {
|
|
400
|
+
return new _LogDTO().timestamp(value);
|
|
401
|
+
}
|
|
402
|
+
static id(value) {
|
|
403
|
+
return new _LogDTO().id(value);
|
|
404
|
+
}
|
|
405
|
+
static payload(partial) {
|
|
406
|
+
return new _LogDTO().payload(partial);
|
|
407
|
+
}
|
|
408
|
+
/** One-shot body input — same last-wins rules as the instance `.schema()`. */
|
|
409
|
+
static schema(input = {}) {
|
|
410
|
+
return new _LogDTO().schema(input);
|
|
411
|
+
}
|
|
412
|
+
level(value) {
|
|
413
|
+
this._level = value;
|
|
414
|
+
return this;
|
|
415
|
+
}
|
|
416
|
+
service(value) {
|
|
417
|
+
this._service = value;
|
|
418
|
+
return this;
|
|
419
|
+
}
|
|
420
|
+
env(value) {
|
|
421
|
+
this._env = value;
|
|
422
|
+
return this;
|
|
423
|
+
}
|
|
424
|
+
message(value) {
|
|
425
|
+
this._message = value;
|
|
426
|
+
return this;
|
|
427
|
+
}
|
|
428
|
+
code(value) {
|
|
429
|
+
this._code = value;
|
|
430
|
+
return this;
|
|
431
|
+
}
|
|
432
|
+
timestamp(value) {
|
|
433
|
+
this._timestamp = value;
|
|
434
|
+
return this;
|
|
435
|
+
}
|
|
436
|
+
id(value) {
|
|
437
|
+
this._id = value;
|
|
438
|
+
return this;
|
|
439
|
+
}
|
|
440
|
+
payload(partial) {
|
|
441
|
+
this._payload = { ...this._payload, ...partial };
|
|
442
|
+
return this;
|
|
443
|
+
}
|
|
444
|
+
schema(input = {}) {
|
|
445
|
+
const { level, service, message, env, code, timestamp, id, payload } = input;
|
|
446
|
+
if (level !== void 0) this.level(level);
|
|
447
|
+
if (service !== void 0) this.service(service);
|
|
448
|
+
if (env !== void 0) this.env(env);
|
|
449
|
+
if (message !== void 0) this.message(message);
|
|
450
|
+
if (code !== void 0) this.code(code);
|
|
451
|
+
if (timestamp !== void 0) this.timestamp(timestamp);
|
|
452
|
+
if (id !== void 0) this.id(id);
|
|
453
|
+
if (payload !== void 0) {
|
|
454
|
+
this._payload = { ...payload };
|
|
455
|
+
}
|
|
456
|
+
return this;
|
|
457
|
+
}
|
|
458
|
+
build() {
|
|
459
|
+
assertRequiredFields(
|
|
460
|
+
{
|
|
461
|
+
level: this._level,
|
|
462
|
+
service: this._service,
|
|
463
|
+
env: this._env
|
|
464
|
+
},
|
|
465
|
+
["level", "service", "env"],
|
|
466
|
+
"Missing log fields"
|
|
467
|
+
);
|
|
468
|
+
const input = {
|
|
469
|
+
level: this._level,
|
|
470
|
+
service: this._service,
|
|
471
|
+
env: this._env,
|
|
472
|
+
message: this._message,
|
|
473
|
+
code: this._code,
|
|
474
|
+
timestamp: this._timestamp,
|
|
475
|
+
id: this._id
|
|
476
|
+
};
|
|
477
|
+
if (Object.keys(this._payload).length > 0) {
|
|
478
|
+
input.payload = this._payload;
|
|
479
|
+
}
|
|
480
|
+
return assembleLogBody(input);
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
// src/utils/helpers/uuid.ts
|
|
485
|
+
function generateUUID() {
|
|
486
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
487
|
+
return crypto.randomUUID();
|
|
488
|
+
}
|
|
489
|
+
const bytes = new Uint8Array(16);
|
|
490
|
+
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
|
|
491
|
+
crypto.getRandomValues(bytes);
|
|
492
|
+
} else {
|
|
493
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
494
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
498
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
499
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
500
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
501
|
+
}
|
|
502
|
+
function isValidUUID(id) {
|
|
503
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// src/dto/queue/builder.ts
|
|
507
|
+
var QueueDTO = class _QueueDTO extends BaseDTO {
|
|
508
|
+
_source;
|
|
509
|
+
_eventType;
|
|
510
|
+
_userId;
|
|
511
|
+
_correlationId;
|
|
512
|
+
_extraData;
|
|
513
|
+
_payload;
|
|
514
|
+
_timestamp;
|
|
515
|
+
static source(value) {
|
|
516
|
+
return new _QueueDTO().source(value);
|
|
517
|
+
}
|
|
518
|
+
static eventType(value) {
|
|
519
|
+
return new _QueueDTO().eventType(value);
|
|
520
|
+
}
|
|
521
|
+
static userId(value) {
|
|
522
|
+
return new _QueueDTO().userId(value);
|
|
523
|
+
}
|
|
524
|
+
static correlationId(value) {
|
|
525
|
+
return new _QueueDTO().correlationId(value);
|
|
526
|
+
}
|
|
527
|
+
static extraData(value) {
|
|
528
|
+
return new _QueueDTO().extraData(value);
|
|
529
|
+
}
|
|
530
|
+
static timestamp(value) {
|
|
531
|
+
return new _QueueDTO().timestamp(value);
|
|
532
|
+
}
|
|
533
|
+
static payload(value) {
|
|
534
|
+
return new _QueueDTO().payload(value);
|
|
535
|
+
}
|
|
536
|
+
static schema(input = {}) {
|
|
537
|
+
return new _QueueDTO().schema(input);
|
|
538
|
+
}
|
|
539
|
+
source(value) {
|
|
540
|
+
this._source = value;
|
|
541
|
+
return this;
|
|
542
|
+
}
|
|
543
|
+
eventType(value) {
|
|
544
|
+
this._eventType = value;
|
|
545
|
+
return this;
|
|
546
|
+
}
|
|
547
|
+
userId(value) {
|
|
548
|
+
this._userId = value;
|
|
549
|
+
return this;
|
|
550
|
+
}
|
|
551
|
+
correlationId(value) {
|
|
552
|
+
this._correlationId = value;
|
|
553
|
+
return this;
|
|
554
|
+
}
|
|
555
|
+
extraData(value) {
|
|
556
|
+
this._extraData = value;
|
|
557
|
+
return this;
|
|
558
|
+
}
|
|
559
|
+
timestamp(value) {
|
|
560
|
+
this._timestamp = value;
|
|
561
|
+
return this;
|
|
562
|
+
}
|
|
563
|
+
payload(value) {
|
|
564
|
+
this._payload = value;
|
|
565
|
+
return this;
|
|
566
|
+
}
|
|
567
|
+
schema(input = {}) {
|
|
568
|
+
const { metadata, payload } = input;
|
|
569
|
+
if (metadata?.source !== void 0) this.source(metadata.source);
|
|
570
|
+
if (metadata?.eventType !== void 0) this.eventType(metadata.eventType);
|
|
571
|
+
if (metadata?.userId !== void 0) this.userId(metadata.userId);
|
|
572
|
+
if (metadata?.correlationId !== void 0) this.correlationId(metadata.correlationId);
|
|
573
|
+
if (metadata?.extraData !== void 0) this.extraData(metadata.extraData);
|
|
574
|
+
if (payload !== void 0) {
|
|
575
|
+
this._payload = payload;
|
|
576
|
+
}
|
|
577
|
+
return this;
|
|
578
|
+
}
|
|
579
|
+
build() {
|
|
580
|
+
assertRequiredFields(
|
|
581
|
+
{
|
|
582
|
+
source: this._source,
|
|
583
|
+
eventType: this._eventType
|
|
584
|
+
},
|
|
585
|
+
["source", "eventType"],
|
|
586
|
+
"Missing queue metadata fields"
|
|
587
|
+
);
|
|
588
|
+
return assembleQueueMessage(
|
|
589
|
+
{
|
|
590
|
+
source: this._source,
|
|
591
|
+
eventType: this._eventType,
|
|
592
|
+
timestamp: this._timestamp ?? Date.now(),
|
|
593
|
+
correlationId: this._correlationId ?? generateUUID(),
|
|
594
|
+
userId: this._userId,
|
|
595
|
+
extraData: this._extraData
|
|
596
|
+
},
|
|
597
|
+
this._payload
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
// src/utils/helpers/request-id.ts
|
|
603
|
+
var DEFAULT_REQUEST_ID_HEADERS = [
|
|
604
|
+
"x-request-id",
|
|
605
|
+
"x-correlation-id",
|
|
606
|
+
"traceparent"
|
|
607
|
+
];
|
|
608
|
+
function readHeader(req, name) {
|
|
609
|
+
const fromGet = req.get?.(name);
|
|
610
|
+
if (fromGet) return fromGet;
|
|
611
|
+
const headers = req.headers;
|
|
612
|
+
if (!headers) return void 0;
|
|
613
|
+
const direct = headers[name] ?? headers[name.toLowerCase()];
|
|
614
|
+
if (direct === void 0) return void 0;
|
|
615
|
+
return Array.isArray(direct) ? direct[0] : direct;
|
|
616
|
+
}
|
|
617
|
+
function traceIdFromTraceparent(traceparent) {
|
|
618
|
+
const parts = traceparent.trim().split("-");
|
|
619
|
+
if (parts.length < 2) return void 0;
|
|
620
|
+
const traceId = parts[1];
|
|
621
|
+
if (!traceId || !/^[0-9a-f]{32}$/i.test(traceId)) return void 0;
|
|
622
|
+
return `${traceId.slice(0, 8)}-${traceId.slice(8, 12)}-${traceId.slice(12, 16)}-${traceId.slice(16, 20)}-${traceId.slice(20)}`;
|
|
623
|
+
}
|
|
624
|
+
function resolveRequestId(req, headerNames = DEFAULT_REQUEST_ID_HEADERS) {
|
|
625
|
+
for (const name of headerNames) {
|
|
626
|
+
const raw = readHeader(req, name);
|
|
627
|
+
if (!raw?.trim()) continue;
|
|
628
|
+
if (name === "traceparent") {
|
|
629
|
+
const traceId = traceIdFromTraceparent(raw);
|
|
630
|
+
if (traceId) return traceId;
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
const id = raw.trim();
|
|
634
|
+
if (isValidUUID(id)) return id;
|
|
635
|
+
return id;
|
|
636
|
+
}
|
|
637
|
+
return generateUUID();
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// src/core/context.ts
|
|
641
|
+
var ContextFactory = class {
|
|
642
|
+
static create(req, options = {}) {
|
|
643
|
+
return {
|
|
644
|
+
requestId: resolveRequestId(req, options.requestIdHeaders),
|
|
645
|
+
startTime: Date.now()
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
static fromId(requestId) {
|
|
649
|
+
return {
|
|
650
|
+
requestId,
|
|
651
|
+
startTime: Date.now()
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
// src/core/metadata.ts
|
|
657
|
+
var MetadataFactory = class {
|
|
658
|
+
static create(options = {}, context) {
|
|
659
|
+
return {
|
|
660
|
+
requestId: context?.requestId ?? generateUUID(),
|
|
661
|
+
serverTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
662
|
+
statusCode: 200,
|
|
663
|
+
...options
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
// src/core/hooks.ts
|
|
669
|
+
var Hooks = class {
|
|
670
|
+
listeners = {};
|
|
671
|
+
emittingError = false;
|
|
672
|
+
on(event, fn) {
|
|
673
|
+
if (!this.listeners[event]) this.listeners[event] = [];
|
|
674
|
+
this.listeners[event].push(fn);
|
|
675
|
+
return this;
|
|
676
|
+
}
|
|
677
|
+
hasListeners(event) {
|
|
678
|
+
return (this.listeners[event]?.length ?? 0) > 0;
|
|
679
|
+
}
|
|
680
|
+
emit(event, payload) {
|
|
681
|
+
const fns = this.listeners[event];
|
|
682
|
+
if (!fns?.length) return;
|
|
683
|
+
for (const fn of fns) {
|
|
684
|
+
try {
|
|
685
|
+
fn(payload);
|
|
686
|
+
} catch (err) {
|
|
687
|
+
if (event === "error" || this.emittingError) continue;
|
|
688
|
+
this.emittingError = true;
|
|
689
|
+
try {
|
|
690
|
+
this.emit("error", { sourceEvent: event, error: err, payload });
|
|
691
|
+
} finally {
|
|
692
|
+
this.emittingError = false;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
// src/core/plugins.ts
|
|
700
|
+
function sortPlugins(plugins) {
|
|
701
|
+
return [...plugins].sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
|
|
702
|
+
}
|
|
703
|
+
var PluginRegistry = class {
|
|
704
|
+
plugins;
|
|
705
|
+
constructor(plugins = []) {
|
|
706
|
+
this.plugins = sortPlugins(plugins);
|
|
707
|
+
}
|
|
708
|
+
runBeforeBuild(ctx) {
|
|
709
|
+
for (const plugin of this.plugins) {
|
|
710
|
+
plugin.beforeBuild?.(ctx);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
runAfterBuild(result, ctx) {
|
|
714
|
+
let current = result;
|
|
715
|
+
for (const plugin of this.plugins) {
|
|
716
|
+
const next = plugin.afterBuild?.(current, ctx);
|
|
717
|
+
if (next) current = next;
|
|
718
|
+
}
|
|
719
|
+
return current;
|
|
720
|
+
}
|
|
721
|
+
runBeforeDispatch(result, ctx) {
|
|
722
|
+
let current = result;
|
|
723
|
+
for (const plugin of this.plugins) {
|
|
724
|
+
const next = plugin.beforeDispatch?.(current, ctx);
|
|
725
|
+
if (next) current = next;
|
|
726
|
+
}
|
|
727
|
+
return current;
|
|
728
|
+
}
|
|
729
|
+
runAfterDispatch(result, ctx) {
|
|
730
|
+
for (const plugin of this.plugins) {
|
|
731
|
+
plugin.afterDispatch?.(result, ctx);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
// src/core/presets.ts
|
|
737
|
+
var ResponsePresets = class {
|
|
738
|
+
builder;
|
|
739
|
+
codes;
|
|
740
|
+
constructor(builder, codes) {
|
|
741
|
+
this.builder = builder;
|
|
742
|
+
this.codes = codes;
|
|
743
|
+
}
|
|
744
|
+
applyExtras(extras) {
|
|
745
|
+
if (extras && Object.keys(extras).length > 0) {
|
|
746
|
+
this.builder.payload(extras);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
dispatch() {
|
|
750
|
+
return this.builder.build();
|
|
751
|
+
}
|
|
752
|
+
resolveFailureArgs(dataOrMessage, messageOrExtras, extras) {
|
|
753
|
+
if (typeof dataOrMessage === "string") {
|
|
754
|
+
return {
|
|
755
|
+
message: dataOrMessage,
|
|
756
|
+
extras: typeof messageOrExtras === "string" ? extras : messageOrExtras
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
return {
|
|
760
|
+
data: dataOrMessage,
|
|
761
|
+
message: typeof messageOrExtras === "string" ? messageOrExtras : void 0,
|
|
762
|
+
extras: typeof messageOrExtras === "string" ? extras : messageOrExtras
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
failure(httpStatus, code, dataOrMessage, messageOrExtras, extras) {
|
|
766
|
+
const resolved = this.resolveFailureArgs(dataOrMessage, messageOrExtras, extras);
|
|
767
|
+
this.builder.httpStatus(httpStatus).code(code).status(false).message(resolved.message ?? defaultMessageForCode(code, this.codes)).data(resolved.data);
|
|
768
|
+
this.applyExtras(resolved.extras);
|
|
769
|
+
return this.dispatch();
|
|
770
|
+
}
|
|
771
|
+
ok(data, message, extras) {
|
|
772
|
+
this.builder.httpStatus(StatusCodes.SUCCESSFUL.OK).code(this.codes.SUCCESS).status(true).message(message ?? defaultMessageForCode(this.codes.SUCCESS, this.codes)).data(data);
|
|
773
|
+
this.applyExtras(extras);
|
|
774
|
+
return this.dispatch();
|
|
775
|
+
}
|
|
776
|
+
created(data, message, extras) {
|
|
777
|
+
this.builder.httpStatus(StatusCodes.SUCCESSFUL.CREATED).code(this.codes.SUCCESS).status(true).message(message ?? defaultMessageForCode(this.codes.SUCCESS, this.codes)).data(data);
|
|
778
|
+
this.applyExtras(extras);
|
|
779
|
+
return this.dispatch();
|
|
780
|
+
}
|
|
781
|
+
accepted(message, extras) {
|
|
782
|
+
this.builder.httpStatus(StatusCodes.SUCCESSFUL.ACCEPTED).code(this.codes.SUCCESS).status(true).message(message ?? defaultMessageForCode(this.codes.SUCCESS, this.codes));
|
|
783
|
+
this.applyExtras(extras);
|
|
784
|
+
return this.dispatch();
|
|
785
|
+
}
|
|
786
|
+
noContent(extras) {
|
|
787
|
+
this.builder.httpStatus(StatusCodes.SUCCESSFUL.NO_CONTENT).code(this.codes.SUCCESS).status(true).message("").data(void 0);
|
|
788
|
+
this.applyExtras(extras);
|
|
789
|
+
return this.dispatch();
|
|
790
|
+
}
|
|
791
|
+
/** Generic client failure — HTTP 400, CLIENT code */
|
|
792
|
+
fail(dataOrMessage, messageOrExtras, extras) {
|
|
793
|
+
return this.failure(StatusCodes.CLIENT_ERROR.BAD_REQUEST, this.codes.CLIENT, dataOrMessage, messageOrExtras, extras);
|
|
794
|
+
}
|
|
795
|
+
/** Generic server failure — HTTP 500, SERVER code */
|
|
796
|
+
error(dataOrMessage, messageOrExtras, extras) {
|
|
797
|
+
return this.failure(
|
|
798
|
+
StatusCodes.SERVER_ERROR.INTERNAL_SERVER_ERROR,
|
|
799
|
+
this.codes.SERVER,
|
|
800
|
+
dataOrMessage,
|
|
801
|
+
messageOrExtras,
|
|
802
|
+
extras
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
badRequest(dataOrMessage, messageOrExtras, extras) {
|
|
806
|
+
return this.failure(StatusCodes.CLIENT_ERROR.BAD_REQUEST, this.codes.CLIENT, dataOrMessage, messageOrExtras, extras);
|
|
807
|
+
}
|
|
808
|
+
unauthorized(dataOrMessage, messageOrExtras, extras) {
|
|
809
|
+
return this.failure(StatusCodes.CLIENT_ERROR.UNAUTHORIZED, this.codes.CLIENT, dataOrMessage, messageOrExtras, extras);
|
|
810
|
+
}
|
|
811
|
+
forbidden(dataOrMessage, messageOrExtras, extras) {
|
|
812
|
+
return this.failure(StatusCodes.CLIENT_ERROR.FORBIDDEN, this.codes.CLIENT, dataOrMessage, messageOrExtras, extras);
|
|
813
|
+
}
|
|
814
|
+
notFound(dataOrMessage, messageOrExtras, extras) {
|
|
815
|
+
return this.failure(StatusCodes.CLIENT_ERROR.NOT_FOUND, this.codes.CLIENT, dataOrMessage, messageOrExtras, extras);
|
|
816
|
+
}
|
|
817
|
+
conflict(dataOrMessage, messageOrExtras, extras) {
|
|
818
|
+
return this.failure(StatusCodes.CLIENT_ERROR.CONFLICT, this.codes.CLIENT, dataOrMessage, messageOrExtras, extras);
|
|
819
|
+
}
|
|
820
|
+
unprocessable(dataOrMessage, messageOrExtras, extras) {
|
|
821
|
+
return this.failure(
|
|
822
|
+
StatusCodes.CLIENT_ERROR.UNPROCESSABLE_ENTITY,
|
|
823
|
+
this.codes.VALIDATION,
|
|
824
|
+
dataOrMessage,
|
|
825
|
+
messageOrExtras,
|
|
826
|
+
extras
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
tooManyRequests(dataOrMessage, messageOrExtras, extras) {
|
|
830
|
+
return this.failure(StatusCodes.CLIENT_ERROR.TOO_MANY_REQUESTS, this.codes.CLIENT, dataOrMessage, messageOrExtras, extras);
|
|
831
|
+
}
|
|
832
|
+
internalServerError(dataOrMessage, messageOrExtras, extras) {
|
|
833
|
+
return this.failure(
|
|
834
|
+
StatusCodes.SERVER_ERROR.INTERNAL_SERVER_ERROR,
|
|
835
|
+
this.codes.SERVER,
|
|
836
|
+
dataOrMessage,
|
|
837
|
+
messageOrExtras,
|
|
838
|
+
extras
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
serviceUnavailable(dataOrMessage, messageOrExtras, extras) {
|
|
842
|
+
return this.failure(
|
|
843
|
+
StatusCodes.SERVER_ERROR.SERVICE_UNAVAILABLE,
|
|
844
|
+
this.codes.SERVER,
|
|
845
|
+
dataOrMessage,
|
|
846
|
+
messageOrExtras,
|
|
847
|
+
extras
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
gatewayTimeout(dataOrMessage, messageOrExtras, extras) {
|
|
851
|
+
return this.failure(
|
|
852
|
+
StatusCodes.SERVER_ERROR.GATEWAY_TIMEOUT,
|
|
853
|
+
this.codes.SERVER,
|
|
854
|
+
dataOrMessage,
|
|
855
|
+
messageOrExtras,
|
|
856
|
+
extras
|
|
857
|
+
);
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
// src/core/config.ts
|
|
862
|
+
function resolveBuilderConfig(options = {}) {
|
|
863
|
+
return {
|
|
864
|
+
verbose: options.verbose === true,
|
|
865
|
+
includeStack: options.includeStack,
|
|
866
|
+
withDefaultBody: options.withDefaultBody !== false,
|
|
867
|
+
codes: createCodeRegistry(options.codes),
|
|
868
|
+
hooks: options.hooks,
|
|
869
|
+
plugins: options.plugins ?? []
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// src/core/builder.ts
|
|
874
|
+
var Builder = class {
|
|
875
|
+
dispatcher;
|
|
876
|
+
options;
|
|
877
|
+
context;
|
|
878
|
+
plugins;
|
|
879
|
+
body;
|
|
880
|
+
_statusCode = StatusCodes.SUCCESSFUL.OK;
|
|
881
|
+
_headers = {};
|
|
882
|
+
_cookies = [];
|
|
883
|
+
_presets;
|
|
884
|
+
constructor(dispatcher, options = {}, context) {
|
|
885
|
+
this.dispatcher = dispatcher;
|
|
886
|
+
this.options = resolveBuilderConfig(options);
|
|
887
|
+
this.context = context;
|
|
888
|
+
this.plugins = new PluginRegistry(this.options.plugins);
|
|
889
|
+
this.body = new ResponseDTO();
|
|
890
|
+
}
|
|
891
|
+
get dto() {
|
|
892
|
+
return this.body;
|
|
893
|
+
}
|
|
894
|
+
httpStatus(code) {
|
|
895
|
+
this._statusCode = code;
|
|
896
|
+
this.body.setCodeFromHttpStatus(code, this.options.codes);
|
|
897
|
+
return this;
|
|
898
|
+
}
|
|
899
|
+
code(code) {
|
|
900
|
+
this.body.code(code);
|
|
901
|
+
return this;
|
|
902
|
+
}
|
|
903
|
+
status(value) {
|
|
904
|
+
this.body.status(value);
|
|
905
|
+
return this;
|
|
906
|
+
}
|
|
907
|
+
message(msg) {
|
|
908
|
+
this.body.message(msg);
|
|
909
|
+
return this;
|
|
910
|
+
}
|
|
911
|
+
data(data) {
|
|
912
|
+
this.body.data(data);
|
|
913
|
+
return this;
|
|
914
|
+
}
|
|
915
|
+
payload(partial) {
|
|
916
|
+
this.body.payload(partial);
|
|
917
|
+
return this;
|
|
918
|
+
}
|
|
919
|
+
schema(input = {}) {
|
|
920
|
+
this.body.schema(input, this.options.codes);
|
|
921
|
+
return this;
|
|
922
|
+
}
|
|
923
|
+
setMeta(meta) {
|
|
924
|
+
this.body.setMeta(meta);
|
|
925
|
+
return this;
|
|
926
|
+
}
|
|
927
|
+
withMetadata(options = {}) {
|
|
928
|
+
const generated = MetadataFactory.create(
|
|
929
|
+
{ statusCode: this._statusCode, ...options },
|
|
930
|
+
{ requestId: this.context?.requestId }
|
|
931
|
+
);
|
|
932
|
+
return this.setMeta(generated);
|
|
933
|
+
}
|
|
934
|
+
paginate(total, page, limit) {
|
|
935
|
+
this.body.paginate(total, page, limit);
|
|
936
|
+
return this;
|
|
937
|
+
}
|
|
938
|
+
setHeaders(keyOrHeaders, value) {
|
|
939
|
+
if (typeof keyOrHeaders === "string") {
|
|
940
|
+
if (value !== void 0) {
|
|
941
|
+
this._headers[keyOrHeaders] = value;
|
|
942
|
+
}
|
|
943
|
+
} else {
|
|
944
|
+
this._headers = { ...this._headers, ...keyOrHeaders };
|
|
945
|
+
}
|
|
946
|
+
return this;
|
|
947
|
+
}
|
|
948
|
+
header(key, value) {
|
|
949
|
+
return this.setHeaders(key, value);
|
|
950
|
+
}
|
|
951
|
+
setCookies(nameOrCookies, valueOrOptions, options) {
|
|
952
|
+
if (typeof nameOrCookies === "string") {
|
|
953
|
+
if (typeof valueOrOptions === "string") {
|
|
954
|
+
this._cookies.push({ name: nameOrCookies, value: valueOrOptions, options });
|
|
955
|
+
}
|
|
956
|
+
} else {
|
|
957
|
+
const sharedOptions = typeof valueOrOptions === "object" ? valueOrOptions : void 0;
|
|
958
|
+
for (const [name, value] of Object.entries(nameOrCookies)) {
|
|
959
|
+
this._cookies.push({ name, value, options: sharedOptions });
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
return this;
|
|
963
|
+
}
|
|
964
|
+
fromError(error) {
|
|
965
|
+
if (isResponseError(error)) {
|
|
966
|
+
return this.httpStatus(error.httpStatus).code(error.code).message(error.message).payload(error.payload ? { ...error.payload } : {}).data(void 0);
|
|
967
|
+
}
|
|
968
|
+
return this.httpStatus(StatusCodes.SERVER_ERROR.INTERNAL_SERVER_ERROR).code(this.options.codes.SERVER).message(this.resolvePublicErrorMessage(error)).data(void 0);
|
|
969
|
+
}
|
|
970
|
+
async wrap(promise) {
|
|
971
|
+
try {
|
|
972
|
+
this.data(await promise);
|
|
973
|
+
return this;
|
|
974
|
+
} catch (error) {
|
|
975
|
+
this.fromError(error);
|
|
976
|
+
this.options.hooks?.emit("error", {
|
|
977
|
+
error,
|
|
978
|
+
message: this.body.getMessage(),
|
|
979
|
+
statusCode: this._statusCode,
|
|
980
|
+
code: this.body.getCode() ?? resolveCodeFromHttpStatus(this._statusCode, this.options.codes)
|
|
981
|
+
});
|
|
982
|
+
return this;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
transform(fn) {
|
|
986
|
+
const next = this;
|
|
987
|
+
next.body = this.body.transformData(fn);
|
|
988
|
+
return next;
|
|
989
|
+
}
|
|
990
|
+
when(condition, fn) {
|
|
991
|
+
if (condition) fn(this);
|
|
992
|
+
return this;
|
|
993
|
+
}
|
|
994
|
+
get as() {
|
|
995
|
+
if (!this._presets) {
|
|
996
|
+
this._presets = new ResponsePresets(this, this.options.codes);
|
|
997
|
+
}
|
|
998
|
+
return this._presets;
|
|
999
|
+
}
|
|
1000
|
+
build() {
|
|
1001
|
+
const pluginCtx = this.createPluginContext();
|
|
1002
|
+
this.options.hooks?.emit("before_build", { statusCode: this._statusCode });
|
|
1003
|
+
this.plugins.runBeforeBuild(pluginCtx);
|
|
1004
|
+
const body = this.body.build({
|
|
1005
|
+
codes: this.options.codes,
|
|
1006
|
+
withDefaultBody: this.options.withDefaultBody,
|
|
1007
|
+
httpStatusCode: this._statusCode
|
|
1008
|
+
});
|
|
1009
|
+
let result = {
|
|
1010
|
+
body,
|
|
1011
|
+
statusCode: this._statusCode,
|
|
1012
|
+
headers: { ...this._headers },
|
|
1013
|
+
cookies: [...this._cookies]
|
|
1014
|
+
};
|
|
1015
|
+
result = this.plugins.runAfterBuild(result, pluginCtx);
|
|
1016
|
+
this.emitHook("after_build", result);
|
|
1017
|
+
if (this.dispatcher) {
|
|
1018
|
+
result = this.plugins.runBeforeDispatch(result, pluginCtx);
|
|
1019
|
+
this.emitHook("before_dispatch", result);
|
|
1020
|
+
const dispatched = this.dispatcher.dispatch(result);
|
|
1021
|
+
this.plugins.runAfterDispatch(result, pluginCtx);
|
|
1022
|
+
this.emitHook("after_dispatch", result);
|
|
1023
|
+
return dispatched ?? result;
|
|
1024
|
+
}
|
|
1025
|
+
return result;
|
|
1026
|
+
}
|
|
1027
|
+
resolvePublicErrorMessage(error) {
|
|
1028
|
+
if (!this.options.verbose && !isResponseError(error)) {
|
|
1029
|
+
return defaultMessageForCode(this.options.codes.SERVER, this.options.codes);
|
|
1030
|
+
}
|
|
1031
|
+
if (error instanceof Error) {
|
|
1032
|
+
if (this.options.includeStack && error.stack) return error.stack;
|
|
1033
|
+
return error.message || defaultMessageForCode(this.options.codes.SERVER, this.options.codes);
|
|
1034
|
+
}
|
|
1035
|
+
if (typeof error === "string") return error;
|
|
1036
|
+
return defaultMessageForCode(this.options.codes.SERVER, this.options.codes);
|
|
1037
|
+
}
|
|
1038
|
+
createPluginContext() {
|
|
1039
|
+
return {
|
|
1040
|
+
builder: this,
|
|
1041
|
+
context: this.context,
|
|
1042
|
+
options: this.options,
|
|
1043
|
+
codes: this.options.codes
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
emitHook(event, result) {
|
|
1047
|
+
const hooks = this.options.hooks;
|
|
1048
|
+
if (!hooks?.hasListeners(event)) return;
|
|
1049
|
+
hooks.emit(event, structuredClone(result));
|
|
1050
|
+
}
|
|
1051
|
+
};
|
|
1052
|
+
function createBuilderProxy(dispatcher, options = {}, context) {
|
|
1053
|
+
const instance = new Builder(dispatcher, options, context);
|
|
1054
|
+
return new Proxy(instance, {
|
|
1055
|
+
get(target, prop, receiver) {
|
|
1056
|
+
const value = Reflect.get(target, prop, receiver);
|
|
1057
|
+
if (typeof value === "function") {
|
|
1058
|
+
return value.bind(target);
|
|
1059
|
+
}
|
|
1060
|
+
return value;
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// src/utils/constants/security-headers.ts
|
|
1066
|
+
var DEFAULT_SECURITY_HEADERS = {
|
|
1067
|
+
"X-Content-Type-Options": "nosniff",
|
|
1068
|
+
"X-Frame-Options": "DENY",
|
|
1069
|
+
"Referrer-Policy": "strict-origin-when-cross-origin",
|
|
1070
|
+
"Content-Security-Policy": "default-src 'none'; frame-ancestors 'none';",
|
|
1071
|
+
"Cross-Origin-Opener-Policy": "same-origin",
|
|
1072
|
+
"Cache-Control": "no-store",
|
|
1073
|
+
Pragma: "no-cache",
|
|
1074
|
+
"X-DNS-Prefetch-Control": "off"
|
|
1075
|
+
};
|
|
1076
|
+
|
|
1077
|
+
// src/utils/constants/http.ts
|
|
1078
|
+
var NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([204, 205, 304]);
|
|
1079
|
+
function shouldSendResponseBody(statusCode) {
|
|
1080
|
+
return !NO_BODY_STATUS_CODES.has(statusCode);
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
// src/adapters/shared.ts
|
|
1084
|
+
function createBuilderRuntime(dispatcher, options, context) {
|
|
1085
|
+
const builderOptions = {
|
|
1086
|
+
verbose: options.verbose,
|
|
1087
|
+
includeStack: options.includeStack,
|
|
1088
|
+
withDefaultBody: options.withDefaultBody,
|
|
1089
|
+
codes: options.codes,
|
|
1090
|
+
hooks: options.hooks,
|
|
1091
|
+
plugins: options.plugins
|
|
1092
|
+
};
|
|
1093
|
+
return {
|
|
1094
|
+
context,
|
|
1095
|
+
codes: resolveBuilderConfig(builderOptions).codes,
|
|
1096
|
+
builder: createBuilderProxy(dispatcher, builderOptions, context)
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// src/adapters/elysia.ts
|
|
1101
|
+
function createElysiaDerive(options = {}) {
|
|
1102
|
+
return ({ request, set }) => {
|
|
1103
|
+
const context = ContextFactory.create({
|
|
1104
|
+
headers: headersToRecord(request.headers)
|
|
1105
|
+
}, {
|
|
1106
|
+
requestIdHeaders: options.requestIdHeaders
|
|
1107
|
+
});
|
|
1108
|
+
if (options.withDefaultHeaders !== false) {
|
|
1109
|
+
const headers = options.defaultHeaders ?? DEFAULT_SECURITY_HEADERS;
|
|
1110
|
+
set.headers = { ...set.headers ?? {}, ...headers };
|
|
1111
|
+
}
|
|
1112
|
+
const runtime = createBuilderRuntime(
|
|
1113
|
+
{
|
|
1114
|
+
dispatch(result) {
|
|
1115
|
+
set.status = result.statusCode;
|
|
1116
|
+
set.headers = {
|
|
1117
|
+
...set.headers ?? {},
|
|
1118
|
+
...normalizeHeaders(result.headers),
|
|
1119
|
+
"Content-Type": "application/json; charset=utf-8"
|
|
1120
|
+
};
|
|
1121
|
+
if (!shouldSendResponseBody(result.statusCode)) {
|
|
1122
|
+
return null;
|
|
1123
|
+
}
|
|
1124
|
+
return result.body;
|
|
1125
|
+
}
|
|
1126
|
+
},
|
|
1127
|
+
options,
|
|
1128
|
+
context
|
|
1129
|
+
);
|
|
1130
|
+
return {
|
|
1131
|
+
builder: runtime.builder,
|
|
1132
|
+
requestId: runtime.context.requestId,
|
|
1133
|
+
startTime: runtime.context.startTime
|
|
1134
|
+
};
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
var ElysiaAdapter = class {
|
|
1138
|
+
options;
|
|
1139
|
+
constructor(options = {}) {
|
|
1140
|
+
this.options = options;
|
|
1141
|
+
}
|
|
1142
|
+
/** Elysia plugin — adds `builder`, `requestId`, `startTime` to the handler context */
|
|
1143
|
+
plugin() {
|
|
1144
|
+
const derive = createElysiaDerive(this.options);
|
|
1145
|
+
return new Elysia({ name: "x" }).derive(
|
|
1146
|
+
{ as: "scoped" },
|
|
1147
|
+
(context) => derive({
|
|
1148
|
+
request: context.request,
|
|
1149
|
+
set: context.set
|
|
1150
|
+
})
|
|
1151
|
+
);
|
|
1152
|
+
}
|
|
1153
|
+
middleware() {
|
|
1154
|
+
return this.plugin();
|
|
1155
|
+
}
|
|
1156
|
+
handler() {
|
|
1157
|
+
return this.plugin();
|
|
1158
|
+
}
|
|
1159
|
+
};
|
|
1160
|
+
function elysiaMiddleware(options = {}) {
|
|
1161
|
+
return new ElysiaAdapter(options).plugin();
|
|
1162
|
+
}
|
|
1163
|
+
function headersToRecord(headers) {
|
|
1164
|
+
const record = {};
|
|
1165
|
+
headers.forEach((value, key) => {
|
|
1166
|
+
record[key] = value;
|
|
1167
|
+
});
|
|
1168
|
+
return record;
|
|
1169
|
+
}
|
|
1170
|
+
function normalizeHeaders(headers) {
|
|
1171
|
+
const normalized = {};
|
|
1172
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1173
|
+
if (Array.isArray(value)) {
|
|
1174
|
+
normalized[key] = value.join(", ");
|
|
1175
|
+
} else {
|
|
1176
|
+
normalized[key] = String(value);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
return normalized;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
// src/adapters/express.ts
|
|
1183
|
+
var ExpressDispatcher = class {
|
|
1184
|
+
res;
|
|
1185
|
+
constructor(res) {
|
|
1186
|
+
this.res = res;
|
|
1187
|
+
}
|
|
1188
|
+
dispatch(result) {
|
|
1189
|
+
if (this.res.headersSent) {
|
|
1190
|
+
return result;
|
|
1191
|
+
}
|
|
1192
|
+
for (const [key, value] of Object.entries(result.headers)) {
|
|
1193
|
+
this.res.setHeader(key, value);
|
|
1194
|
+
}
|
|
1195
|
+
if (result.cookies.length && this.res.cookie) {
|
|
1196
|
+
for (const cookie of result.cookies) {
|
|
1197
|
+
this.res.cookie(cookie.name, cookie.value, cookie.options ?? {});
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
this.res.status(result.statusCode);
|
|
1201
|
+
if (shouldSendResponseBody(result.statusCode)) {
|
|
1202
|
+
this.res.json(result.body);
|
|
1203
|
+
} else {
|
|
1204
|
+
this.res.end();
|
|
1205
|
+
}
|
|
1206
|
+
return result;
|
|
1207
|
+
}
|
|
1208
|
+
};
|
|
1209
|
+
var ExpressAdapter = class {
|
|
1210
|
+
options;
|
|
1211
|
+
constructor(options = {}) {
|
|
1212
|
+
this.options = options;
|
|
1213
|
+
}
|
|
1214
|
+
handler() {
|
|
1215
|
+
return this.middleware.bind(this);
|
|
1216
|
+
}
|
|
1217
|
+
middleware(req, res, next) {
|
|
1218
|
+
const context = ContextFactory.create(req, {
|
|
1219
|
+
requestIdHeaders: this.options.requestIdHeaders
|
|
1220
|
+
});
|
|
1221
|
+
if (this.options.withDefaultHeaders !== false) {
|
|
1222
|
+
const headers = this.options.defaultHeaders ?? DEFAULT_SECURITY_HEADERS;
|
|
1223
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1224
|
+
res.setHeader(key, value);
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
const runtime = createBuilderRuntime(new ExpressDispatcher(res), this.options, context);
|
|
1228
|
+
req.ctx = runtime.context;
|
|
1229
|
+
res.builder = runtime.builder;
|
|
1230
|
+
next();
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
function expressMiddleware(options = {}) {
|
|
1234
|
+
return new ExpressAdapter(options).handler();
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
// src/adapters/node.ts
|
|
1238
|
+
var NodeDispatcher = class {
|
|
1239
|
+
res;
|
|
1240
|
+
constructor(res) {
|
|
1241
|
+
this.res = res;
|
|
1242
|
+
}
|
|
1243
|
+
dispatch(result) {
|
|
1244
|
+
if (this.res.headersSent) {
|
|
1245
|
+
return result;
|
|
1246
|
+
}
|
|
1247
|
+
for (const [key, value] of Object.entries(result.headers)) {
|
|
1248
|
+
this.res.setHeader(key, value);
|
|
1249
|
+
}
|
|
1250
|
+
this.res.statusCode = result.statusCode;
|
|
1251
|
+
if (!shouldSendResponseBody(result.statusCode)) {
|
|
1252
|
+
this.res.end();
|
|
1253
|
+
return result;
|
|
1254
|
+
}
|
|
1255
|
+
const body = JSON.stringify(result.body);
|
|
1256
|
+
if (!this.res.getHeader("Content-Type")) {
|
|
1257
|
+
this.res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
1258
|
+
}
|
|
1259
|
+
this.res.end(body);
|
|
1260
|
+
return result;
|
|
1261
|
+
}
|
|
1262
|
+
};
|
|
1263
|
+
var NodeAdapter = class {
|
|
1264
|
+
options;
|
|
1265
|
+
constructor(options = {}) {
|
|
1266
|
+
this.options = options;
|
|
1267
|
+
}
|
|
1268
|
+
handler() {
|
|
1269
|
+
return this.middleware.bind(this);
|
|
1270
|
+
}
|
|
1271
|
+
middleware(req, res, next) {
|
|
1272
|
+
const context = ContextFactory.create(req, {
|
|
1273
|
+
requestIdHeaders: this.options.requestIdHeaders
|
|
1274
|
+
});
|
|
1275
|
+
if (this.options.withDefaultHeaders !== false) {
|
|
1276
|
+
const headers = this.options.defaultHeaders ?? DEFAULT_SECURITY_HEADERS;
|
|
1277
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1278
|
+
if (!res.getHeader(key)) {
|
|
1279
|
+
res.setHeader(key, value);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
const runtime = createBuilderRuntime(new NodeDispatcher(res), this.options, context);
|
|
1284
|
+
req.ctx = runtime.context;
|
|
1285
|
+
res.builder = runtime.builder;
|
|
1286
|
+
next();
|
|
1287
|
+
}
|
|
1288
|
+
};
|
|
1289
|
+
function nodeMiddleware(options = {}) {
|
|
1290
|
+
return new NodeAdapter(options).handler();
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
// src/adapters/socketio.ts
|
|
1294
|
+
var SocketIoDispatcher = class {
|
|
1295
|
+
socket;
|
|
1296
|
+
event;
|
|
1297
|
+
constructor(socket, event = "response") {
|
|
1298
|
+
this.socket = socket;
|
|
1299
|
+
this.event = event;
|
|
1300
|
+
}
|
|
1301
|
+
dispatch(result) {
|
|
1302
|
+
this.socket.emit(this.event, result.body);
|
|
1303
|
+
return result;
|
|
1304
|
+
}
|
|
1305
|
+
};
|
|
1306
|
+
var SocketIoAdapter = class {
|
|
1307
|
+
options;
|
|
1308
|
+
constructor(options = {}) {
|
|
1309
|
+
this.options = {
|
|
1310
|
+
event: "response",
|
|
1311
|
+
...options
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
attach(socket) {
|
|
1315
|
+
const context = ContextFactory.create({
|
|
1316
|
+
headers: socket.handshake?.headers
|
|
1317
|
+
}, {
|
|
1318
|
+
requestIdHeaders: this.options.requestIdHeaders
|
|
1319
|
+
});
|
|
1320
|
+
const runtime = createBuilderRuntime(
|
|
1321
|
+
new SocketIoDispatcher(socket, this.options.event),
|
|
1322
|
+
this.options,
|
|
1323
|
+
context
|
|
1324
|
+
);
|
|
1325
|
+
socket.ctx = runtime.context;
|
|
1326
|
+
socket.builder = runtime.builder;
|
|
1327
|
+
return runtime;
|
|
1328
|
+
}
|
|
1329
|
+
handler() {
|
|
1330
|
+
return (socket, next) => {
|
|
1331
|
+
try {
|
|
1332
|
+
this.attach(socket);
|
|
1333
|
+
next?.();
|
|
1334
|
+
} catch (error) {
|
|
1335
|
+
next?.(error instanceof Error ? error : new Error(String(error)));
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
};
|
|
1340
|
+
function socketIoMiddleware(options = {}) {
|
|
1341
|
+
return new SocketIoAdapter(options).handler();
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
// src/adapters/websocket.ts
|
|
1345
|
+
var WS_OPEN = 1;
|
|
1346
|
+
var WebSocketDispatcher = class {
|
|
1347
|
+
socket;
|
|
1348
|
+
constructor(socket) {
|
|
1349
|
+
this.socket = socket;
|
|
1350
|
+
}
|
|
1351
|
+
dispatch(result) {
|
|
1352
|
+
if (this.socket.readyState !== void 0 && this.socket.readyState !== WS_OPEN) {
|
|
1353
|
+
return result;
|
|
1354
|
+
}
|
|
1355
|
+
this.socket.send(JSON.stringify(result.body));
|
|
1356
|
+
return result;
|
|
1357
|
+
}
|
|
1358
|
+
};
|
|
1359
|
+
var WebSocketAdapter = class {
|
|
1360
|
+
options;
|
|
1361
|
+
constructor(options = {}) {
|
|
1362
|
+
this.options = options;
|
|
1363
|
+
}
|
|
1364
|
+
attach(socket, requestId) {
|
|
1365
|
+
const context = requestId ? ContextFactory.fromId(requestId) : ContextFactory.fromId(generateUUID());
|
|
1366
|
+
const runtime = createBuilderRuntime(
|
|
1367
|
+
new WebSocketDispatcher(socket),
|
|
1368
|
+
this.options,
|
|
1369
|
+
context
|
|
1370
|
+
);
|
|
1371
|
+
socket.ctx = runtime.context;
|
|
1372
|
+
socket.builder = runtime.builder;
|
|
1373
|
+
return runtime;
|
|
1374
|
+
}
|
|
1375
|
+
handler() {
|
|
1376
|
+
return (socket, next) => {
|
|
1377
|
+
this.attach(socket);
|
|
1378
|
+
next?.();
|
|
1379
|
+
};
|
|
1380
|
+
}
|
|
1381
|
+
};
|
|
1382
|
+
function websocketMiddleware(options = {}) {
|
|
1383
|
+
return new WebSocketAdapter(options).handler();
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
// src/dto/runtime/dto.ts
|
|
1387
|
+
var DTO = class _DTO {
|
|
1388
|
+
static Log = LogDTO;
|
|
1389
|
+
static Queue = QueueDTO;
|
|
1390
|
+
static Response = ResponseDTO;
|
|
1391
|
+
options;
|
|
1392
|
+
constructor(options = {}) {
|
|
1393
|
+
this.options = options;
|
|
1394
|
+
}
|
|
1395
|
+
use(...plugins) {
|
|
1396
|
+
return new _DTO({
|
|
1397
|
+
...this.options,
|
|
1398
|
+
plugins: mergePlugins(this.options.plugins, plugins)
|
|
1399
|
+
});
|
|
1400
|
+
}
|
|
1401
|
+
express() {
|
|
1402
|
+
return new ExpressAdapter(this.options).handler();
|
|
1403
|
+
}
|
|
1404
|
+
node() {
|
|
1405
|
+
return new NodeAdapter(this.options).handler();
|
|
1406
|
+
}
|
|
1407
|
+
elysia() {
|
|
1408
|
+
return new ElysiaAdapter(this.options).middleware();
|
|
1409
|
+
}
|
|
1410
|
+
websocket() {
|
|
1411
|
+
return new WebSocketAdapter(this.socketOptions()).handler();
|
|
1412
|
+
}
|
|
1413
|
+
attachWebSocket(socket, requestId) {
|
|
1414
|
+
return new WebSocketAdapter(this.socketOptions()).attach(socket, requestId);
|
|
1415
|
+
}
|
|
1416
|
+
socketIo() {
|
|
1417
|
+
return new SocketIoAdapter(this.socketOptions()).handler();
|
|
1418
|
+
}
|
|
1419
|
+
attachSocketIo(socket) {
|
|
1420
|
+
return new SocketIoAdapter(this.socketOptions()).attach(socket);
|
|
1421
|
+
}
|
|
1422
|
+
socketOptions() {
|
|
1423
|
+
return {
|
|
1424
|
+
...this.options,
|
|
1425
|
+
event: this.options.socket?.event ?? this.options.event ?? "response"
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
function createDTO(options = {}) {
|
|
1430
|
+
return new DTO(options);
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
export { BaseDTO, Builder, ClientError, ContextFactory, DEFAULT_SECURITY_HEADERS, DTO, DefaultCodes, ElysiaAdapter, ExpressAdapter, Hooks, LogDTO, MetadataFactory, NO_BODY_STATUS_CODES, NodeAdapter, NodeEnvEnum, PluginRegistry, QueueDTO, ResponseDTO, ResponseError, ResponsePresets, ServerError, SocketIoAdapter, StatusCodes, ValidationError, WebSocketAdapter, assembleLogBody, assembleQueueMessage, assembleResponseBody, assertRequiredFields, createBuilderProxy, createCodeRegistry, createDTO, defaultMessageForCode, definePlugin, elysiaMiddleware, expressMiddleware, inferHttpStatusFromCode, isResponseError, isSuccessCode, lookupCode, mergePlugins, nodeMiddleware, resolveBuilderConfig, resolveCodeFromHttpStatus, resolveStatusFromCode, shouldSendResponseBody, socketIoMiddleware, websocketMiddleware };
|