@azure-net/kit 3.0.3 → 3.0.5
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.
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import type { RequestErrors } from '../../delivery/schema/index.js';
|
|
2
2
|
import type { AsyncActionResponse } from '../../index.js';
|
|
3
|
-
type InitialData<FormData
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
type InitialData<FormData, Initial extends Partial<FormData>> = Initial | Promise<Initial> | (() => Initial | Promise<Initial>);
|
|
4
|
+
type PathRequiredShape<T, P extends string> = P extends `${infer Head}.${infer Tail}` ? Head extends keyof T ? {
|
|
5
|
+
[K in Head]-?: PathRequiredShape<NonNullable<T[K]>, Tail>;
|
|
6
|
+
} : unknown : P extends keyof T ? {
|
|
7
|
+
[K in P]-?: NonNullable<T[K]>;
|
|
8
|
+
} : unknown;
|
|
9
|
+
type UnionToIntersection<U> = (U extends unknown ? (arg: U) => void : never) extends (arg: infer I) => void ? I : never;
|
|
10
|
+
type RequiredByPaths<T, P extends string> = [P] extends [never] ? {} : UnionToIntersection<PathRequiredShape<T, P>>;
|
|
11
|
+
export interface FormConfig<FormData, Response, Initial extends Partial<FormData> = Partial<FormData>, RequiredPath extends string = never> {
|
|
12
|
+
initialData?: InitialData<FormData, Initial>;
|
|
13
|
+
required?: readonly RequiredPath[];
|
|
6
14
|
onSuccess?: (response: Response) => Promise<void> | void;
|
|
7
15
|
onError?: () => Promise<void> | void;
|
|
8
|
-
beforeSubmit?: (form: ActiveFormController<FormData>, abort: () => void) => Promise<void> | void;
|
|
16
|
+
beforeSubmit?: (form: ActiveFormController<FormData, RequiredPath>, abort: () => void) => Promise<void> | void;
|
|
9
17
|
waitForInitialData?: boolean;
|
|
10
18
|
}
|
|
11
|
-
export interface ActiveForm<FormData, Response, Custom> {
|
|
12
|
-
data: Partial<FormData>;
|
|
19
|
+
export interface ActiveForm<FormData, Response, Custom, RequiredPath extends string = never> {
|
|
20
|
+
data: Partial<FormData> & RequiredByPaths<FormData, RequiredPath>;
|
|
13
21
|
errors: RequestErrors<FormData>;
|
|
14
22
|
submit: () => Promise<AsyncActionResponse<Response, FormData, Custom>>;
|
|
15
23
|
reset: (toInitial?: boolean) => void;
|
|
@@ -17,8 +25,8 @@ export interface ActiveForm<FormData, Response, Custom> {
|
|
|
17
25
|
dirty: boolean;
|
|
18
26
|
ready: Promise<Partial<FormData>>;
|
|
19
27
|
}
|
|
20
|
-
export interface ActiveFormController<FormData> {
|
|
21
|
-
data: Partial<FormData>;
|
|
28
|
+
export interface ActiveFormController<FormData, RequiredPath extends string = never> {
|
|
29
|
+
data: Partial<FormData> & RequiredByPaths<FormData, RequiredPath>;
|
|
22
30
|
errors: RequestErrors<FormData>;
|
|
23
31
|
reset: (toInitial?: boolean) => void;
|
|
24
32
|
}
|
|
@@ -31,5 +39,5 @@ type ExtractFromSubmit<T> = {
|
|
|
31
39
|
formData: ExtractFormData<UnwrapPromise<T>>;
|
|
32
40
|
custom: ExtractCustom<UnwrapPromise<T>>;
|
|
33
41
|
};
|
|
34
|
-
export declare const createActiveForm: <SubmitReturn extends Promise<AsyncActionResponse<unknown, unknown, unknown
|
|
42
|
+
export declare const createActiveForm: <SubmitReturn extends Promise<AsyncActionResponse<unknown, unknown, unknown>>, RequiredPath extends string = never>(onSubmit: (formData: Partial<ExtractFromSubmit<SubmitReturn>["formData"]>) => SubmitReturn, config?: FormConfig<ExtractFromSubmit<SubmitReturn>["formData"], ExtractFromSubmit<SubmitReturn>["response"], Partial<ExtractFromSubmit<SubmitReturn>["formData"]>, RequiredPath>) => ActiveForm<ExtractFromSubmit<SubmitReturn>["formData"], ExtractFromSubmit<SubmitReturn>["response"], ExtractFromSubmit<SubmitReturn>["custom"], RequiredPath>;
|
|
35
43
|
export {};
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
export type AsyncStatus = 'idle' | 'pending' | 'success' | 'error';
|
|
2
|
+
export type AsyncSignalSource = 'auto' | 'manual' | 'global';
|
|
2
3
|
export interface AsyncSignalOptions<TData, TError = Error> {
|
|
3
4
|
server?: boolean;
|
|
4
5
|
immediate?: boolean;
|
|
5
6
|
watch?: (() => unknown)[];
|
|
6
|
-
initialData?: TData;
|
|
7
|
+
initialData?: TData | (() => TData);
|
|
8
|
+
beforeSend?: (meta: {
|
|
9
|
+
initial: boolean;
|
|
10
|
+
source: AsyncSignalSource;
|
|
11
|
+
}) => void | Promise<void>;
|
|
7
12
|
onSuccess?: (data: TData) => void | Promise<void>;
|
|
8
13
|
onError?: (error: TError) => void | Promise<void>;
|
|
9
14
|
key?: string;
|
|
@@ -25,7 +25,7 @@ const createAsyncSignalManager = () => {
|
|
|
25
25
|
if (instances) {
|
|
26
26
|
const instance = instances.get(key);
|
|
27
27
|
try {
|
|
28
|
-
await instance?.();
|
|
28
|
+
await instance?.('global');
|
|
29
29
|
}
|
|
30
30
|
catch {
|
|
31
31
|
return;
|
|
@@ -35,7 +35,7 @@ const createAsyncSignalManager = () => {
|
|
|
35
35
|
const refreshAll = async () => {
|
|
36
36
|
if (instances) {
|
|
37
37
|
try {
|
|
38
|
-
await Promise.all(instances.values().map((val) => val()));
|
|
38
|
+
await Promise.all(instances.values().map((val) => val('global')));
|
|
39
39
|
}
|
|
40
40
|
catch {
|
|
41
41
|
return;
|
|
@@ -47,18 +47,25 @@ const createAsyncSignalManager = () => {
|
|
|
47
47
|
const asyncSignalManager = createAsyncSignalManager();
|
|
48
48
|
export const createAsyncSignal = (handler, options = {}) => {
|
|
49
49
|
const { server = false, immediate = true, watch = [], initialData = undefined, key } = options;
|
|
50
|
-
|
|
50
|
+
const resolvedInitialData = typeof initialData === 'function' ? initialData() : initialData;
|
|
51
|
+
let data = $state(resolvedInitialData);
|
|
51
52
|
let error = $state();
|
|
52
53
|
let status = $state('idle');
|
|
53
54
|
const pending = $derived(status === 'pending');
|
|
54
55
|
let abortController = null;
|
|
55
56
|
let currentPromise = null;
|
|
56
57
|
let currentRunId = 0;
|
|
57
|
-
|
|
58
|
+
let started = false;
|
|
59
|
+
const run = async (runId, source) => {
|
|
60
|
+
const initial = !started;
|
|
61
|
+
started = true;
|
|
58
62
|
if (abortController) {
|
|
59
63
|
abortController.abort();
|
|
60
64
|
}
|
|
61
65
|
abortController = new AbortController();
|
|
66
|
+
if (options.beforeSend) {
|
|
67
|
+
await options.beforeSend({ initial, source });
|
|
68
|
+
}
|
|
62
69
|
status = 'pending';
|
|
63
70
|
error = undefined;
|
|
64
71
|
try {
|
|
@@ -90,22 +97,27 @@ export const createAsyncSignal = (handler, options = {}) => {
|
|
|
90
97
|
}
|
|
91
98
|
}
|
|
92
99
|
};
|
|
93
|
-
const start = () => {
|
|
100
|
+
const start = (source) => {
|
|
101
|
+
if (currentPromise) {
|
|
102
|
+
return currentPromise;
|
|
103
|
+
}
|
|
94
104
|
const runId = ++currentRunId;
|
|
95
|
-
const localPromise = run(runId);
|
|
105
|
+
const localPromise = run(runId, source);
|
|
96
106
|
currentPromise = localPromise;
|
|
97
107
|
return localPromise;
|
|
98
108
|
};
|
|
99
109
|
const execute = async () => {
|
|
100
|
-
if (
|
|
110
|
+
if (currentPromise) {
|
|
101
111
|
await currentPromise;
|
|
102
112
|
return;
|
|
103
113
|
}
|
|
104
|
-
await start();
|
|
114
|
+
await start('manual');
|
|
105
115
|
};
|
|
106
116
|
if (EnvironmentUtil.isBrowser) {
|
|
107
117
|
const signalKey = key ?? asyncSignalManager.generateKey();
|
|
108
|
-
asyncSignalManager.register(signalKey, () =>
|
|
118
|
+
asyncSignalManager.register(signalKey, (source) => {
|
|
119
|
+
return start(source);
|
|
120
|
+
});
|
|
109
121
|
$effect(() => {
|
|
110
122
|
return () => {
|
|
111
123
|
asyncSignalManager.unregister(signalKey);
|
|
@@ -120,7 +132,7 @@ export const createAsyncSignal = (handler, options = {}) => {
|
|
|
120
132
|
return;
|
|
121
133
|
}
|
|
122
134
|
if (!isFirst) {
|
|
123
|
-
void
|
|
135
|
+
void start('auto');
|
|
124
136
|
}
|
|
125
137
|
isFirst = false;
|
|
126
138
|
});
|
|
@@ -129,11 +141,11 @@ export const createAsyncSignal = (handler, options = {}) => {
|
|
|
129
141
|
if (immediate) {
|
|
130
142
|
if (EnvironmentUtil.isServer && server) {
|
|
131
143
|
untrack(() => {
|
|
132
|
-
void
|
|
144
|
+
void start('auto');
|
|
133
145
|
});
|
|
134
146
|
}
|
|
135
147
|
else if (EnvironmentUtil.isBrowser) {
|
|
136
|
-
void
|
|
148
|
+
void start('auto');
|
|
137
149
|
}
|
|
138
150
|
}
|
|
139
151
|
return {
|
|
@@ -152,7 +164,7 @@ export const createAsyncSignal = (handler, options = {}) => {
|
|
|
152
164
|
get ready() {
|
|
153
165
|
if (currentPromise)
|
|
154
166
|
return currentPromise;
|
|
155
|
-
return start();
|
|
167
|
+
return start('auto');
|
|
156
168
|
},
|
|
157
169
|
execute,
|
|
158
170
|
refresh: execute,
|