@azure-net/kit 3.0.4 → 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> = Partial<FormData> | Promise<Partial<FormData>> | (() => Partial<FormData> | Promise<Partial<FormData>>);
4
- export interface FormConfig<FormData, Response> {
5
- initialData?: InitialData<FormData>;
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>>>(onSubmit: (formData: Partial<ExtractFromSubmit<SubmitReturn>["formData"]>) => SubmitReturn, config?: FormConfig<ExtractFromSubmit<SubmitReturn>["formData"], ExtractFromSubmit<SubmitReturn>["response"]>) => ActiveForm<ExtractFromSubmit<SubmitReturn>["formData"], ExtractFromSubmit<SubmitReturn>["response"], ExtractFromSubmit<SubmitReturn>["custom"]>;
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,12 +1,13 @@
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);
7
8
  beforeSend?: (meta: {
8
9
  initial: boolean;
9
- external: boolean;
10
+ source: AsyncSignalSource;
10
11
  }) => void | Promise<void>;
11
12
  onSuccess?: (data: TData) => void | Promise<void>;
12
13
  onError?: (error: TError) => void | Promise<void>;
@@ -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,7 +47,8 @@ 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
- let data = $state(initialData);
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');
@@ -55,7 +56,7 @@ export const createAsyncSignal = (handler, options = {}) => {
55
56
  let currentPromise = null;
56
57
  let currentRunId = 0;
57
58
  let started = false;
58
- const run = async (runId, external) => {
59
+ const run = async (runId, source) => {
59
60
  const initial = !started;
60
61
  started = true;
61
62
  if (abortController) {
@@ -63,7 +64,7 @@ export const createAsyncSignal = (handler, options = {}) => {
63
64
  }
64
65
  abortController = new AbortController();
65
66
  if (options.beforeSend) {
66
- await options.beforeSend({ initial, external });
67
+ await options.beforeSend({ initial, source });
67
68
  }
68
69
  status = 'pending';
69
70
  error = undefined;
@@ -96,12 +97,12 @@ export const createAsyncSignal = (handler, options = {}) => {
96
97
  }
97
98
  }
98
99
  };
99
- const start = (external) => {
100
+ const start = (source) => {
100
101
  if (currentPromise) {
101
102
  return currentPromise;
102
103
  }
103
104
  const runId = ++currentRunId;
104
- const localPromise = run(runId, external);
105
+ const localPromise = run(runId, source);
105
106
  currentPromise = localPromise;
106
107
  return localPromise;
107
108
  };
@@ -110,11 +111,13 @@ export const createAsyncSignal = (handler, options = {}) => {
110
111
  await currentPromise;
111
112
  return;
112
113
  }
113
- await start(true);
114
+ await start('manual');
114
115
  };
115
116
  if (EnvironmentUtil.isBrowser) {
116
117
  const signalKey = key ?? asyncSignalManager.generateKey();
117
- asyncSignalManager.register(signalKey, () => execute());
118
+ asyncSignalManager.register(signalKey, (source) => {
119
+ return start(source);
120
+ });
118
121
  $effect(() => {
119
122
  return () => {
120
123
  asyncSignalManager.unregister(signalKey);
@@ -129,7 +132,7 @@ export const createAsyncSignal = (handler, options = {}) => {
129
132
  return;
130
133
  }
131
134
  if (!isFirst) {
132
- void start(false);
135
+ void start('auto');
133
136
  }
134
137
  isFirst = false;
135
138
  });
@@ -138,11 +141,11 @@ export const createAsyncSignal = (handler, options = {}) => {
138
141
  if (immediate) {
139
142
  if (EnvironmentUtil.isServer && server) {
140
143
  untrack(() => {
141
- void start(false);
144
+ void start('auto');
142
145
  });
143
146
  }
144
147
  else if (EnvironmentUtil.isBrowser) {
145
- void start(false);
148
+ void start('auto');
146
149
  }
147
150
  }
148
151
  return {
@@ -161,7 +164,7 @@ export const createAsyncSignal = (handler, options = {}) => {
161
164
  get ready() {
162
165
  if (currentPromise)
163
166
  return currentPromise;
164
- return start(false);
167
+ return start('auto');
165
168
  },
166
169
  execute,
167
170
  refresh: execute,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-net/kit",
3
- "version": "3.0.4",
3
+ "version": "3.0.5",
4
4
  "files": [
5
5
  "dist",
6
6
  "!dist/**/*.test.*",