@azure-net/kit 3.9.1 → 3.9.3
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/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 -36
- package/dist/core/delivery/injectableDependencies/AsyncHelpers.js +79 -137
- 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 +13 -4
- package/dist/core/delivery/schema/Schema.js +11 -2
- package/dist/core/delivery/schema/rules/messages/index.d.ts +1 -0
- package/dist/core/delivery/schema/rules/messages/index.js +1 -0
- 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/httpService/HttpServiceInstance.d.ts +16 -8
- package/dist/core/infra/httpService/HttpServiceInstance.js +47 -49
- package/dist/core/infra/query/QueryBuilder.js +2 -1
- 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.js +1 -1
- package/dist/core/shared/boundaryProvider/Provider.js +4 -3
- 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 +8 -10
- package/dist/core/svelte/ActiveForm/ActiveForm.svelte.d.ts +6 -5
- package/dist/core/svelte/ActiveForm/ActiveForm.svelte.js +31 -26
- 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 +42 -54
- package/dist/core/ui/scrollTo/index.js +2 -2
- package/dist/edges/index.d.ts +1 -1
- package/dist/edges/index.js +1 -1
- package/package.json +13 -9
- 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
|
@@ -26,22 +26,26 @@ export class HttpServiceResponse {
|
|
|
26
26
|
this.raw = raw;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
export
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
export var HttpErrorTypes;
|
|
30
|
+
(function (HttpErrorTypes) {
|
|
31
|
+
HttpErrorTypes["Internal"] = "internal";
|
|
32
|
+
HttpErrorTypes["External"] = "external";
|
|
33
|
+
})(HttpErrorTypes || (HttpErrorTypes = {}));
|
|
34
|
+
export class HttpServiceError extends Error {
|
|
33
35
|
data;
|
|
36
|
+
status;
|
|
34
37
|
message;
|
|
38
|
+
type;
|
|
35
39
|
original;
|
|
36
|
-
|
|
37
|
-
constructor({
|
|
38
|
-
|
|
40
|
+
response;
|
|
41
|
+
constructor({ status = 500, data, message = 'unknown error', original, type = HttpErrorTypes.Internal, response }) {
|
|
42
|
+
super(message);
|
|
39
43
|
this.status = status;
|
|
40
|
-
this.success = success;
|
|
41
44
|
this.data = data;
|
|
42
45
|
this.message = message;
|
|
43
46
|
this.original = original;
|
|
44
|
-
this.
|
|
47
|
+
this.response = response;
|
|
48
|
+
this.type = type;
|
|
45
49
|
}
|
|
46
50
|
}
|
|
47
51
|
const stringifyJsonFunc = (data) => {
|
|
@@ -188,16 +192,39 @@ const withTimeout = (signal, timeout) => {
|
|
|
188
192
|
};
|
|
189
193
|
};
|
|
190
194
|
const shouldRetryError = (error) => {
|
|
191
|
-
|
|
192
|
-
return [408, 425, 429, 500, 502, 503, 504].includes(error.status);
|
|
193
|
-
}
|
|
194
|
-
return !(error instanceof Error && error.name === 'AbortError');
|
|
195
|
+
return error instanceof HttpServiceError && error.type === HttpErrorTypes.External;
|
|
195
196
|
};
|
|
196
197
|
const normalizeUnknownError = (error) => {
|
|
197
198
|
if (error instanceof Error)
|
|
198
199
|
return error;
|
|
199
200
|
return new Error(String(error));
|
|
200
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
|
+
};
|
|
201
228
|
const defaultDoFetch = async (request) => {
|
|
202
229
|
const maxAttempts = Math.max(1, Math.floor(request.retry) + 1);
|
|
203
230
|
let lastError;
|
|
@@ -211,30 +238,14 @@ const defaultDoFetch = async (request) => {
|
|
|
211
238
|
body: request.body,
|
|
212
239
|
signal: timeoutState.signal ?? undefined
|
|
213
240
|
});
|
|
214
|
-
const
|
|
215
|
-
const data = await parseBodyByFormat(response, request.responseFormat);
|
|
216
|
-
if (!response.ok) {
|
|
217
|
-
const httpError = new HttpServiceError({
|
|
218
|
-
headers: Object.fromEntries(response.headers.entries()),
|
|
219
|
-
status: response.status,
|
|
220
|
-
success: false,
|
|
221
|
-
data,
|
|
222
|
-
message: `Request failed with status code ${response.status}`,
|
|
223
|
-
raw: rawResponse
|
|
224
|
-
});
|
|
225
|
-
lastError = httpError;
|
|
226
|
-
if (attempt >= maxAttempts || !shouldRetryError(httpError)) {
|
|
227
|
-
throw httpError;
|
|
228
|
-
}
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
241
|
+
const { data, headers, status, raw } = await parseResponse(response, request);
|
|
231
242
|
return new HttpServiceResponse({
|
|
232
|
-
headers
|
|
233
|
-
status
|
|
243
|
+
headers,
|
|
244
|
+
status,
|
|
234
245
|
success: true,
|
|
235
246
|
data,
|
|
236
247
|
message: 'Request completed',
|
|
237
|
-
raw
|
|
248
|
+
raw
|
|
238
249
|
});
|
|
239
250
|
}
|
|
240
251
|
catch (error) {
|
|
@@ -303,28 +314,15 @@ const makeMethod = (method, defaults) => {
|
|
|
303
314
|
const normalizedError = error instanceof HttpServiceError
|
|
304
315
|
? error
|
|
305
316
|
: new HttpServiceError({
|
|
306
|
-
headers: {},
|
|
307
|
-
status: 500,
|
|
308
|
-
success: false,
|
|
309
317
|
data: undefined,
|
|
310
|
-
message: normalizeUnknownError(error).message,
|
|
318
|
+
message: normalizeUnknownError(error).message ?? 'Unknown error',
|
|
311
319
|
original: normalizeUnknownError(error)
|
|
312
320
|
});
|
|
313
321
|
const onError = options.onError ?? defaults.onError;
|
|
314
322
|
if (!onError)
|
|
315
323
|
throw normalizedError;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
throw new HttpServiceError({
|
|
319
|
-
headers: normalizedError.headers,
|
|
320
|
-
status: normalizedError.status,
|
|
321
|
-
success: false,
|
|
322
|
-
data: normalizedError.data,
|
|
323
|
-
message: 'onError hook must return HttpServiceError',
|
|
324
|
-
original: new Error(normalizedError.message)
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
throw handledError;
|
|
324
|
+
await onError(normalizedError, normalizedRequest);
|
|
325
|
+
throw normalizedError;
|
|
328
326
|
}
|
|
329
327
|
};
|
|
330
328
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AzureNetKitInternalError } from '../../shared/appError/AppError.js';
|
|
1
2
|
const normalizeSettings = (base, override) => {
|
|
2
3
|
return {
|
|
3
4
|
delimiter: override?.delimiter ?? base?.delimiter ?? true,
|
|
@@ -19,7 +20,7 @@ const encodeArrayEntries = (key, values, arrayFormat) => {
|
|
|
19
20
|
case 'json':
|
|
20
21
|
return [[key, JSON.stringify(cleanValues)]];
|
|
21
22
|
default:
|
|
22
|
-
throw new
|
|
23
|
+
throw new AzureNetKitInternalError(`[QueryInstance] Unsupported array format: ${arrayFormat}`);
|
|
23
24
|
}
|
|
24
25
|
};
|
|
25
26
|
const serializeEntries = (obj, arrayFormat, objectFormat, prefix = '') => {
|
|
@@ -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
1
|
import { EventBus } from '@azure-net/tools';
|
|
2
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,5 +1,6 @@
|
|
|
1
1
|
import { RequestContext } from '../../../edges/context/index.js';
|
|
2
2
|
import { BROWSER } from '@azure-net/tools/environment';
|
|
3
|
+
import { AzureNetKitInternalError } from '../appError/AppError.js';
|
|
3
4
|
const clientCache = new Map();
|
|
4
5
|
const factoriesCache = new WeakMap();
|
|
5
6
|
const providerProxyCache = new Map();
|
|
@@ -94,15 +95,15 @@ export const createBoundaryProvider = (name, settings) => {
|
|
|
94
95
|
}
|
|
95
96
|
const factories = getFactories();
|
|
96
97
|
if (!(key in factories)) {
|
|
97
|
-
throw new
|
|
98
|
+
throw new AzureNetKitInternalError(`[BoundaryProvider] Service '${key}' not found in provider '${name}'`);
|
|
98
99
|
}
|
|
99
100
|
const factory = factories[key];
|
|
100
101
|
if (typeof factory !== 'function') {
|
|
101
|
-
throw
|
|
102
|
+
throw new AzureNetKitInternalError('[BoundaryProvider] Factory must be a function');
|
|
102
103
|
}
|
|
103
104
|
const instance = factory();
|
|
104
105
|
if (instance && typeof instance?.then === 'function') {
|
|
105
|
-
throw new
|
|
106
|
+
throw new AzureNetKitInternalError(`[BoundaryProvider] Service '${key}' in provider '${name}' returned Promise.`);
|
|
106
107
|
}
|
|
107
108
|
cache.set(key, instance);
|
|
108
109
|
return instance;
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
declare const MIRROR_TARGET: unique symbol;
|
|
2
|
+
declare const MIRROR_CACHE: unique symbol;
|
|
3
|
+
export declare class ClassMirror {
|
|
4
|
+
private [MIRROR_TARGET];
|
|
5
|
+
private [MIRROR_CACHE];
|
|
6
|
+
constructor(target: object);
|
|
3
7
|
}
|
|
8
|
+
export {};
|
|
@@ -1,19 +1,38 @@
|
|
|
1
|
+
const MIRROR_TARGET = Symbol('class-mirror-target');
|
|
2
|
+
const MIRROR_CACHE = Symbol('class-mirror-cache');
|
|
1
3
|
export class ClassMirror {
|
|
4
|
+
[MIRROR_TARGET];
|
|
5
|
+
[MIRROR_CACHE];
|
|
2
6
|
constructor(target) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
this[MIRROR_TARGET] = target;
|
|
8
|
+
this[MIRROR_CACHE] = new Map();
|
|
9
|
+
return new Proxy(this, {
|
|
10
|
+
get(proxyTarget, prop, receiver) {
|
|
11
|
+
if (Reflect.has(proxyTarget, prop)) {
|
|
12
|
+
return Reflect.get(proxyTarget, prop, receiver);
|
|
13
|
+
}
|
|
14
|
+
const mirrorTarget = proxyTarget[MIRROR_TARGET];
|
|
15
|
+
const mirroredValue = Reflect.get(mirrorTarget, prop, mirrorTarget);
|
|
16
|
+
if (typeof mirroredValue !== 'function') {
|
|
17
|
+
return mirroredValue;
|
|
18
|
+
}
|
|
19
|
+
const cache = proxyTarget[MIRROR_CACHE];
|
|
20
|
+
if (cache.has(prop)) {
|
|
21
|
+
return cache.get(prop);
|
|
22
|
+
}
|
|
23
|
+
const bound = mirroredValue.bind(mirrorTarget);
|
|
24
|
+
cache.set(prop, bound);
|
|
25
|
+
return bound;
|
|
26
|
+
},
|
|
27
|
+
has(proxyTarget, prop) {
|
|
28
|
+
return Reflect.has(proxyTarget, prop) || Reflect.has(proxyTarget[MIRROR_TARGET], prop);
|
|
29
|
+
},
|
|
30
|
+
ownKeys(proxyTarget) {
|
|
31
|
+
return [...new Set([...Reflect.ownKeys(proxyTarget), ...Reflect.ownKeys(proxyTarget[MIRROR_TARGET])])];
|
|
32
|
+
},
|
|
33
|
+
getOwnPropertyDescriptor(proxyTarget, prop) {
|
|
34
|
+
return Reflect.getOwnPropertyDescriptor(proxyTarget, prop) ?? Reflect.getOwnPropertyDescriptor(proxyTarget[MIRROR_TARGET], prop);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
18
37
|
}
|
|
19
38
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Cookies
|
|
1
|
+
import { Cookies } from '@azure-net/tools';
|
|
2
|
+
import { BROWSER } from '@azure-net/tools/environment';
|
|
2
3
|
import { RequestContext } from '@azure-net/edges/context';
|
|
3
4
|
/**
|
|
4
5
|
* Utility class for managing cookies in svelte ssr (browser and server).
|
|
@@ -17,11 +18,11 @@ export class UniversalCookie {
|
|
|
17
18
|
* @returns {void}
|
|
18
19
|
*/
|
|
19
20
|
static set(name, value, options) {
|
|
20
|
-
if (
|
|
21
|
+
if (BROWSER) {
|
|
21
22
|
Cookies.set(name, value, options);
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
+
else {
|
|
25
26
|
const event = RequestContext.current().event;
|
|
26
27
|
if (event) {
|
|
27
28
|
const encodedKey = encodeURIComponent(name);
|
|
@@ -53,7 +54,6 @@ export class UniversalCookie {
|
|
|
53
54
|
return;
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
|
-
throw new Error('Could not detect current environment');
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
59
|
* Retrieves the value of a cookie by key.
|
|
@@ -64,10 +64,10 @@ export class UniversalCookie {
|
|
|
64
64
|
* @returns {T | undefined} The cookie value, parsed as type T or null if not found.
|
|
65
65
|
*/
|
|
66
66
|
static get(name) {
|
|
67
|
-
if (
|
|
67
|
+
if (BROWSER) {
|
|
68
68
|
return Cookies.get(name) ?? undefined;
|
|
69
69
|
}
|
|
70
|
-
|
|
70
|
+
else {
|
|
71
71
|
const event = RequestContext.current().event;
|
|
72
72
|
if (event) {
|
|
73
73
|
const encodedKey = encodeURIComponent(name);
|
|
@@ -85,7 +85,6 @@ export class UniversalCookie {
|
|
|
85
85
|
}
|
|
86
86
|
return undefined;
|
|
87
87
|
}
|
|
88
|
-
return undefined;
|
|
89
88
|
}
|
|
90
89
|
/**
|
|
91
90
|
* Retrieves all cookies as a key-value record.
|
|
@@ -95,10 +94,10 @@ export class UniversalCookie {
|
|
|
95
94
|
* @returns {T | undefined} An object with all cookie keys and their values.
|
|
96
95
|
*/
|
|
97
96
|
static getAll() {
|
|
98
|
-
if (
|
|
97
|
+
if (BROWSER) {
|
|
99
98
|
return Cookies.getAll();
|
|
100
99
|
}
|
|
101
|
-
|
|
100
|
+
else {
|
|
102
101
|
const event = RequestContext.current().event;
|
|
103
102
|
const result = {};
|
|
104
103
|
if (event) {
|
|
@@ -114,7 +113,6 @@ export class UniversalCookie {
|
|
|
114
113
|
}
|
|
115
114
|
return result;
|
|
116
115
|
}
|
|
117
|
-
return undefined;
|
|
118
116
|
}
|
|
119
117
|
/**
|
|
120
118
|
* Checks if a cookie with the given key exists.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RequestErrors } from '../../delivery/schema/index.js';
|
|
2
|
-
import type { AsyncActionResponse } from '../../
|
|
3
|
-
type InitialData<FormData, Initial extends Partial<FormData>> =
|
|
2
|
+
import type { AsyncActionResponse } from '../../delivery/injectableDependencies/AsyncHelpers.js';
|
|
3
|
+
type InitialData<FormData, Initial extends Partial<FormData>> = () => Initial | Promise<Initial>;
|
|
4
4
|
type PathRequiredShape<T, P extends string> = P extends `${infer Head}.${infer Tail}` ? Head extends keyof T ? {
|
|
5
5
|
[K in Head]-?: PathRequiredShape<NonNullable<T[K]>, Tail>;
|
|
6
6
|
} : unknown : P extends keyof T ? {
|
|
@@ -8,6 +8,7 @@ type PathRequiredShape<T, P extends string> = P extends `${infer Head}.${infer T
|
|
|
8
8
|
} : unknown;
|
|
9
9
|
type UnionToIntersection<U> = (U extends unknown ? (arg: U) => void : never) extends (arg: infer I) => void ? I : never;
|
|
10
10
|
type RequiredByPaths<T, P extends string> = [P] extends [never] ? object : UnionToIntersection<PathRequiredShape<T, P>>;
|
|
11
|
+
type ResetBehaviors = 'clear' | 'initial' | 'reloadInitial' | 'default';
|
|
11
12
|
export interface FormConfig<FormData, Response, Initial extends Partial<FormData> = Partial<FormData>, RequiredPath extends string = never> {
|
|
12
13
|
initialData?: InitialData<FormData, Initial>;
|
|
13
14
|
required?: readonly RequiredPath[];
|
|
@@ -17,13 +18,13 @@ export interface FormConfig<FormData, Response, Initial extends Partial<FormData
|
|
|
17
18
|
form: ActiveFormController<FormData, RequiredPath>;
|
|
18
19
|
abort: () => void;
|
|
19
20
|
}) => Promise<void> | void;
|
|
20
|
-
|
|
21
|
+
successBehavior?: ResetBehaviors;
|
|
21
22
|
}
|
|
22
23
|
export interface ActiveForm<FormData, Response, Custom, RequiredPath extends string = never> {
|
|
23
24
|
data: Partial<FormData> & RequiredByPaths<FormData, RequiredPath>;
|
|
24
25
|
errors: RequestErrors<FormData>;
|
|
25
26
|
submit: () => Promise<AsyncActionResponse<Response, FormData, Custom>>;
|
|
26
|
-
reset: (
|
|
27
|
+
reset: (behavior?: ResetBehaviors) => Promise<void>;
|
|
27
28
|
pending: boolean;
|
|
28
29
|
dirty: boolean;
|
|
29
30
|
ready: Promise<Partial<FormData>>;
|
|
@@ -31,7 +32,7 @@ export interface ActiveForm<FormData, Response, Custom, RequiredPath extends str
|
|
|
31
32
|
export interface ActiveFormController<FormData, RequiredPath extends string = never> {
|
|
32
33
|
data: Partial<FormData> & RequiredByPaths<FormData, RequiredPath>;
|
|
33
34
|
errors: RequestErrors<FormData>;
|
|
34
|
-
reset: (
|
|
35
|
+
reset: (behavior?: ResetBehaviors) => Promise<void>;
|
|
35
36
|
}
|
|
36
37
|
type ExtractResponse<T> = T extends AsyncActionResponse<infer R, unknown, unknown> ? R : never;
|
|
37
38
|
type ExtractFormData<T> = T extends AsyncActionResponse<unknown, infer D, unknown> ? D : never;
|
|
@@ -3,32 +3,27 @@ export const createActiveForm = (onSubmit, config) => {
|
|
|
3
3
|
const isPromise = (value) => {
|
|
4
4
|
return typeof value?.then === 'function';
|
|
5
5
|
};
|
|
6
|
-
|
|
7
|
-
const source = config?.initialData;
|
|
8
|
-
if (!source) {
|
|
9
|
-
return { sync: true, value: {} };
|
|
10
|
-
}
|
|
11
|
-
const result = typeof source === 'function' ? source() : source;
|
|
12
|
-
if (isPromise(result)) {
|
|
13
|
-
return { sync: false, promise: result };
|
|
14
|
-
}
|
|
15
|
-
return { sync: true, value: (result ?? {}) };
|
|
16
|
-
};
|
|
17
|
-
const initialSource = resolveInitialSource();
|
|
18
|
-
let initial = initialSource.sync ? initialSource.value : {};
|
|
6
|
+
let initial = {};
|
|
19
7
|
let formData = $state(ObjectUtil.deepClone(initial));
|
|
20
8
|
let formErrors = $state({});
|
|
21
9
|
let pending = $state(false);
|
|
22
10
|
const dirty = $derived(!ObjectUtil.equals(formData, initial));
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
11
|
+
const loadInitialData = async () => {
|
|
12
|
+
const source = config?.initialData;
|
|
13
|
+
if (!source) {
|
|
14
|
+
initial = {};
|
|
15
|
+
formData = ObjectUtil.deepClone(initial);
|
|
16
|
+
formErrors = {};
|
|
17
|
+
return initial;
|
|
29
18
|
}
|
|
19
|
+
const value = source();
|
|
20
|
+
const nextInitial = isPromise(value) ? await value : value;
|
|
21
|
+
initial = (nextInitial ?? {});
|
|
22
|
+
formData = ObjectUtil.deepClone(initial);
|
|
23
|
+
formErrors = {};
|
|
30
24
|
return initial;
|
|
31
|
-
}
|
|
25
|
+
};
|
|
26
|
+
const ready = loadInitialData();
|
|
32
27
|
const submit = async () => {
|
|
33
28
|
pending = true;
|
|
34
29
|
try {
|
|
@@ -49,11 +44,11 @@ export const createActiveForm = (onSubmit, config) => {
|
|
|
49
44
|
const result = await onSubmit($state.snapshot(formData));
|
|
50
45
|
if (result.success) {
|
|
51
46
|
await config?.onSuccess?.(result.response);
|
|
52
|
-
|
|
47
|
+
await reset(config?.successBehavior ?? 'default');
|
|
53
48
|
}
|
|
54
49
|
else {
|
|
55
|
-
if (result.error?.
|
|
56
|
-
formErrors = result.error.
|
|
50
|
+
if (result.error?.validation) {
|
|
51
|
+
formErrors = result.error.validation;
|
|
57
52
|
}
|
|
58
53
|
await config?.onError?.();
|
|
59
54
|
}
|
|
@@ -63,8 +58,18 @@ export const createActiveForm = (onSubmit, config) => {
|
|
|
63
58
|
pending = false;
|
|
64
59
|
}
|
|
65
60
|
};
|
|
66
|
-
const reset = (
|
|
67
|
-
|
|
61
|
+
const reset = async (behavior = 'clear') => {
|
|
62
|
+
switch (behavior) {
|
|
63
|
+
case 'clear':
|
|
64
|
+
formData = {};
|
|
65
|
+
break;
|
|
66
|
+
case 'initial':
|
|
67
|
+
formData = ObjectUtil.deepClone(initial);
|
|
68
|
+
break;
|
|
69
|
+
case 'reloadInitial':
|
|
70
|
+
await loadInitialData();
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
68
73
|
formErrors = {};
|
|
69
74
|
};
|
|
70
75
|
const formApi = {
|
|
@@ -101,8 +106,8 @@ export const createActiveForm = (onSubmit, config) => {
|
|
|
101
106
|
get pending() {
|
|
102
107
|
return pending;
|
|
103
108
|
},
|
|
104
|
-
ready,
|
|
105
109
|
submit,
|
|
110
|
+
ready,
|
|
106
111
|
reset
|
|
107
112
|
};
|
|
108
113
|
};
|
|
@@ -3,7 +3,6 @@ export type AsyncSignalSource = 'auto' | 'manual' | 'global';
|
|
|
3
3
|
export interface AsyncSignalOptions<TData, TError = Error> {
|
|
4
4
|
server?: boolean;
|
|
5
5
|
immediate?: boolean;
|
|
6
|
-
watch?: (() => unknown)[];
|
|
7
6
|
initialData?: TData | (() => TData);
|
|
8
7
|
beforeSend?: (meta: {
|
|
9
8
|
initial: boolean;
|