@zintrust/core 0.5.5 → 0.5.8
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/package.json +1 -1
- package/src/index.js +3 -3
- package/src/tools/http/Http.d.ts +14 -4
- package/src/tools/http/Http.d.ts.map +1 -1
- package/src/tools/http/Http.js +110 -21
- package/src/tools/http/index.d.ts +4 -4
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zintrust/core v0.5.
|
|
2
|
+
* @zintrust/core v0.5.8
|
|
3
3
|
*
|
|
4
4
|
* ZinTrust Framework - Production-Grade TypeScript Backend
|
|
5
5
|
* Built for performance, type safety, and exceptional developer experience
|
|
6
6
|
*
|
|
7
7
|
* Build Information:
|
|
8
|
-
* Built: 2026-04-
|
|
8
|
+
* Built: 2026-04-14T16:54:24.540Z
|
|
9
9
|
* Node: >=20.0.0
|
|
10
10
|
* License: MIT
|
|
11
11
|
*
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* Available at runtime for debugging and health checks
|
|
22
22
|
*/
|
|
23
23
|
export const ZINTRUST_VERSION = '0.1.41';
|
|
24
|
-
export const ZINTRUST_BUILD_DATE = '2026-04-
|
|
24
|
+
export const ZINTRUST_BUILD_DATE = '2026-04-14T16:54:24.508Z'; // Replaced during build
|
|
25
25
|
export { Application } from './boot/Application.js';
|
|
26
26
|
export { AwsSigV4 } from './common/index.js';
|
|
27
27
|
export { SignedRequest } from './security/SignedRequest.js';
|
package/src/tools/http/Http.d.ts
CHANGED
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { type IHttpResponse } from './HttpResponse';
|
|
9
9
|
export type { IHttpResponse } from './HttpResponse';
|
|
10
|
+
export type HttpRequestBody = Record<string, unknown> | string | ArrayBuffer | ArrayBufferView | Blob | FormData | URLSearchParams;
|
|
11
|
+
export type HttpRequestCustomMode = Readonly<{
|
|
12
|
+
contentType?: string;
|
|
13
|
+
serializeBody?: (body: HttpRequestBody | null | undefined) => BodyInitLocal | null | undefined;
|
|
14
|
+
}>;
|
|
10
15
|
/**
|
|
11
16
|
* HTTP Request builder interface
|
|
12
17
|
*/
|
|
@@ -18,6 +23,7 @@ export interface IHttpRequest {
|
|
|
18
23
|
withTimeout(ms: number): IHttpRequest;
|
|
19
24
|
asJson(): IHttpRequest;
|
|
20
25
|
asForm(): IHttpRequest;
|
|
26
|
+
asCustom(mode: HttpRequestCustomMode): IHttpRequest;
|
|
21
27
|
send(): Promise<IHttpResponse>;
|
|
22
28
|
sendRaw(): Promise<Response>;
|
|
23
29
|
sendStream(): Promise<{
|
|
@@ -25,6 +31,10 @@ export interface IHttpRequest {
|
|
|
25
31
|
stream: ReadableStream<Uint8Array> | null;
|
|
26
32
|
}>;
|
|
27
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Internal request state
|
|
36
|
+
*/
|
|
37
|
+
type BodyInitLocal = NonNullable<RequestInit['body']>;
|
|
28
38
|
/**
|
|
29
39
|
* HTTP Client - Sealed namespace for making HTTP requests
|
|
30
40
|
*/
|
|
@@ -36,19 +46,19 @@ export declare const HttpClient: Readonly<{
|
|
|
36
46
|
/**
|
|
37
47
|
* Make POST request
|
|
38
48
|
*/
|
|
39
|
-
post(url: string, data?:
|
|
49
|
+
post(url: string, data?: HttpRequestBody | null): IHttpRequest;
|
|
40
50
|
/**
|
|
41
51
|
* Make PUT request
|
|
42
52
|
*/
|
|
43
|
-
put(url: string, data?:
|
|
53
|
+
put(url: string, data?: HttpRequestBody | null): IHttpRequest;
|
|
44
54
|
/**
|
|
45
55
|
* Make PATCH request
|
|
46
56
|
*/
|
|
47
|
-
patch(url: string, data?:
|
|
57
|
+
patch(url: string, data?: HttpRequestBody | null): IHttpRequest;
|
|
48
58
|
/**
|
|
49
59
|
* Make DELETE request
|
|
50
60
|
*/
|
|
51
|
-
delete(url: string, data?:
|
|
61
|
+
delete(url: string, data?: HttpRequestBody | null): IHttpRequest;
|
|
52
62
|
}>;
|
|
53
63
|
export default HttpClient;
|
|
54
64
|
//# sourceMappingURL=Http.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Http.d.ts","sourceRoot":"","sources":["../../../../src/tools/http/Http.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"Http.d.ts","sourceRoot":"","sources":["../../../../src/tools/http/Http.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAElF,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,MAAM,eAAe,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,MAAM,GACN,WAAW,GACX,eAAe,GACf,IAAI,GACJ,QAAQ,GACR,eAAe,CAAC;AAEpB,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,KAAK,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;CAChG,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC;IACtD,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;IACnE,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC;IAChE,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAAC;IACtC,MAAM,IAAI,YAAY,CAAC;IACvB,MAAM,IAAI,YAAY,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,qBAAqB,GAAG,YAAY,CAAC;IACpD,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAC/B,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7B,UAAU,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC1F;AAED;;GAEG;AACH,KAAK,aAAa,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AAuXtD;;GAEG;AACH,eAAO,MAAM,UAAU;IACrB;;OAEG;aACM,MAAM,GAAG,YAAY;IAI9B;;OAEG;cACO,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;IAQ9D;;OAEG;aACM,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;IAQ7D;;OAEG;eACQ,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;IAQ/D;;OAEG;gBACS,MAAM,SAAS,eAAe,GAAG,IAAI,GAAG,YAAY;EAOhE,CAAC;AAEH,eAAe,UAAU,CAAC"}
|
package/src/tools/http/Http.js
CHANGED
|
@@ -10,6 +10,7 @@ import { SystemTraceBridge } from '../../trace/SystemTraceBridge.js';
|
|
|
10
10
|
import { Env } from '../../config/env.js';
|
|
11
11
|
import { Logger } from '../../config/logger.js';
|
|
12
12
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
13
|
+
import { isArray, isDate, isObject } from '../../helper/index.js';
|
|
13
14
|
import { createHttpResponse } from './HttpResponse.js';
|
|
14
15
|
const headersToRecord = (headers) => {
|
|
15
16
|
if (!headers)
|
|
@@ -45,10 +46,88 @@ const bodyToTracePayload = (body) => {
|
|
|
45
46
|
if (typeof FormData !== 'undefined' && body instanceof FormData) {
|
|
46
47
|
return Array.from(body.entries()).map(([key, value]) => [key, String(value)]);
|
|
47
48
|
}
|
|
49
|
+
if (ArrayBuffer.isView(body) || body instanceof ArrayBuffer) {
|
|
50
|
+
return '[binary]';
|
|
51
|
+
}
|
|
52
|
+
if (isObject(body)) {
|
|
53
|
+
return body;
|
|
54
|
+
}
|
|
48
55
|
return '[stream]';
|
|
49
56
|
};
|
|
57
|
+
const appendFormValue = (params, key, value) => {
|
|
58
|
+
if (value === undefined || value === null) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (isArray(value)) {
|
|
62
|
+
for (const item of value) {
|
|
63
|
+
appendFormValue(params, key, item);
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (isDate(value)) {
|
|
68
|
+
params.append(key, value.toISOString());
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (isObject(value)) {
|
|
72
|
+
params.append(key, JSON.stringify(value));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
params.append(key, String(value));
|
|
76
|
+
};
|
|
77
|
+
const normalizeBodyInit = (body) => {
|
|
78
|
+
if (ArrayBuffer.isView(body) && !(body instanceof DataView)) {
|
|
79
|
+
return new Uint8Array(body.buffer, body.byteOffset, body.byteLength);
|
|
80
|
+
}
|
|
81
|
+
return body;
|
|
82
|
+
};
|
|
83
|
+
const serializeFormBody = (body) => {
|
|
84
|
+
if (body === null || body === undefined)
|
|
85
|
+
return body;
|
|
86
|
+
if (typeof body === 'string' || body instanceof URLSearchParams)
|
|
87
|
+
return body;
|
|
88
|
+
if (body instanceof ArrayBuffer ||
|
|
89
|
+
ArrayBuffer.isView(body) ||
|
|
90
|
+
body instanceof Blob ||
|
|
91
|
+
(typeof FormData !== 'undefined' && body instanceof FormData)) {
|
|
92
|
+
return normalizeBodyInit(body);
|
|
93
|
+
}
|
|
94
|
+
if (isObject(body)) {
|
|
95
|
+
const params = new URLSearchParams();
|
|
96
|
+
for (const [key, value] of Object.entries(body)) {
|
|
97
|
+
appendFormValue(params, key, value);
|
|
98
|
+
}
|
|
99
|
+
return params;
|
|
100
|
+
}
|
|
101
|
+
return body;
|
|
102
|
+
};
|
|
103
|
+
const serializeJsonBody = (body) => {
|
|
104
|
+
if (body === null || body === undefined)
|
|
105
|
+
return body;
|
|
106
|
+
if (typeof body === 'string' || body instanceof URLSearchParams)
|
|
107
|
+
return body;
|
|
108
|
+
if (body instanceof ArrayBuffer ||
|
|
109
|
+
ArrayBuffer.isView(body) ||
|
|
110
|
+
body instanceof Blob ||
|
|
111
|
+
(typeof FormData !== 'undefined' && body instanceof FormData)) {
|
|
112
|
+
return normalizeBodyInit(body);
|
|
113
|
+
}
|
|
114
|
+
return JSON.stringify(body);
|
|
115
|
+
};
|
|
116
|
+
const serializeRequestBody = (state) => {
|
|
117
|
+
if (state.contentType === 'custom') {
|
|
118
|
+
const customBody = state.customMode?.serializeBody?.(state.body);
|
|
119
|
+
return customBody ?? serializeJsonBody(state.body);
|
|
120
|
+
}
|
|
121
|
+
if (state.contentType === 'form') {
|
|
122
|
+
return serializeFormBody(state.body);
|
|
123
|
+
}
|
|
124
|
+
if (state.contentType === 'json') {
|
|
125
|
+
return serializeJsonBody(state.body);
|
|
126
|
+
}
|
|
127
|
+
return serializeJsonBody(state.body);
|
|
128
|
+
};
|
|
50
129
|
const emitHttpClientTrace = (input) => {
|
|
51
|
-
const { state, durationMs, response, responseBody, error } = input;
|
|
130
|
+
const { state, requestBody, durationMs, response, responseBody, error } = input;
|
|
52
131
|
SystemTraceBridge.emitHttpClient({
|
|
53
132
|
source: 'http-client',
|
|
54
133
|
method: state.method,
|
|
@@ -56,7 +135,7 @@ const emitHttpClientTrace = (input) => {
|
|
|
56
135
|
requestHeaders: { ...state.headers },
|
|
57
136
|
responseStatus: response?.status,
|
|
58
137
|
duration: durationMs,
|
|
59
|
-
requestBody: bodyToTracePayload(state.body),
|
|
138
|
+
requestBody: bodyToTracePayload(requestBody ?? state.body),
|
|
60
139
|
responseHeaders: headersToRecord(response?.headers),
|
|
61
140
|
responseBody,
|
|
62
141
|
error,
|
|
@@ -83,10 +162,10 @@ async function performRequest(state) {
|
|
|
83
162
|
return createHttpResponse(response, bodyText);
|
|
84
163
|
}
|
|
85
164
|
async function performRequestRaw(state) {
|
|
86
|
-
const { response, durationMs } = await performFetch(state);
|
|
165
|
+
const { response, durationMs, requestBody } = await performFetch(state);
|
|
87
166
|
const bodyText = await response.text();
|
|
88
|
-
emitHttpClientTrace({ state, response, responseBody: bodyText, durationMs });
|
|
89
|
-
return { response, bodyText, durationMs };
|
|
167
|
+
emitHttpClientTrace({ state, requestBody, response, responseBody: bodyText, durationMs });
|
|
168
|
+
return { response, bodyText, durationMs, requestBody };
|
|
90
169
|
}
|
|
91
170
|
async function performFetch(state) {
|
|
92
171
|
const timeout = state.timeout ?? Env.getInt('HTTP_TIMEOUT', 30000);
|
|
@@ -99,29 +178,31 @@ async function performFetch(state) {
|
|
|
99
178
|
if (OpenTelemetry.isEnabled()) {
|
|
100
179
|
OpenTelemetry.injectTraceHeaders(state.headers);
|
|
101
180
|
}
|
|
181
|
+
const requestBody = serializeRequestBody(state);
|
|
102
182
|
const init = {
|
|
103
183
|
method: state.method,
|
|
104
184
|
headers: state.headers,
|
|
105
185
|
signal: controller.signal,
|
|
106
186
|
};
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
['POST', 'PUT', 'PATCH'].includes(state.method)) {
|
|
110
|
-
init.body =
|
|
187
|
+
if (requestBody !== undefined &&
|
|
188
|
+
requestBody !== null &&
|
|
189
|
+
['POST', 'PUT', 'PATCH', 'DELETE'].includes(state.method)) {
|
|
190
|
+
init.body = requestBody;
|
|
111
191
|
}
|
|
112
|
-
return init;
|
|
192
|
+
return { init, requestBody };
|
|
113
193
|
};
|
|
114
194
|
const startTime = Date.now();
|
|
115
195
|
try {
|
|
116
|
-
const init = buildInit();
|
|
196
|
+
const { init, requestBody } = buildInit();
|
|
117
197
|
const response = await globalThis.fetch(state.url, init);
|
|
118
198
|
const duration = Date.now() - startTime;
|
|
119
|
-
return { response, durationMs: duration };
|
|
199
|
+
return { response, durationMs: duration, requestBody };
|
|
120
200
|
}
|
|
121
201
|
catch (error) {
|
|
122
202
|
const duration = Date.now() - startTime;
|
|
123
203
|
emitHttpClientTrace({
|
|
124
204
|
state,
|
|
205
|
+
requestBody: serializeRequestBody(state),
|
|
125
206
|
durationMs: duration,
|
|
126
207
|
error: error instanceof Error ? error.message : String(error),
|
|
127
208
|
});
|
|
@@ -154,7 +235,7 @@ function createRequestBuilder(method, url, initialBody) {
|
|
|
154
235
|
headers: {
|
|
155
236
|
'User-Agent': 'ZinTrust/1.0',
|
|
156
237
|
},
|
|
157
|
-
body: initialBody
|
|
238
|
+
body: initialBody ?? undefined,
|
|
158
239
|
};
|
|
159
240
|
const self = {
|
|
160
241
|
withHeader(name, value) {
|
|
@@ -188,19 +269,27 @@ function createRequestBuilder(method, url, initialBody) {
|
|
|
188
269
|
state.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
189
270
|
return self;
|
|
190
271
|
},
|
|
272
|
+
asCustom(mode) {
|
|
273
|
+
state.contentType = 'custom';
|
|
274
|
+
state.customMode = mode;
|
|
275
|
+
if (typeof mode.contentType === 'string' && mode.contentType.trim() !== '') {
|
|
276
|
+
state.headers['Content-Type'] = mode.contentType;
|
|
277
|
+
}
|
|
278
|
+
return self;
|
|
279
|
+
},
|
|
191
280
|
async send() {
|
|
192
281
|
return performRequest(state);
|
|
193
282
|
},
|
|
194
283
|
async sendRaw() {
|
|
195
|
-
const { response, durationMs } = await performFetch(state);
|
|
284
|
+
const { response, durationMs, requestBody } = await performFetch(state);
|
|
196
285
|
const responseBody = await captureTraceResponseBody(response);
|
|
197
|
-
emitHttpClientTrace({ state, response, responseBody, durationMs });
|
|
286
|
+
emitHttpClientTrace({ state, requestBody, response, responseBody, durationMs });
|
|
198
287
|
return response;
|
|
199
288
|
},
|
|
200
289
|
async sendStream() {
|
|
201
|
-
const { response, durationMs } = await performFetch(state);
|
|
290
|
+
const { response, durationMs, requestBody } = await performFetch(state);
|
|
202
291
|
const responseBody = await captureTraceResponseBody(response);
|
|
203
|
-
emitHttpClientTrace({ state, response, responseBody, durationMs });
|
|
292
|
+
emitHttpClientTrace({ state, requestBody, response, responseBody, durationMs });
|
|
204
293
|
return { response, stream: response.body };
|
|
205
294
|
},
|
|
206
295
|
};
|
|
@@ -221,7 +310,7 @@ export const HttpClient = Object.freeze({
|
|
|
221
310
|
*/
|
|
222
311
|
post(url, data) {
|
|
223
312
|
const builder = createRequestBuilder('POST', url, data);
|
|
224
|
-
if (data) {
|
|
313
|
+
if (isObject(data)) {
|
|
225
314
|
builder.asJson();
|
|
226
315
|
}
|
|
227
316
|
return builder;
|
|
@@ -231,7 +320,7 @@ export const HttpClient = Object.freeze({
|
|
|
231
320
|
*/
|
|
232
321
|
put(url, data) {
|
|
233
322
|
const builder = createRequestBuilder('PUT', url, data);
|
|
234
|
-
if (data) {
|
|
323
|
+
if (isObject(data)) {
|
|
235
324
|
builder.asJson();
|
|
236
325
|
}
|
|
237
326
|
return builder;
|
|
@@ -241,7 +330,7 @@ export const HttpClient = Object.freeze({
|
|
|
241
330
|
*/
|
|
242
331
|
patch(url, data) {
|
|
243
332
|
const builder = createRequestBuilder('PATCH', url, data);
|
|
244
|
-
if (data) {
|
|
333
|
+
if (isObject(data)) {
|
|
245
334
|
builder.asJson();
|
|
246
335
|
}
|
|
247
336
|
return builder;
|
|
@@ -251,7 +340,7 @@ export const HttpClient = Object.freeze({
|
|
|
251
340
|
*/
|
|
252
341
|
delete(url, data) {
|
|
253
342
|
const builder = createRequestBuilder('DELETE', url, data);
|
|
254
|
-
if (data) {
|
|
343
|
+
if (isObject(data)) {
|
|
255
344
|
builder.asJson();
|
|
256
345
|
}
|
|
257
346
|
return builder;
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
declare const _default: Readonly<{
|
|
5
5
|
HttpClient: Readonly<{
|
|
6
6
|
get(url: string): import("./Http").IHttpRequest;
|
|
7
|
-
post(url: string, data?:
|
|
8
|
-
put(url: string, data?:
|
|
9
|
-
patch(url: string, data?:
|
|
10
|
-
delete(url: string, data?:
|
|
7
|
+
post(url: string, data?: import("./Http").HttpRequestBody | null): import("./Http").IHttpRequest;
|
|
8
|
+
put(url: string, data?: import("./Http").HttpRequestBody | null): import("./Http").IHttpRequest;
|
|
9
|
+
patch(url: string, data?: import("./Http").HttpRequestBody | null): import("./Http").IHttpRequest;
|
|
10
|
+
delete(url: string, data?: import("./Http").HttpRequestBody | null): import("./Http").IHttpRequest;
|
|
11
11
|
}>;
|
|
12
12
|
createHttpResponse: (response: Response, body: string) => import("./HttpResponse").IHttpResponse;
|
|
13
13
|
}>;
|