@xrystal/dto 26.6.27-v15 → 26.11.14
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/LICENSE +21 -0
- package/README.md +181 -65
- package/dist/adapters/elysia.cjs +125 -125
- package/dist/adapters/elysia.js +125 -125
- package/dist/adapters/express.cjs +149 -128
- package/dist/adapters/express.js +149 -128
- package/dist/adapters/fetch.cjs +122 -126
- package/dist/adapters/fetch.js +122 -126
- package/dist/adapters/node.cjs +122 -126
- package/dist/adapters/node.js +122 -126
- package/dist/adapters/socketio.cjs +121 -123
- package/dist/adapters/socketio.js +121 -123
- package/dist/adapters/websocket.cjs +121 -123
- package/dist/adapters/websocket.js +121 -123
- package/dist/dto/adapters/bind.d.ts +2 -2
- package/dist/dto/adapters/elysia-adapter.d.ts +79 -0
- package/dist/dto/adapters/elysia.d.ts +1 -1
- package/dist/dto/adapters/http.d.ts +1 -76
- package/dist/dto/index.cjs +46 -27
- package/dist/dto/index.js +46 -27
- package/dist/dto/response/index.cjs +12 -2
- package/dist/dto/response/index.js +12 -2
- package/dist/dto/runtime/builder-runtime.d.ts +11 -0
- package/dist/dto/runtime/index.cjs +57 -38
- package/dist/dto/runtime/index.d.ts +7 -15
- package/dist/dto/runtime/index.js +57 -38
- package/dist/index.cjs +46 -27
- package/dist/index.js +46 -27
- package/package.json +5 -2
package/dist/adapters/elysia.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var elysia = require('elysia');
|
|
4
4
|
|
|
5
|
-
// src/dto/adapters/
|
|
5
|
+
// src/dto/adapters/elysia-adapter.ts
|
|
6
6
|
|
|
7
7
|
// src/utils/constants/security-headers.ts
|
|
8
8
|
var DEFAULT_SECURITY_HEADERS = {
|
|
@@ -16,6 +16,89 @@ var DEFAULT_SECURITY_HEADERS = {
|
|
|
16
16
|
"X-DNS-Prefetch-Control": "off"
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
// src/utils/helpers/uuid.ts
|
|
20
|
+
function generateUUID() {
|
|
21
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
22
|
+
return crypto.randomUUID();
|
|
23
|
+
}
|
|
24
|
+
const bytes = new Uint8Array(16);
|
|
25
|
+
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
|
|
26
|
+
crypto.getRandomValues(bytes);
|
|
27
|
+
} else {
|
|
28
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
29
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
33
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
34
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
35
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
36
|
+
}
|
|
37
|
+
function isValidUUID(id) {
|
|
38
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/utils/helpers/request-id.ts
|
|
42
|
+
var DEFAULT_REQUEST_ID_HEADERS = [
|
|
43
|
+
"x-request-id",
|
|
44
|
+
"x-correlation-id",
|
|
45
|
+
"traceparent"
|
|
46
|
+
];
|
|
47
|
+
function readHeader(req, name) {
|
|
48
|
+
const fromGet = req.get?.(name);
|
|
49
|
+
if (fromGet) return fromGet;
|
|
50
|
+
const headers = req.headers;
|
|
51
|
+
if (!headers) return void 0;
|
|
52
|
+
const direct = headers[name] ?? headers[name.toLowerCase()];
|
|
53
|
+
if (direct === void 0) return void 0;
|
|
54
|
+
return Array.isArray(direct) ? direct[0] : direct;
|
|
55
|
+
}
|
|
56
|
+
function traceIdFromTraceparent(traceparent) {
|
|
57
|
+
const parts = traceparent.trim().split("-");
|
|
58
|
+
if (parts.length < 2) return void 0;
|
|
59
|
+
const traceId = parts[1];
|
|
60
|
+
if (!traceId || !/^[0-9a-f]{32}$/i.test(traceId)) return void 0;
|
|
61
|
+
return `${traceId.slice(0, 8)}-${traceId.slice(8, 12)}-${traceId.slice(12, 16)}-${traceId.slice(16, 20)}-${traceId.slice(20)}`;
|
|
62
|
+
}
|
|
63
|
+
function resolveRequestId(req, headerNames = DEFAULT_REQUEST_ID_HEADERS) {
|
|
64
|
+
for (const name of headerNames) {
|
|
65
|
+
const raw = readHeader(req, name);
|
|
66
|
+
if (!raw?.trim()) continue;
|
|
67
|
+
if (name === "traceparent") {
|
|
68
|
+
const traceId = traceIdFromTraceparent(raw);
|
|
69
|
+
if (traceId) return traceId;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const id = raw.trim();
|
|
73
|
+
if (isValidUUID(id)) return id;
|
|
74
|
+
return id;
|
|
75
|
+
}
|
|
76
|
+
return generateUUID();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/dto/factories.ts
|
|
80
|
+
var ContextFactory = class {
|
|
81
|
+
static create(req, options = {}) {
|
|
82
|
+
return {
|
|
83
|
+
requestId: resolveRequestId(req, options.requestIdHeaders),
|
|
84
|
+
startTime: Date.now()
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
static fromId(requestId) {
|
|
88
|
+
return { requestId, startTime: Date.now() };
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
var MetadataFactory = class {
|
|
92
|
+
static create(options = {}, context) {
|
|
93
|
+
return {
|
|
94
|
+
requestId: context?.requestId ?? generateUUID(),
|
|
95
|
+
serverTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
96
|
+
statusCode: 200,
|
|
97
|
+
...options
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
19
102
|
// src/utils/constants/status-codes.ts
|
|
20
103
|
var StatusCodes = {
|
|
21
104
|
SUCCESSFUL: {
|
|
@@ -72,6 +155,44 @@ function resolveStatusFromCode(code, codes) {
|
|
|
72
155
|
return isSuccessCode(code, codes);
|
|
73
156
|
}
|
|
74
157
|
|
|
158
|
+
// src/errors/error.ts
|
|
159
|
+
var ResponseError = class extends Error {
|
|
160
|
+
code;
|
|
161
|
+
httpStatus;
|
|
162
|
+
payload;
|
|
163
|
+
constructor(options = {}) {
|
|
164
|
+
const codes = createCodeRegistry(options.codes);
|
|
165
|
+
const code = options.code ?? codes.SERVER;
|
|
166
|
+
const message = options.message ?? defaultMessageForCode(code, codes);
|
|
167
|
+
super(message, { cause: options.cause });
|
|
168
|
+
this.name = "ResponseError";
|
|
169
|
+
this.code = code;
|
|
170
|
+
this.httpStatus = options.httpStatus ?? codeToDefaultHttpStatus(code, codes);
|
|
171
|
+
if (options.payload !== void 0) {
|
|
172
|
+
this.payload = options.payload;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
toJSON() {
|
|
176
|
+
return {
|
|
177
|
+
name: this.name,
|
|
178
|
+
message: this.message,
|
|
179
|
+
code: this.code,
|
|
180
|
+
httpStatus: this.httpStatus,
|
|
181
|
+
payload: this.payload
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
function isResponseError(value) {
|
|
186
|
+
return value instanceof ResponseError;
|
|
187
|
+
}
|
|
188
|
+
function codeToDefaultHttpStatus(code, codes) {
|
|
189
|
+
if (code === codes.SUCCESS) return 200;
|
|
190
|
+
if (code === codes.CLIENT) return 400;
|
|
191
|
+
if (code === codes.SERVER) return 500;
|
|
192
|
+
if (code === codes.VALIDATION) return 422;
|
|
193
|
+
return 500;
|
|
194
|
+
}
|
|
195
|
+
|
|
75
196
|
// src/dto/shared.ts
|
|
76
197
|
var BaseDTO = class {
|
|
77
198
|
};
|
|
@@ -86,28 +207,6 @@ function resolveBuilderConfig(options = {}) {
|
|
|
86
207
|
};
|
|
87
208
|
}
|
|
88
209
|
|
|
89
|
-
// src/utils/helpers/uuid.ts
|
|
90
|
-
function generateUUID() {
|
|
91
|
-
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
92
|
-
return crypto.randomUUID();
|
|
93
|
-
}
|
|
94
|
-
const bytes = new Uint8Array(16);
|
|
95
|
-
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
|
|
96
|
-
crypto.getRandomValues(bytes);
|
|
97
|
-
} else {
|
|
98
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
99
|
-
bytes[i] = Math.floor(Math.random() * 256);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
bytes[6] = bytes[6] & 15 | 64;
|
|
103
|
-
bytes[8] = bytes[8] & 63 | 128;
|
|
104
|
-
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
105
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
106
|
-
}
|
|
107
|
-
function isValidUUID(id) {
|
|
108
|
-
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
210
|
// src/dto/shapes/response.ts
|
|
112
211
|
function assembleResponseBody(input) {
|
|
113
212
|
const ordered = {
|
|
@@ -227,105 +326,6 @@ var ResponseDTO = class _ResponseDTO extends BaseDTO {
|
|
|
227
326
|
}
|
|
228
327
|
};
|
|
229
328
|
|
|
230
|
-
// src/utils/helpers/request-id.ts
|
|
231
|
-
var DEFAULT_REQUEST_ID_HEADERS = [
|
|
232
|
-
"x-request-id",
|
|
233
|
-
"x-correlation-id",
|
|
234
|
-
"traceparent"
|
|
235
|
-
];
|
|
236
|
-
function readHeader(req, name) {
|
|
237
|
-
const fromGet = req.get?.(name);
|
|
238
|
-
if (fromGet) return fromGet;
|
|
239
|
-
const headers = req.headers;
|
|
240
|
-
if (!headers) return void 0;
|
|
241
|
-
const direct = headers[name] ?? headers[name.toLowerCase()];
|
|
242
|
-
if (direct === void 0) return void 0;
|
|
243
|
-
return Array.isArray(direct) ? direct[0] : direct;
|
|
244
|
-
}
|
|
245
|
-
function traceIdFromTraceparent(traceparent) {
|
|
246
|
-
const parts = traceparent.trim().split("-");
|
|
247
|
-
if (parts.length < 2) return void 0;
|
|
248
|
-
const traceId = parts[1];
|
|
249
|
-
if (!traceId || !/^[0-9a-f]{32}$/i.test(traceId)) return void 0;
|
|
250
|
-
return `${traceId.slice(0, 8)}-${traceId.slice(8, 12)}-${traceId.slice(12, 16)}-${traceId.slice(16, 20)}-${traceId.slice(20)}`;
|
|
251
|
-
}
|
|
252
|
-
function resolveRequestId(req, headerNames = DEFAULT_REQUEST_ID_HEADERS) {
|
|
253
|
-
for (const name of headerNames) {
|
|
254
|
-
const raw = readHeader(req, name);
|
|
255
|
-
if (!raw?.trim()) continue;
|
|
256
|
-
if (name === "traceparent") {
|
|
257
|
-
const traceId = traceIdFromTraceparent(raw);
|
|
258
|
-
if (traceId) return traceId;
|
|
259
|
-
continue;
|
|
260
|
-
}
|
|
261
|
-
const id = raw.trim();
|
|
262
|
-
if (isValidUUID(id)) return id;
|
|
263
|
-
return id;
|
|
264
|
-
}
|
|
265
|
-
return generateUUID();
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// src/dto/factories.ts
|
|
269
|
-
var ContextFactory = class {
|
|
270
|
-
static create(req, options = {}) {
|
|
271
|
-
return {
|
|
272
|
-
requestId: resolveRequestId(req, options.requestIdHeaders),
|
|
273
|
-
startTime: Date.now()
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
static fromId(requestId) {
|
|
277
|
-
return { requestId, startTime: Date.now() };
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
var MetadataFactory = class {
|
|
281
|
-
static create(options = {}, context) {
|
|
282
|
-
return {
|
|
283
|
-
requestId: context?.requestId ?? generateUUID(),
|
|
284
|
-
serverTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
285
|
-
statusCode: 200,
|
|
286
|
-
...options
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
// src/errors/error.ts
|
|
292
|
-
var ResponseError = class extends Error {
|
|
293
|
-
code;
|
|
294
|
-
httpStatus;
|
|
295
|
-
payload;
|
|
296
|
-
constructor(options = {}) {
|
|
297
|
-
const codes = createCodeRegistry(options.codes);
|
|
298
|
-
const code = options.code ?? codes.SERVER;
|
|
299
|
-
const message = options.message ?? defaultMessageForCode(code, codes);
|
|
300
|
-
super(message, { cause: options.cause });
|
|
301
|
-
this.name = "ResponseError";
|
|
302
|
-
this.code = code;
|
|
303
|
-
this.httpStatus = options.httpStatus ?? codeToDefaultHttpStatus(code, codes);
|
|
304
|
-
if (options.payload !== void 0) {
|
|
305
|
-
this.payload = options.payload;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
toJSON() {
|
|
309
|
-
return {
|
|
310
|
-
name: this.name,
|
|
311
|
-
message: this.message,
|
|
312
|
-
code: this.code,
|
|
313
|
-
httpStatus: this.httpStatus,
|
|
314
|
-
payload: this.payload
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
function isResponseError(value) {
|
|
319
|
-
return value instanceof ResponseError;
|
|
320
|
-
}
|
|
321
|
-
function codeToDefaultHttpStatus(code, codes) {
|
|
322
|
-
if (code === codes.SUCCESS) return 200;
|
|
323
|
-
if (code === codes.CLIENT) return 400;
|
|
324
|
-
if (code === codes.SERVER) return 500;
|
|
325
|
-
if (code === codes.VALIDATION) return 422;
|
|
326
|
-
return 500;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
329
|
// src/dto/send/plugins.ts
|
|
330
330
|
function sortPlugins(plugins) {
|
|
331
331
|
return [...plugins].sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
|
|
@@ -754,7 +754,7 @@ function createBuilderProxy(sink, options = {}, context) {
|
|
|
754
754
|
});
|
|
755
755
|
}
|
|
756
756
|
|
|
757
|
-
// src/dto/runtime/
|
|
757
|
+
// src/dto/runtime/builder-runtime.ts
|
|
758
758
|
function createBuilderRuntime(sink, options, context) {
|
|
759
759
|
const builderOptions = {
|
|
760
760
|
verbose: options.verbose,
|
|
@@ -771,7 +771,7 @@ function createBuilderRuntime(sink, options, context) {
|
|
|
771
771
|
};
|
|
772
772
|
}
|
|
773
773
|
|
|
774
|
-
// src/dto/adapters/
|
|
774
|
+
// src/dto/adapters/elysia-adapter.ts
|
|
775
775
|
function elysiaSink(set) {
|
|
776
776
|
return { dispatch: (result) => applyElysiaTransport(result, set) };
|
|
777
777
|
}
|
|
@@ -800,7 +800,7 @@ var ElysiaAdapter = class {
|
|
|
800
800
|
options;
|
|
801
801
|
plugin() {
|
|
802
802
|
const derive = createElysiaDerive(this.options);
|
|
803
|
-
return new elysia.Elysia({ name: "
|
|
803
|
+
return new elysia.Elysia({ name: "xrystal-dto" }).derive(
|
|
804
804
|
{ as: "scoped" },
|
|
805
805
|
(context) => derive({
|
|
806
806
|
request: context.request,
|
package/dist/adapters/elysia.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Elysia } from 'elysia';
|
|
2
2
|
|
|
3
|
-
// src/dto/adapters/
|
|
3
|
+
// src/dto/adapters/elysia-adapter.ts
|
|
4
4
|
|
|
5
5
|
// src/utils/constants/security-headers.ts
|
|
6
6
|
var DEFAULT_SECURITY_HEADERS = {
|
|
@@ -14,6 +14,89 @@ var DEFAULT_SECURITY_HEADERS = {
|
|
|
14
14
|
"X-DNS-Prefetch-Control": "off"
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
// src/utils/helpers/uuid.ts
|
|
18
|
+
function generateUUID() {
|
|
19
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
20
|
+
return crypto.randomUUID();
|
|
21
|
+
}
|
|
22
|
+
const bytes = new Uint8Array(16);
|
|
23
|
+
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
|
|
24
|
+
crypto.getRandomValues(bytes);
|
|
25
|
+
} else {
|
|
26
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
27
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
31
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
32
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
33
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
34
|
+
}
|
|
35
|
+
function isValidUUID(id) {
|
|
36
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/utils/helpers/request-id.ts
|
|
40
|
+
var DEFAULT_REQUEST_ID_HEADERS = [
|
|
41
|
+
"x-request-id",
|
|
42
|
+
"x-correlation-id",
|
|
43
|
+
"traceparent"
|
|
44
|
+
];
|
|
45
|
+
function readHeader(req, name) {
|
|
46
|
+
const fromGet = req.get?.(name);
|
|
47
|
+
if (fromGet) return fromGet;
|
|
48
|
+
const headers = req.headers;
|
|
49
|
+
if (!headers) return void 0;
|
|
50
|
+
const direct = headers[name] ?? headers[name.toLowerCase()];
|
|
51
|
+
if (direct === void 0) return void 0;
|
|
52
|
+
return Array.isArray(direct) ? direct[0] : direct;
|
|
53
|
+
}
|
|
54
|
+
function traceIdFromTraceparent(traceparent) {
|
|
55
|
+
const parts = traceparent.trim().split("-");
|
|
56
|
+
if (parts.length < 2) return void 0;
|
|
57
|
+
const traceId = parts[1];
|
|
58
|
+
if (!traceId || !/^[0-9a-f]{32}$/i.test(traceId)) return void 0;
|
|
59
|
+
return `${traceId.slice(0, 8)}-${traceId.slice(8, 12)}-${traceId.slice(12, 16)}-${traceId.slice(16, 20)}-${traceId.slice(20)}`;
|
|
60
|
+
}
|
|
61
|
+
function resolveRequestId(req, headerNames = DEFAULT_REQUEST_ID_HEADERS) {
|
|
62
|
+
for (const name of headerNames) {
|
|
63
|
+
const raw = readHeader(req, name);
|
|
64
|
+
if (!raw?.trim()) continue;
|
|
65
|
+
if (name === "traceparent") {
|
|
66
|
+
const traceId = traceIdFromTraceparent(raw);
|
|
67
|
+
if (traceId) return traceId;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const id = raw.trim();
|
|
71
|
+
if (isValidUUID(id)) return id;
|
|
72
|
+
return id;
|
|
73
|
+
}
|
|
74
|
+
return generateUUID();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/dto/factories.ts
|
|
78
|
+
var ContextFactory = class {
|
|
79
|
+
static create(req, options = {}) {
|
|
80
|
+
return {
|
|
81
|
+
requestId: resolveRequestId(req, options.requestIdHeaders),
|
|
82
|
+
startTime: Date.now()
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
static fromId(requestId) {
|
|
86
|
+
return { requestId, startTime: Date.now() };
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
var MetadataFactory = class {
|
|
90
|
+
static create(options = {}, context) {
|
|
91
|
+
return {
|
|
92
|
+
requestId: context?.requestId ?? generateUUID(),
|
|
93
|
+
serverTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
94
|
+
statusCode: 200,
|
|
95
|
+
...options
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
17
100
|
// src/utils/constants/status-codes.ts
|
|
18
101
|
var StatusCodes = {
|
|
19
102
|
SUCCESSFUL: {
|
|
@@ -70,6 +153,44 @@ function resolveStatusFromCode(code, codes) {
|
|
|
70
153
|
return isSuccessCode(code, codes);
|
|
71
154
|
}
|
|
72
155
|
|
|
156
|
+
// src/errors/error.ts
|
|
157
|
+
var ResponseError = class extends Error {
|
|
158
|
+
code;
|
|
159
|
+
httpStatus;
|
|
160
|
+
payload;
|
|
161
|
+
constructor(options = {}) {
|
|
162
|
+
const codes = createCodeRegistry(options.codes);
|
|
163
|
+
const code = options.code ?? codes.SERVER;
|
|
164
|
+
const message = options.message ?? defaultMessageForCode(code, codes);
|
|
165
|
+
super(message, { cause: options.cause });
|
|
166
|
+
this.name = "ResponseError";
|
|
167
|
+
this.code = code;
|
|
168
|
+
this.httpStatus = options.httpStatus ?? codeToDefaultHttpStatus(code, codes);
|
|
169
|
+
if (options.payload !== void 0) {
|
|
170
|
+
this.payload = options.payload;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
toJSON() {
|
|
174
|
+
return {
|
|
175
|
+
name: this.name,
|
|
176
|
+
message: this.message,
|
|
177
|
+
code: this.code,
|
|
178
|
+
httpStatus: this.httpStatus,
|
|
179
|
+
payload: this.payload
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
function isResponseError(value) {
|
|
184
|
+
return value instanceof ResponseError;
|
|
185
|
+
}
|
|
186
|
+
function codeToDefaultHttpStatus(code, codes) {
|
|
187
|
+
if (code === codes.SUCCESS) return 200;
|
|
188
|
+
if (code === codes.CLIENT) return 400;
|
|
189
|
+
if (code === codes.SERVER) return 500;
|
|
190
|
+
if (code === codes.VALIDATION) return 422;
|
|
191
|
+
return 500;
|
|
192
|
+
}
|
|
193
|
+
|
|
73
194
|
// src/dto/shared.ts
|
|
74
195
|
var BaseDTO = class {
|
|
75
196
|
};
|
|
@@ -84,28 +205,6 @@ function resolveBuilderConfig(options = {}) {
|
|
|
84
205
|
};
|
|
85
206
|
}
|
|
86
207
|
|
|
87
|
-
// src/utils/helpers/uuid.ts
|
|
88
|
-
function generateUUID() {
|
|
89
|
-
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
90
|
-
return crypto.randomUUID();
|
|
91
|
-
}
|
|
92
|
-
const bytes = new Uint8Array(16);
|
|
93
|
-
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
|
|
94
|
-
crypto.getRandomValues(bytes);
|
|
95
|
-
} else {
|
|
96
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
97
|
-
bytes[i] = Math.floor(Math.random() * 256);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
bytes[6] = bytes[6] & 15 | 64;
|
|
101
|
-
bytes[8] = bytes[8] & 63 | 128;
|
|
102
|
-
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
103
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
104
|
-
}
|
|
105
|
-
function isValidUUID(id) {
|
|
106
|
-
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
208
|
// src/dto/shapes/response.ts
|
|
110
209
|
function assembleResponseBody(input) {
|
|
111
210
|
const ordered = {
|
|
@@ -225,105 +324,6 @@ var ResponseDTO = class _ResponseDTO extends BaseDTO {
|
|
|
225
324
|
}
|
|
226
325
|
};
|
|
227
326
|
|
|
228
|
-
// src/utils/helpers/request-id.ts
|
|
229
|
-
var DEFAULT_REQUEST_ID_HEADERS = [
|
|
230
|
-
"x-request-id",
|
|
231
|
-
"x-correlation-id",
|
|
232
|
-
"traceparent"
|
|
233
|
-
];
|
|
234
|
-
function readHeader(req, name) {
|
|
235
|
-
const fromGet = req.get?.(name);
|
|
236
|
-
if (fromGet) return fromGet;
|
|
237
|
-
const headers = req.headers;
|
|
238
|
-
if (!headers) return void 0;
|
|
239
|
-
const direct = headers[name] ?? headers[name.toLowerCase()];
|
|
240
|
-
if (direct === void 0) return void 0;
|
|
241
|
-
return Array.isArray(direct) ? direct[0] : direct;
|
|
242
|
-
}
|
|
243
|
-
function traceIdFromTraceparent(traceparent) {
|
|
244
|
-
const parts = traceparent.trim().split("-");
|
|
245
|
-
if (parts.length < 2) return void 0;
|
|
246
|
-
const traceId = parts[1];
|
|
247
|
-
if (!traceId || !/^[0-9a-f]{32}$/i.test(traceId)) return void 0;
|
|
248
|
-
return `${traceId.slice(0, 8)}-${traceId.slice(8, 12)}-${traceId.slice(12, 16)}-${traceId.slice(16, 20)}-${traceId.slice(20)}`;
|
|
249
|
-
}
|
|
250
|
-
function resolveRequestId(req, headerNames = DEFAULT_REQUEST_ID_HEADERS) {
|
|
251
|
-
for (const name of headerNames) {
|
|
252
|
-
const raw = readHeader(req, name);
|
|
253
|
-
if (!raw?.trim()) continue;
|
|
254
|
-
if (name === "traceparent") {
|
|
255
|
-
const traceId = traceIdFromTraceparent(raw);
|
|
256
|
-
if (traceId) return traceId;
|
|
257
|
-
continue;
|
|
258
|
-
}
|
|
259
|
-
const id = raw.trim();
|
|
260
|
-
if (isValidUUID(id)) return id;
|
|
261
|
-
return id;
|
|
262
|
-
}
|
|
263
|
-
return generateUUID();
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// src/dto/factories.ts
|
|
267
|
-
var ContextFactory = class {
|
|
268
|
-
static create(req, options = {}) {
|
|
269
|
-
return {
|
|
270
|
-
requestId: resolveRequestId(req, options.requestIdHeaders),
|
|
271
|
-
startTime: Date.now()
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
static fromId(requestId) {
|
|
275
|
-
return { requestId, startTime: Date.now() };
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
var MetadataFactory = class {
|
|
279
|
-
static create(options = {}, context) {
|
|
280
|
-
return {
|
|
281
|
-
requestId: context?.requestId ?? generateUUID(),
|
|
282
|
-
serverTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
283
|
-
statusCode: 200,
|
|
284
|
-
...options
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
// src/errors/error.ts
|
|
290
|
-
var ResponseError = class extends Error {
|
|
291
|
-
code;
|
|
292
|
-
httpStatus;
|
|
293
|
-
payload;
|
|
294
|
-
constructor(options = {}) {
|
|
295
|
-
const codes = createCodeRegistry(options.codes);
|
|
296
|
-
const code = options.code ?? codes.SERVER;
|
|
297
|
-
const message = options.message ?? defaultMessageForCode(code, codes);
|
|
298
|
-
super(message, { cause: options.cause });
|
|
299
|
-
this.name = "ResponseError";
|
|
300
|
-
this.code = code;
|
|
301
|
-
this.httpStatus = options.httpStatus ?? codeToDefaultHttpStatus(code, codes);
|
|
302
|
-
if (options.payload !== void 0) {
|
|
303
|
-
this.payload = options.payload;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
toJSON() {
|
|
307
|
-
return {
|
|
308
|
-
name: this.name,
|
|
309
|
-
message: this.message,
|
|
310
|
-
code: this.code,
|
|
311
|
-
httpStatus: this.httpStatus,
|
|
312
|
-
payload: this.payload
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
};
|
|
316
|
-
function isResponseError(value) {
|
|
317
|
-
return value instanceof ResponseError;
|
|
318
|
-
}
|
|
319
|
-
function codeToDefaultHttpStatus(code, codes) {
|
|
320
|
-
if (code === codes.SUCCESS) return 200;
|
|
321
|
-
if (code === codes.CLIENT) return 400;
|
|
322
|
-
if (code === codes.SERVER) return 500;
|
|
323
|
-
if (code === codes.VALIDATION) return 422;
|
|
324
|
-
return 500;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
327
|
// src/dto/send/plugins.ts
|
|
328
328
|
function sortPlugins(plugins) {
|
|
329
329
|
return [...plugins].sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
|
|
@@ -752,7 +752,7 @@ function createBuilderProxy(sink, options = {}, context) {
|
|
|
752
752
|
});
|
|
753
753
|
}
|
|
754
754
|
|
|
755
|
-
// src/dto/runtime/
|
|
755
|
+
// src/dto/runtime/builder-runtime.ts
|
|
756
756
|
function createBuilderRuntime(sink, options, context) {
|
|
757
757
|
const builderOptions = {
|
|
758
758
|
verbose: options.verbose,
|
|
@@ -769,7 +769,7 @@ function createBuilderRuntime(sink, options, context) {
|
|
|
769
769
|
};
|
|
770
770
|
}
|
|
771
771
|
|
|
772
|
-
// src/dto/adapters/
|
|
772
|
+
// src/dto/adapters/elysia-adapter.ts
|
|
773
773
|
function elysiaSink(set) {
|
|
774
774
|
return { dispatch: (result) => applyElysiaTransport(result, set) };
|
|
775
775
|
}
|
|
@@ -798,7 +798,7 @@ var ElysiaAdapter = class {
|
|
|
798
798
|
options;
|
|
799
799
|
plugin() {
|
|
800
800
|
const derive = createElysiaDerive(this.options);
|
|
801
|
-
return new Elysia({ name: "
|
|
801
|
+
return new Elysia({ name: "xrystal-dto" }).derive(
|
|
802
802
|
{ as: "scoped" },
|
|
803
803
|
(context) => derive({
|
|
804
804
|
request: context.request,
|