@azure-net/kit 3.1.0 → 3.9.2
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 +2 -2
- package/dist/core/delivery/index.d.ts +1 -4
- package/dist/core/delivery/index.js +1 -4
- package/dist/core/delivery/injectableDependencies/AsyncHelpers.d.ts +28 -30
- package/dist/core/delivery/injectableDependencies/AsyncHelpers.js +80 -116
- package/dist/core/delivery/injectableDependencies/ErrorHandler.d.ts +3 -21
- package/dist/core/delivery/injectableDependencies/ErrorHandler.js +11 -42
- package/dist/core/delivery/schema/Schema.d.ts +8 -1
- package/dist/core/delivery/schema/Schema.js +12 -3
- package/dist/core/delivery.d.ts +5 -0
- package/dist/core/delivery.js +5 -0
- package/dist/core/errors.d.ts +4 -0
- package/dist/core/errors.js +4 -0
- package/dist/core/index.d.ts +7 -8
- package/dist/core/index.js +7 -8
- package/dist/core/infra/datasource/BaseDatasource.d.ts +11 -11
- package/dist/core/infra/datasource/BaseDatasource.js +4 -4
- package/dist/core/infra/httpService/HttpServiceInstance.d.ts +90 -0
- package/dist/core/infra/httpService/HttpServiceInstance.js +340 -0
- package/dist/core/infra/httpService/index.d.ts +1 -1
- package/dist/core/infra/httpService/index.js +1 -1
- package/dist/core/infra/query/QueryBuilder.d.ts +9 -21
- package/dist/core/infra/query/QueryBuilder.js +63 -50
- package/dist/core/infra/response/BaseResponse.js +3 -2
- package/dist/core/infra.d.ts +6 -0
- package/dist/core/infra.js +6 -0
- package/dist/core/shared/appError/AppError.d.ts +30 -0
- package/dist/core/shared/appError/AppError.js +66 -0
- package/dist/core/shared/appEventBus/EventBus.d.ts +1 -1
- package/dist/core/shared/appEventBus/EventBus.js +3 -3
- package/dist/core/shared/boundaryProvider/Provider.d.ts +2 -2
- package/dist/core/shared/boundaryProvider/Provider.js +16 -9
- package/dist/core/shared/classMirror/ClassMirror.d.ts +7 -2
- package/dist/core/shared/classMirror/ClassMirror.js +34 -15
- package/dist/core/shared/cookie/UniversalCookie.js +9 -11
- package/dist/core/shared/middleware/Middleware.js +12 -8
- package/dist/core/svelte/ActiveForm/ActiveForm.svelte.d.ts +10 -6
- package/dist/core/svelte/ActiveForm/ActiveForm.svelte.js +47 -41
- package/dist/core/svelte/AsyncSignal/AsyncSignal.svelte.d.ts +0 -1
- package/dist/core/svelte/AsyncSignal/AsyncSignal.svelte.js +21 -30
- package/dist/core/svelte/Query/Query.svelte.d.ts +11 -12
- package/dist/core/svelte/Query/Query.svelte.js +43 -55
- package/dist/core/ui/onClickOutside/OnClickOutside.js +1 -1
- package/dist/core/ui/scrollTo/index.js +2 -2
- package/dist/edges/context/index.d.ts +1 -1
- package/dist/edges/context/index.js +1 -1
- package/dist/edges/dev/index.d.ts +1 -1
- package/dist/edges/dev/index.js +1 -1
- package/dist/edges/index.d.ts +1 -1
- package/dist/edges/index.js +1 -1
- package/dist/edges/plugin/index.d.ts +1 -1
- package/dist/edges/plugin/index.js +1 -1
- package/dist/edges/server/index.d.ts +1 -1
- package/dist/edges/server/index.js +1 -1
- package/dist/edges/state/index.d.ts +1 -1
- package/dist/edges/state/index.js +1 -1
- package/dist/i18n/index.d.ts +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/tools/index.d.ts +2 -1
- package/dist/tools/index.js +2 -1
- package/package.json +45 -47
- package/dist/core/delivery/serverAction/CreateServerAction.d.ts +0 -15
- package/dist/core/delivery/serverAction/CreateServerAction.js +0 -22
- package/dist/core/delivery/serverAction/index.d.ts +0 -1
- package/dist/core/delivery/serverAction/index.js +0 -1
- package/dist/core/infra/httpService/HttpService.d.ts +0 -74
- package/dist/core/infra/httpService/HttpService.js +0 -164
- package/dist/core/shared/eventBus/EventBus.d.ts +0 -87
- package/dist/core/shared/eventBus/EventBus.js +0 -227
- package/dist/core/shared/eventBus/index.d.ts +0 -1
- package/dist/core/shared/eventBus/index.js +0 -1
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { BROWSER } from '@azure-net/tools/environment';
|
|
2
|
+
import { RequestContext } from '@azure-net/edges/context';
|
|
3
|
+
export var HttpInstanceFetchMethods;
|
|
4
|
+
(function (HttpInstanceFetchMethods) {
|
|
5
|
+
HttpInstanceFetchMethods["GET"] = "GET";
|
|
6
|
+
HttpInstanceFetchMethods["POST"] = "POST";
|
|
7
|
+
HttpInstanceFetchMethods["PUT"] = "PUT";
|
|
8
|
+
HttpInstanceFetchMethods["PATCH"] = "PATCH";
|
|
9
|
+
HttpInstanceFetchMethods["DELETE"] = "DELETE";
|
|
10
|
+
HttpInstanceFetchMethods["HEAD"] = "HEAD";
|
|
11
|
+
HttpInstanceFetchMethods["OPTIONS"] = "OPTIONS";
|
|
12
|
+
})(HttpInstanceFetchMethods || (HttpInstanceFetchMethods = {}));
|
|
13
|
+
export class HttpServiceResponse {
|
|
14
|
+
headers;
|
|
15
|
+
status;
|
|
16
|
+
success;
|
|
17
|
+
data;
|
|
18
|
+
message;
|
|
19
|
+
raw;
|
|
20
|
+
constructor({ headers, status, success, data, message, raw }) {
|
|
21
|
+
this.headers = headers;
|
|
22
|
+
this.status = status;
|
|
23
|
+
this.success = success;
|
|
24
|
+
this.data = data;
|
|
25
|
+
this.message = message;
|
|
26
|
+
this.raw = raw;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export var HttpErrorTypes;
|
|
30
|
+
(function (HttpErrorTypes) {
|
|
31
|
+
HttpErrorTypes["Internal"] = "internal";
|
|
32
|
+
HttpErrorTypes["External"] = "external";
|
|
33
|
+
})(HttpErrorTypes || (HttpErrorTypes = {}));
|
|
34
|
+
export class HttpServiceError extends Error {
|
|
35
|
+
data;
|
|
36
|
+
status;
|
|
37
|
+
message;
|
|
38
|
+
type;
|
|
39
|
+
original;
|
|
40
|
+
response;
|
|
41
|
+
constructor({ status = 500, data, message = 'unknown error', original, type = HttpErrorTypes.Internal, response }) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.status = status;
|
|
44
|
+
this.data = data;
|
|
45
|
+
this.message = message;
|
|
46
|
+
this.original = original;
|
|
47
|
+
this.response = response;
|
|
48
|
+
this.type = type;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const stringifyJsonFunc = (data) => {
|
|
52
|
+
try {
|
|
53
|
+
return JSON.stringify(data);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const isAbsoluteUrl = (value) => /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(value);
|
|
60
|
+
const normalizeHeaders = (headers) => {
|
|
61
|
+
if (!headers)
|
|
62
|
+
return new Headers();
|
|
63
|
+
if (headers instanceof Headers)
|
|
64
|
+
return new Headers(headers);
|
|
65
|
+
if (Array.isArray(headers))
|
|
66
|
+
return new Headers(headers);
|
|
67
|
+
return new Headers(Object.entries(headers).filter(([, value]) => value !== undefined));
|
|
68
|
+
};
|
|
69
|
+
const normalizeSearchParams = (value) => {
|
|
70
|
+
if (!value)
|
|
71
|
+
return new URLSearchParams();
|
|
72
|
+
if (value instanceof URLSearchParams)
|
|
73
|
+
return new URLSearchParams(value);
|
|
74
|
+
if (typeof value === 'string')
|
|
75
|
+
return new URLSearchParams(value);
|
|
76
|
+
if (Array.isArray(value)) {
|
|
77
|
+
const params = new URLSearchParams();
|
|
78
|
+
for (const [key, rawValue] of value) {
|
|
79
|
+
params.append(String(key), String(rawValue));
|
|
80
|
+
}
|
|
81
|
+
return params;
|
|
82
|
+
}
|
|
83
|
+
const params = new URLSearchParams();
|
|
84
|
+
for (const [key, rawValue] of Object.entries(value)) {
|
|
85
|
+
if (rawValue === undefined)
|
|
86
|
+
continue;
|
|
87
|
+
params.append(key, String(rawValue));
|
|
88
|
+
}
|
|
89
|
+
return params;
|
|
90
|
+
};
|
|
91
|
+
const mergeSearchParams = (base, extra) => {
|
|
92
|
+
if (!base && !extra)
|
|
93
|
+
return undefined;
|
|
94
|
+
const result = normalizeSearchParams(base);
|
|
95
|
+
const next = normalizeSearchParams(extra);
|
|
96
|
+
for (const [key, value] of next.entries()) {
|
|
97
|
+
result.append(key, value);
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
};
|
|
101
|
+
const mergeOptions = (base = {}, extra = {}) => {
|
|
102
|
+
const mergedHeaders = new Headers(normalizeHeaders(base.headers));
|
|
103
|
+
for (const [key, value] of normalizeHeaders(extra.headers).entries()) {
|
|
104
|
+
mergedHeaders.set(key, value);
|
|
105
|
+
}
|
|
106
|
+
const mergedSearchParams = mergeSearchParams(base.searchParams, extra.searchParams);
|
|
107
|
+
return {
|
|
108
|
+
...base,
|
|
109
|
+
...extra,
|
|
110
|
+
headers: mergedHeaders,
|
|
111
|
+
searchParams: mergedSearchParams,
|
|
112
|
+
stringifyJson: extra.stringifyJson ?? base.stringifyJson,
|
|
113
|
+
onRequest: extra.onRequest ?? base.onRequest,
|
|
114
|
+
onError: extra.onError ?? base.onError,
|
|
115
|
+
doFetch: extra.doFetch ?? base.doFetch
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
const mergeQueryToRelativeUrl = (url, searchParams) => {
|
|
119
|
+
const hashIndex = url.indexOf('#');
|
|
120
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : '';
|
|
121
|
+
const urlWithoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
122
|
+
const queryIndex = urlWithoutHash.indexOf('?');
|
|
123
|
+
const path = queryIndex >= 0 ? urlWithoutHash.slice(0, queryIndex) : urlWithoutHash;
|
|
124
|
+
const query = queryIndex >= 0 ? urlWithoutHash.slice(queryIndex + 1) : '';
|
|
125
|
+
const merged = new URLSearchParams(query);
|
|
126
|
+
for (const [key, value] of searchParams.entries()) {
|
|
127
|
+
merged.append(key, value);
|
|
128
|
+
}
|
|
129
|
+
const nextQuery = merged.toString();
|
|
130
|
+
return `${path}${nextQuery ? `?${nextQuery}` : ''}${hash}`;
|
|
131
|
+
};
|
|
132
|
+
const resolveUrl = (target, baseUrl, searchParams) => {
|
|
133
|
+
if (!baseUrl && !searchParams)
|
|
134
|
+
return target;
|
|
135
|
+
let rawUrl = String(target);
|
|
136
|
+
if (baseUrl) {
|
|
137
|
+
const base = String(baseUrl);
|
|
138
|
+
rawUrl = isAbsoluteUrl(rawUrl) ? rawUrl : new URL(rawUrl, base).toString();
|
|
139
|
+
}
|
|
140
|
+
if (!searchParams)
|
|
141
|
+
return rawUrl;
|
|
142
|
+
const normalizedSearchParams = normalizeSearchParams(searchParams);
|
|
143
|
+
if (!normalizedSearchParams.size)
|
|
144
|
+
return rawUrl;
|
|
145
|
+
if (isAbsoluteUrl(rawUrl)) {
|
|
146
|
+
const absoluteUrl = new URL(rawUrl);
|
|
147
|
+
for (const [key, value] of normalizedSearchParams.entries()) {
|
|
148
|
+
absoluteUrl.searchParams.append(key, value);
|
|
149
|
+
}
|
|
150
|
+
return absoluteUrl.toString();
|
|
151
|
+
}
|
|
152
|
+
return mergeQueryToRelativeUrl(rawUrl, normalizedSearchParams);
|
|
153
|
+
};
|
|
154
|
+
const parseBodyByFormat = async (response, format) => {
|
|
155
|
+
switch (format) {
|
|
156
|
+
case 'blob':
|
|
157
|
+
return (await response.blob());
|
|
158
|
+
case 'text':
|
|
159
|
+
return (await response.text());
|
|
160
|
+
case 'arrayBuffer':
|
|
161
|
+
return (await response.arrayBuffer());
|
|
162
|
+
case 'body':
|
|
163
|
+
return response.body;
|
|
164
|
+
case 'json':
|
|
165
|
+
return (await response.json());
|
|
166
|
+
default:
|
|
167
|
+
return (await response.json());
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
const withTimeout = (signal, timeout) => {
|
|
171
|
+
if (!timeout || timeout <= 0) {
|
|
172
|
+
return { signal, clear: () => undefined };
|
|
173
|
+
}
|
|
174
|
+
const controller = new AbortController();
|
|
175
|
+
const timer = setTimeout(() => controller.abort(new Error('Request timeout exceeded')), timeout);
|
|
176
|
+
const abortBySource = () => controller.abort(signal?.reason);
|
|
177
|
+
if (signal) {
|
|
178
|
+
if (signal.aborted) {
|
|
179
|
+
abortBySource();
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
signal.addEventListener('abort', abortBySource, { once: true });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
signal: controller.signal,
|
|
187
|
+
clear: () => {
|
|
188
|
+
clearTimeout(timer);
|
|
189
|
+
if (signal)
|
|
190
|
+
signal.removeEventListener('abort', abortBySource);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
const shouldRetryError = (error) => {
|
|
195
|
+
return error instanceof HttpServiceError && error.type === HttpErrorTypes.External;
|
|
196
|
+
};
|
|
197
|
+
const normalizeUnknownError = (error) => {
|
|
198
|
+
if (error instanceof Error)
|
|
199
|
+
return error;
|
|
200
|
+
return new Error(String(error));
|
|
201
|
+
};
|
|
202
|
+
const parseResponse = async (response, request) => {
|
|
203
|
+
const raw = request.includeRaw && typeof response?.clone === 'function' ? response?.clone() : undefined;
|
|
204
|
+
let data;
|
|
205
|
+
let parseError;
|
|
206
|
+
try {
|
|
207
|
+
data = await parseBodyByFormat(response, request.responseFormat);
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
parseError = normalizeUnknownError(error);
|
|
211
|
+
data = undefined;
|
|
212
|
+
}
|
|
213
|
+
if (!response.ok || parseError) {
|
|
214
|
+
const message = !response.ok
|
|
215
|
+
? `Request failed with status code ${response.status}. ${response.statusText}`
|
|
216
|
+
: (parseError?.message ?? 'Internal error');
|
|
217
|
+
throw new HttpServiceError({
|
|
218
|
+
status: response.status,
|
|
219
|
+
data,
|
|
220
|
+
message,
|
|
221
|
+
type: !response.ok ? HttpErrorTypes.External : HttpErrorTypes.Internal,
|
|
222
|
+
original: parseError,
|
|
223
|
+
response: raw ?? response
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return { data, headers: Object.fromEntries(response.headers.entries()), status: response.status, raw };
|
|
227
|
+
};
|
|
228
|
+
const defaultDoFetch = async (request) => {
|
|
229
|
+
const maxAttempts = Math.max(1, Math.floor(request.retry) + 1);
|
|
230
|
+
let lastError;
|
|
231
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
232
|
+
const timeoutState = withTimeout(request.requestInit.signal ?? null, request.timeout);
|
|
233
|
+
try {
|
|
234
|
+
const response = await request.fetch(request.url, {
|
|
235
|
+
...request.requestInit,
|
|
236
|
+
method: request.method,
|
|
237
|
+
headers: request.headers,
|
|
238
|
+
body: request.body,
|
|
239
|
+
signal: timeoutState.signal ?? undefined
|
|
240
|
+
});
|
|
241
|
+
const { data, headers, status, raw } = await parseResponse(response, request);
|
|
242
|
+
return new HttpServiceResponse({
|
|
243
|
+
headers,
|
|
244
|
+
status,
|
|
245
|
+
success: true,
|
|
246
|
+
data,
|
|
247
|
+
message: 'Request completed',
|
|
248
|
+
raw
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
lastError = error;
|
|
253
|
+
if (attempt >= maxAttempts || !shouldRetryError(error)) {
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
finally {
|
|
258
|
+
timeoutState.clear();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
throw lastError;
|
|
262
|
+
};
|
|
263
|
+
const makeMethod = (method, defaults) => {
|
|
264
|
+
return async (url, options = {}) => {
|
|
265
|
+
const merged = mergeOptions(defaults, options);
|
|
266
|
+
const stringifyJson = merged.stringifyJson ?? stringifyJsonFunc;
|
|
267
|
+
const fetcher = !BROWSER ? (RequestContext.current()?.event?.fetch ?? fetch) : fetch;
|
|
268
|
+
const headers = normalizeHeaders(merged.headers);
|
|
269
|
+
let body = merged.body;
|
|
270
|
+
if (merged.json !== undefined && body === undefined) {
|
|
271
|
+
body = stringifyJson(merged.json);
|
|
272
|
+
if (!headers.has('content-type')) {
|
|
273
|
+
headers.set('content-type', 'application/json');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
const responseFormat = merged.responseFormat ?? 'json';
|
|
277
|
+
if (responseFormat === 'json' && !headers.has('accept')) {
|
|
278
|
+
headers.set('accept', 'application/json');
|
|
279
|
+
}
|
|
280
|
+
const normalizedRequest = {
|
|
281
|
+
url: resolveUrl(url, merged.prefixUrl, merged.searchParams),
|
|
282
|
+
method,
|
|
283
|
+
headers,
|
|
284
|
+
body,
|
|
285
|
+
responseFormat,
|
|
286
|
+
includeRaw: merged.includeRaw ?? false,
|
|
287
|
+
timeout: merged.timeout ?? 20000,
|
|
288
|
+
retry: merged.retry ?? 0,
|
|
289
|
+
stringifyJson,
|
|
290
|
+
fetch: fetcher,
|
|
291
|
+
requestInit: {
|
|
292
|
+
cache: merged.cache,
|
|
293
|
+
credentials: merged.credentials,
|
|
294
|
+
integrity: merged.integrity,
|
|
295
|
+
keepalive: merged.keepalive,
|
|
296
|
+
mode: merged.mode,
|
|
297
|
+
priority: merged.priority,
|
|
298
|
+
redirect: merged.redirect,
|
|
299
|
+
referrer: merged.referrer,
|
|
300
|
+
referrerPolicy: merged.referrerPolicy,
|
|
301
|
+
signal: merged.signal,
|
|
302
|
+
window: merged.window
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
const onRequest = options.onRequest ?? defaults.onRequest;
|
|
306
|
+
if (onRequest) {
|
|
307
|
+
await onRequest(normalizedRequest);
|
|
308
|
+
}
|
|
309
|
+
const doFetch = merged.doFetch ?? defaults.doFetch ?? defaultDoFetch;
|
|
310
|
+
try {
|
|
311
|
+
return await doFetch(normalizedRequest);
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
const normalizedError = error instanceof HttpServiceError
|
|
315
|
+
? error
|
|
316
|
+
: new HttpServiceError({
|
|
317
|
+
data: undefined,
|
|
318
|
+
message: normalizeUnknownError(error).message ?? 'Unknown error',
|
|
319
|
+
original: normalizeUnknownError(error)
|
|
320
|
+
});
|
|
321
|
+
const onError = options.onError ?? defaults.onError;
|
|
322
|
+
if (!onError)
|
|
323
|
+
throw normalizedError;
|
|
324
|
+
await onError(normalizedError, normalizedRequest);
|
|
325
|
+
throw normalizedError;
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
};
|
|
329
|
+
export const createHttpServiceInstance = (config = {}) => {
|
|
330
|
+
const defaults = { ...config };
|
|
331
|
+
return {
|
|
332
|
+
get: makeMethod(HttpInstanceFetchMethods.GET, defaults),
|
|
333
|
+
post: makeMethod(HttpInstanceFetchMethods.POST, defaults),
|
|
334
|
+
put: makeMethod(HttpInstanceFetchMethods.PUT, defaults),
|
|
335
|
+
delete: makeMethod(HttpInstanceFetchMethods.DELETE, defaults),
|
|
336
|
+
patch: makeMethod(HttpInstanceFetchMethods.PATCH, defaults),
|
|
337
|
+
head: makeMethod(HttpInstanceFetchMethods.HEAD, defaults),
|
|
338
|
+
options: makeMethod(HttpInstanceFetchMethods.OPTIONS, defaults)
|
|
339
|
+
};
|
|
340
|
+
};
|
|
@@ -1,25 +1,13 @@
|
|
|
1
1
|
export type ArrayFormat = 'repeat' | 'brackets' | 'comma' | 'json';
|
|
2
2
|
export type ObjectFormat = 'default' | 'nested-brackets';
|
|
3
|
-
export interface
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
transform(object: object): object;
|
|
3
|
+
export interface IQueryBuilderSettings<TTransformInput extends object = object> {
|
|
4
|
+
delimiter?: boolean;
|
|
5
|
+
arrayFormat?: ArrayFormat;
|
|
6
|
+
objectFormat?: ObjectFormat;
|
|
7
|
+
transform?: (obj: TTransformInput) => object;
|
|
9
8
|
}
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
constructor(options?: {
|
|
14
|
-
arrayFormat?: ArrayFormat;
|
|
15
|
-
objectFormat?: ObjectFormat;
|
|
16
|
-
});
|
|
17
|
-
transform(object: object): object;
|
|
18
|
-
build(query?: object, opts?: {
|
|
19
|
-
delimiter?: boolean;
|
|
20
|
-
arrayFormat?: ArrayFormat;
|
|
21
|
-
objectFormat?: ObjectFormat;
|
|
22
|
-
}): string;
|
|
23
|
-
private serialize;
|
|
24
|
-
private encodeArray;
|
|
9
|
+
export interface IQueryBuilderInstance<TTransformInput extends object = object> {
|
|
10
|
+
toString: (query: object, settings?: IQueryBuilderSettings<TTransformInput>) => string;
|
|
11
|
+
toSearchParams: (query: object, settings?: Omit<IQueryBuilderSettings<TTransformInput>, 'delimiter'>) => URLSearchParams;
|
|
25
12
|
}
|
|
13
|
+
export declare const createQueryInstance: <TTransformInput extends object = object>(defaults?: IQueryBuilderSettings<TTransformInput>) => IQueryBuilderInstance<TTransformInput>;
|
|
@@ -1,57 +1,70 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { AzureNetKitInternalError } from '../../shared/appError/AppError.js';
|
|
2
|
+
const normalizeSettings = (base, override) => {
|
|
3
|
+
return {
|
|
4
|
+
delimiter: override?.delimiter ?? base?.delimiter ?? true,
|
|
5
|
+
arrayFormat: override?.arrayFormat ?? base?.arrayFormat ?? 'repeat',
|
|
6
|
+
objectFormat: override?.objectFormat ?? base?.objectFormat ?? 'default',
|
|
7
|
+
transform: override?.transform ?? base?.transform
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
const encodeQuery = (entries) => entries.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&');
|
|
11
|
+
const encodeArrayEntries = (key, values, arrayFormat) => {
|
|
12
|
+
const cleanValues = values.filter((v) => v !== null && v !== undefined).map((v) => String(v));
|
|
13
|
+
switch (arrayFormat) {
|
|
14
|
+
case 'repeat':
|
|
15
|
+
return cleanValues.map((v) => [key, v]);
|
|
16
|
+
case 'brackets':
|
|
17
|
+
return cleanValues.map((v) => [`${key}[]`, v]);
|
|
18
|
+
case 'comma':
|
|
19
|
+
return [[key, cleanValues.join(',')]];
|
|
20
|
+
case 'json':
|
|
21
|
+
return [[key, JSON.stringify(cleanValues)]];
|
|
22
|
+
default:
|
|
23
|
+
throw new AzureNetKitInternalError(`[QueryInstance] Unsupported array format: ${arrayFormat}`);
|
|
7
24
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (value === null || value === undefined)
|
|
23
|
-
continue;
|
|
24
|
-
const fullKey = prefix ? (objectFormat === 'nested-brackets' ? `${prefix}[${key}]` : `${prefix}.${key}`) : key;
|
|
25
|
-
if (Array.isArray(value)) {
|
|
26
|
-
parts.push(...this.encodeArray(fullKey, value, arrayFormat));
|
|
27
|
-
}
|
|
28
|
-
else if (typeof value === 'object' && !(value instanceof Date)) {
|
|
29
|
-
if (objectFormat === 'nested-brackets') {
|
|
30
|
-
parts.push(...this.serialize(value, arrayFormat, objectFormat, fullKey));
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
parts.push(`${encodeURIComponent(fullKey)}=${encodeURIComponent(JSON.stringify(value))}`);
|
|
34
|
-
}
|
|
25
|
+
};
|
|
26
|
+
const serializeEntries = (obj, arrayFormat, objectFormat, prefix = '') => {
|
|
27
|
+
const entries = [];
|
|
28
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
29
|
+
if (value === null || value === undefined)
|
|
30
|
+
continue;
|
|
31
|
+
const fullKey = prefix ? (objectFormat === 'nested-brackets' ? `${prefix}[${key}]` : `${prefix}.${key}`) : key;
|
|
32
|
+
if (Array.isArray(value)) {
|
|
33
|
+
entries.push(...encodeArrayEntries(fullKey, value, arrayFormat));
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (typeof value === 'object' && !(value instanceof Date)) {
|
|
37
|
+
if (objectFormat === 'nested-brackets') {
|
|
38
|
+
entries.push(...serializeEntries(value, arrayFormat, objectFormat, fullKey));
|
|
35
39
|
}
|
|
36
40
|
else {
|
|
37
|
-
|
|
41
|
+
entries.push([fullKey, JSON.stringify(value)]);
|
|
38
42
|
}
|
|
43
|
+
continue;
|
|
39
44
|
}
|
|
40
|
-
|
|
45
|
+
entries.push([fullKey, String(value)]);
|
|
41
46
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return [`${encodeURIComponent(key)}=${encodeURIComponent(cleanArray.join(','))}`];
|
|
51
|
-
case 'json':
|
|
52
|
-
return [`${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(cleanArray))}`];
|
|
53
|
-
default:
|
|
54
|
-
throw new Error(`Unsupported array format: ${arrayFormat}`);
|
|
55
|
-
}
|
|
47
|
+
return entries;
|
|
48
|
+
};
|
|
49
|
+
const toSearchParamsWithSettings = (query, settings) => {
|
|
50
|
+
const source = settings.transform ? settings.transform(query) : query;
|
|
51
|
+
const entries = serializeEntries(source, settings.arrayFormat, settings.objectFormat);
|
|
52
|
+
const params = new URLSearchParams();
|
|
53
|
+
for (const [key, value] of entries) {
|
|
54
|
+
params.append(key, value);
|
|
56
55
|
}
|
|
57
|
-
|
|
56
|
+
return params;
|
|
57
|
+
};
|
|
58
|
+
export const createQueryInstance = (defaults) => {
|
|
59
|
+
return {
|
|
60
|
+
toSearchParams: (query, settings) => {
|
|
61
|
+
const resolved = normalizeSettings(defaults, settings);
|
|
62
|
+
return toSearchParamsWithSettings(query, resolved);
|
|
63
|
+
},
|
|
64
|
+
toString: (query, settings) => {
|
|
65
|
+
const resolved = normalizeSettings(defaults, settings);
|
|
66
|
+
const serialized = encodeQuery(Array.from(toSearchParamsWithSettings(query, resolved).entries()));
|
|
67
|
+
return resolved.delimiter && serialized ? `?${serialized}` : serialized;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AzureNetKitInternalError } from '../../shared/appError/AppError.js';
|
|
1
2
|
export class ResponseBuilder {
|
|
2
3
|
response;
|
|
3
4
|
state;
|
|
@@ -22,7 +23,7 @@ export class ResponseBuilder {
|
|
|
22
23
|
}
|
|
23
24
|
mapCollectionUsing(ResourceClass) {
|
|
24
25
|
if (!Array.isArray(this.state.data)) {
|
|
25
|
-
throw new
|
|
26
|
+
throw new AzureNetKitInternalError('[ResponseBuilder] Method "mapCollectionUsing" can only be used when data is an array');
|
|
26
27
|
}
|
|
27
28
|
const collection = this.state.data.map((dataElement) => new ResourceClass(dataElement).toPlainObject());
|
|
28
29
|
const newResponse = new this.constructor(this.response);
|
|
@@ -40,7 +41,7 @@ export class ResponseBuilder {
|
|
|
40
41
|
result = result[key];
|
|
41
42
|
}
|
|
42
43
|
else {
|
|
43
|
-
throw new
|
|
44
|
+
throw new AzureNetKitInternalError(`[ResponseBuilder] Failed to extract: path "${path}" not found in response data`);
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
const newResponse = new this.constructor(this.response);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createHttpServiceInstance, HttpInstanceFetchMethods, HttpErrorTypes, HttpServiceResponse, type IHttpServiceError, type IHttpServiceResponse, type IHttpServiceInstance, type IHttpInstanceOptions, type HttpInstanceNormalizedRequest, type HttpInstanceOnRequest, type HttpInstanceOnError, type HttpInstanceDoFetch, type HttpInstanceRequestMethod } from './infra/httpService/HttpServiceInstance.js';
|
|
2
|
+
export { HttpStatusCode } from './infra/httpService/Statuses.js';
|
|
3
|
+
export { BaseHttpDatasource, type CreateRequestCallbackType } from './infra/datasource/BaseDatasource.js';
|
|
4
|
+
export { ResponseBuilder } from './infra/response/BaseResponse.js';
|
|
5
|
+
export { createQueryInstance, type IQueryBuilderInstance, type ArrayFormat, type ObjectFormat, type IQueryBuilderSettings } from './infra/query/QueryBuilder.js';
|
|
6
|
+
export { DTOMapper, type IDTOMapper } from './infra/resource/BaseResource.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createHttpServiceInstance, HttpInstanceFetchMethods, HttpErrorTypes, HttpServiceResponse } from './infra/httpService/HttpServiceInstance.js';
|
|
2
|
+
export { HttpStatusCode } from './infra/httpService/Statuses.js';
|
|
3
|
+
export { BaseHttpDatasource } from './infra/datasource/BaseDatasource.js';
|
|
4
|
+
export { ResponseBuilder } from './infra/response/BaseResponse.js';
|
|
5
|
+
export { createQueryInstance } from './infra/query/QueryBuilder.js';
|
|
6
|
+
export { DTOMapper } from './infra/resource/BaseResource.js';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { HttpServiceError } from '../../infra/httpService/HttpServiceInstance.js';
|
|
2
|
+
import { type RequestErrors } from '../../delivery/schema/Schema.js';
|
|
3
|
+
export declare enum ErrorTypes {
|
|
4
|
+
Http = "Http",
|
|
5
|
+
Schema = "Schema",
|
|
6
|
+
KitInternalError = "AzureNetKitInternal",
|
|
7
|
+
AsyncHelperError = "AsyncHelperError",
|
|
8
|
+
Unknown = "Unknown"
|
|
9
|
+
}
|
|
10
|
+
export declare class AzureNetKitInternalError extends Error {
|
|
11
|
+
}
|
|
12
|
+
export interface IAppError<T = unknown> {
|
|
13
|
+
type: ErrorTypes;
|
|
14
|
+
message: string;
|
|
15
|
+
validation?: RequestErrors<T>;
|
|
16
|
+
external: boolean;
|
|
17
|
+
appErrorConvert?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare class AppError<T = unknown> extends Error {
|
|
20
|
+
error: Error;
|
|
21
|
+
type: ErrorTypes;
|
|
22
|
+
message: string;
|
|
23
|
+
external: boolean;
|
|
24
|
+
validation?: RequestErrors<T>;
|
|
25
|
+
constructor(error: Error);
|
|
26
|
+
tryToGetExternalError<HttpServiceDataType = unknown>(): HttpServiceError<HttpServiceDataType> | undefined;
|
|
27
|
+
redeclareValidation<D = T>(validation: D): void;
|
|
28
|
+
toPlainObject<CustomData extends object>(custom?: CustomData): IAppError<T> & CustomData;
|
|
29
|
+
private parseError;
|
|
30
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { HttpErrorTypes, HttpServiceError } from '../../infra/httpService/HttpServiceInstance.js';
|
|
2
|
+
import { SchemaFail } from '../../delivery/schema/Schema.js';
|
|
3
|
+
import { AsyncHelperError } from '../../delivery/injectableDependencies/AsyncHelpers.js';
|
|
4
|
+
export var ErrorTypes;
|
|
5
|
+
(function (ErrorTypes) {
|
|
6
|
+
ErrorTypes["Http"] = "Http";
|
|
7
|
+
ErrorTypes["Schema"] = "Schema";
|
|
8
|
+
ErrorTypes["KitInternalError"] = "AzureNetKitInternal";
|
|
9
|
+
ErrorTypes["AsyncHelperError"] = "AsyncHelperError";
|
|
10
|
+
ErrorTypes["Unknown"] = "Unknown";
|
|
11
|
+
})(ErrorTypes || (ErrorTypes = {}));
|
|
12
|
+
export class AzureNetKitInternalError extends Error {
|
|
13
|
+
}
|
|
14
|
+
export class AppError extends Error {
|
|
15
|
+
error;
|
|
16
|
+
type = ErrorTypes.Unknown;
|
|
17
|
+
message;
|
|
18
|
+
external = false;
|
|
19
|
+
validation;
|
|
20
|
+
constructor(error) {
|
|
21
|
+
super(error.message);
|
|
22
|
+
this.error = error;
|
|
23
|
+
this.message = error.message ?? 'Unknown error';
|
|
24
|
+
this.parseError();
|
|
25
|
+
}
|
|
26
|
+
tryToGetExternalError() {
|
|
27
|
+
if (this.external && this.error instanceof HttpServiceError) {
|
|
28
|
+
return this.error;
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
redeclareValidation(validation) {
|
|
33
|
+
this.validation = validation;
|
|
34
|
+
}
|
|
35
|
+
toPlainObject(custom) {
|
|
36
|
+
const customData = custom ?? {};
|
|
37
|
+
return {
|
|
38
|
+
message: this.message,
|
|
39
|
+
type: this.type,
|
|
40
|
+
external: this.external,
|
|
41
|
+
validation: this.validation,
|
|
42
|
+
appErrorConvert: true,
|
|
43
|
+
...customData
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
parseError() {
|
|
47
|
+
switch (true) {
|
|
48
|
+
case this.error instanceof HttpServiceError:
|
|
49
|
+
this.type = ErrorTypes.Http;
|
|
50
|
+
this.external = this.error.type === HttpErrorTypes.External;
|
|
51
|
+
break;
|
|
52
|
+
case this.error instanceof SchemaFail:
|
|
53
|
+
this.type = ErrorTypes.Schema;
|
|
54
|
+
this.validation = this.error.getSelfTypedData();
|
|
55
|
+
break;
|
|
56
|
+
case this.error instanceof AzureNetKitInternalError:
|
|
57
|
+
this.type = ErrorTypes.KitInternalError;
|
|
58
|
+
break;
|
|
59
|
+
case this.error instanceof AsyncHelperError:
|
|
60
|
+
this.type = ErrorTypes.AsyncHelperError;
|
|
61
|
+
break;
|
|
62
|
+
default:
|
|
63
|
+
this.type = ErrorTypes.Unknown;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { EventBus } from 'azure-net
|
|
2
|
-
import { createPresenter } from 'edges
|
|
1
|
+
import { EventBus } from '@azure-net/tools';
|
|
2
|
+
import { createPresenter } from '@azure-net/edges';
|
|
3
3
|
export const AppEvents = createPresenter(() => {
|
|
4
|
-
const appEventBus = new EventBus({
|
|
4
|
+
const appEventBus = new EventBus({});
|
|
5
5
|
return {
|
|
6
6
|
bus: appEventBus
|
|
7
7
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
type ServiceFactory<T> = () => T
|
|
1
|
+
type ServiceFactory<T> = () => T;
|
|
2
2
|
type ServiceMap = Record<string, ServiceFactory<unknown>>;
|
|
3
3
|
type ResolvedServices<T extends ServiceMap> = {
|
|
4
|
-
[K in keyof T]:
|
|
4
|
+
[K in keyof T]: ReturnType<T[K]>;
|
|
5
5
|
};
|
|
6
6
|
type InferProviderType<T> = T extends ProviderWithType<infer S> ? ResolvedServices<S> : never;
|
|
7
7
|
export interface ProviderWithType<T extends ServiceMap> {
|