@skopon-cool/form-sdk 0.3.0 → 0.3.1

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.
@@ -8,6 +8,7 @@ export interface FormAutoControlTargets {
8
8
  }
9
9
  export interface FormAutoControlHelpers {
10
10
  reportEvent: (event: FormRuntimeEventData) => void;
11
+ /** 支持同步或返回 Promise(async submit 期间保持 autoControlDepth) */
11
12
  runAutoControl: <T>(fn: () => T) => T;
12
13
  }
13
14
  /** 执行下行 form_auto_control_event;缺参或未知 action 时 warn 并忽略。 */
@@ -1 +1 @@
1
- {"version":3,"file":"formAutoControl.d.ts","sourceRoot":"","sources":["../../src/runtime/formAutoControl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAE7E,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACpD,SAAS,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7D,MAAM,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClC,yCAAyC;IACzC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAA;IAClD,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;CACtC;AAiCD,4DAA4D;AAC5D,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,wBAAwB,EAC9B,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,sBAAsB,GAC9B,IAAI,CAyDN"}
1
+ {"version":3,"file":"formAutoControl.d.ts","sourceRoot":"","sources":["../../src/runtime/formAutoControl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAE7E,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACpD,SAAS,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7D,MAAM,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClC,yCAAyC;IACzC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAA;IAClD,0DAA0D;IAC1D,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;CACtC;AAiCD,4DAA4D;AAC5D,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,wBAAwB,EAC9B,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,sBAAsB,GAC9B,IAAI,CAyDN"}
@@ -4,6 +4,10 @@ import type { FormRuntimeEventData } from './types';
4
4
  export interface FormRuntimeContextValue {
5
5
  reportEvent: (event: FormRuntimeEventData) => void;
6
6
  reportData: (values: Record<string, unknown>) => void;
7
+ /**
8
+ * 在自动控上下文中执行 fn。若 fn 返回 Promise,depth 保持到 settle,
9
+ * 使异步 submit 内的 reportEvent 仍为 form_auto_control_bac_event。
10
+ */
7
11
  runAutoControl: <T>(fn: () => T) => T;
8
12
  isAutoControl: () => boolean;
9
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"formRuntimeContext.d.ts","sourceRoot":"","sources":["../../src/runtime/formRuntimeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEnD,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAA;IAClD,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACrD,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IACrC,aAAa,EAAE,MAAM,OAAO,CAAA;CAC7B;AAqBD,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAA;IAClC,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,QAAQ,GACT,EAAE,wBAAwB,+BAwD1B;AAED,uCAAuC;AACvC,wBAAgB,cAAc,IAAI,uBAAuB,CAExD"}
1
+ {"version":3,"file":"formRuntimeContext.d.ts","sourceRoot":"","sources":["../../src/runtime/formRuntimeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEnD,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAA;IAClD,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACrD;;;OAGG;IACH,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IACrC,aAAa,EAAE,MAAM,OAAO,CAAA;CAC7B;AA6BD,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAA;IAClC,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,QAAQ,GACT,EAAE,wBAAwB,+BAkE1B;AAED,uCAAuC;AACvC,wBAAgB,cAAc,IAAI,uBAAuB,CAExD"}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.3.0",
6
+ "version": "0.3.1",
7
7
  "description": "Skopon form rendering SDK (A2UI + form_definition) with submit helpers",
8
8
  "type": "module",
9
9
  "sideEffects": [
@@ -5,6 +5,32 @@ import { describe, it, expect, vi } from 'vitest'
5
5
  import { executeFormAutoControl } from './formAutoControl'
6
6
  import type { FormAutoControlEventData } from './types'
7
7
 
8
+ /** 模拟 FormRuntimeProvider.runAutoControl:Promise settle 前保持 depth。 */
9
+ function createDepthTrackingRunAutoControl(depthRef: { current: number }) {
10
+ return <T,>(fn: () => T): T => {
11
+ depthRef.current += 1
12
+ let syncResult: T
13
+ try {
14
+ syncResult = fn()
15
+ } catch (error) {
16
+ depthRef.current = Math.max(0, depthRef.current - 1)
17
+ throw error
18
+ }
19
+ if (
20
+ syncResult != null &&
21
+ (typeof syncResult === 'object' || typeof syncResult === 'function') &&
22
+ typeof (syncResult as PromiseLike<unknown>).then === 'function'
23
+ ) {
24
+ const promise = Promise.resolve(syncResult).finally(() => {
25
+ depthRef.current = Math.max(0, depthRef.current - 1)
26
+ })
27
+ return promise as T
28
+ }
29
+ depthRef.current = Math.max(0, depthRef.current - 1)
30
+ return syncResult
31
+ }
32
+ }
33
+
8
34
  describe('executeFormAutoControl', () => {
9
35
  it('writes values and reports bac change event', () => {
10
36
  const setValues = vi.fn()
@@ -68,4 +94,34 @@ describe('executeFormAutoControl', () => {
68
94
  )
69
95
  expect(submit).toHaveBeenCalled()
70
96
  })
97
+
98
+ it('keeps autoControl depth until async submit settles', async () => {
99
+ const depthRef = { current: 0 }
100
+ const runAutoControl = createDepthTrackingRunAutoControl(depthRef)
101
+ let resolveSubmit!: () => void
102
+ const submit = vi.fn(
103
+ () =>
104
+ new Promise<void>((resolve) => {
105
+ resolveSubmit = resolve
106
+ }),
107
+ )
108
+
109
+ executeFormAutoControl(
110
+ { action: 'submit' },
111
+ {
112
+ setValues: vi.fn(),
113
+ getValues: () => ({}),
114
+ submit,
115
+ rootElement: null,
116
+ },
117
+ { reportEvent: vi.fn(), runAutoControl },
118
+ )
119
+
120
+ expect(submit).toHaveBeenCalled()
121
+ expect(depthRef.current).toBe(1)
122
+ resolveSubmit()
123
+ await Promise.resolve()
124
+ await Promise.resolve()
125
+ expect(depthRef.current).toBe(0)
126
+ })
71
127
  })
@@ -10,6 +10,7 @@ export interface FormAutoControlTargets {
10
10
 
11
11
  export interface FormAutoControlHelpers {
12
12
  reportEvent: (event: FormRuntimeEventData) => void
13
+ /** 支持同步或返回 Promise(async submit 期间保持 autoControlDepth) */
13
14
  runAutoControl: <T>(fn: () => T) => T
14
15
  }
15
16
 
@@ -64,8 +65,8 @@ export function executeFormAutoControl(
64
65
 
65
66
  helpers.runAutoControl(() => {
66
67
  if (action === 'submit') {
67
- void targets.submit()
68
- return
68
+ // 返回 Promise,使 runAutoControl 在 settle 前保持 depth
69
+ return targets.submit()
69
70
  }
70
71
 
71
72
  const field = typeof data.field === 'string' ? data.field.trim() : ''
@@ -12,12 +12,24 @@ import type { FormRuntimeEventData } from './types'
12
12
  export interface FormRuntimeContextValue {
13
13
  reportEvent: (event: FormRuntimeEventData) => void
14
14
  reportData: (values: Record<string, unknown>) => void
15
+ /**
16
+ * 在自动控上下文中执行 fn。若 fn 返回 Promise,depth 保持到 settle,
17
+ * 使异步 submit 内的 reportEvent 仍为 form_auto_control_bac_event。
18
+ */
15
19
  runAutoControl: <T>(fn: () => T) => T
16
20
  isAutoControl: () => boolean
17
21
  }
18
22
 
19
23
  const FormRuntimeContext = createContext<FormRuntimeContextValue | null>(null)
20
24
 
25
+ function isThenable(value: unknown): value is PromiseLike<unknown> {
26
+ return (
27
+ value != null &&
28
+ (typeof value === 'object' || typeof value === 'function') &&
29
+ typeof (value as PromiseLike<unknown>).then === 'function'
30
+ )
31
+ }
32
+
21
33
  const noopRuntime: FormRuntimeContextValue = {
22
34
  reportEvent: () => {},
23
35
  reportData: () => {},
@@ -72,11 +84,21 @@ export function FormRuntimeProvider({
72
84
 
73
85
  const runAutoControl = useCallback(<T,>(fn: () => T): T => {
74
86
  autoControlDepthRef.current += 1
87
+ let syncResult: T
75
88
  try {
76
- return fn()
77
- } finally {
89
+ syncResult = fn()
90
+ } catch (error) {
78
91
  autoControlDepthRef.current = Math.max(0, autoControlDepthRef.current - 1)
92
+ throw error
93
+ }
94
+ if (isThenable(syncResult)) {
95
+ const promise = Promise.resolve(syncResult).finally(() => {
96
+ autoControlDepthRef.current = Math.max(0, autoControlDepthRef.current - 1)
97
+ })
98
+ return promise as T
79
99
  }
100
+ autoControlDepthRef.current = Math.max(0, autoControlDepthRef.current - 1)
101
+ return syncResult
80
102
  }, [])
81
103
 
82
104
  const isAutoControl = useCallback(