@wix/zero-config-implementation 1.8.0 → 1.10.0

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,17 +8,13 @@
8
8
  import type { HTMLAttributes } from 'react'
9
9
  import { TRACE_ATTR } from '../../../component-renderer'
10
10
  import type { PropSpyMeta, TrackingStores } from '../types'
11
- import { type PropSpyContext, createPropSpyContext } from '../utils/prop-spy'
11
+ import { type PropSpyRegistrar, generateMockProps, resetMockCounter } from '../utils/mock-generator'
12
12
  import type { CreateElementEvent, ReactExtractor, RenderContext } from './core/types'
13
13
 
14
14
  // ─────────────────────────────────────────────────────────────────────────────
15
15
  // Types
16
16
  // ─────────────────────────────────────────────────────────────────────────────
17
17
 
18
- const SPY_REGEX = /__spy_\d+__/g
19
-
20
- export type GetSpyMetadataFn = (id: string) => PropSpyMeta | null
21
-
22
18
  export interface PropTrackerData {
23
19
  tag: string
24
20
  role?: string
@@ -28,7 +24,6 @@ export interface PropTrackerData {
28
24
 
29
25
  export interface PropTrackerExtractorState {
30
26
  stores: TrackingStores
31
- spyContext: PropSpyContext
32
27
  }
33
28
 
34
29
  // ─────────────────────────────────────────────────────────────────────────────
@@ -37,28 +32,54 @@ export interface PropTrackerExtractorState {
37
32
 
38
33
  /**
39
34
  * Creates a prop tracker extractor that:
40
- * 1. Wraps props with spy proxies during beforeRender
35
+ * 1. Generates spy-instrumented mock props during beforeRender
41
36
  * 2. Detects spy markers in element props during onCreateElement
42
- * 3. Writes tracking data to the store namespaced by 'prop-tracker'
37
+ * 3. propUsages tracking data to the store namespaced by 'prop-tracker'
43
38
  */
44
39
  export function createPropTrackerExtractor(): {
45
40
  extractor: ReactExtractor
46
41
  state: PropTrackerExtractorState
47
42
  } {
48
- const spyContext = createPropSpyContext()
43
+ const stringMeta = new Map<string, PropSpyMeta>()
44
+ const numberMeta = new Map<number, PropSpyMeta>()
45
+ const fnMeta = new WeakMap<(...args: unknown[]) => unknown, PropSpyMeta>()
49
46
  const stores: TrackingStores = {
50
- reads: new Map(),
51
- writes: new Map(),
47
+ propUsages: new Map(),
48
+ }
49
+
50
+ const registrar: PropSpyRegistrar = {
51
+ registerString(path, propName, value) {
52
+ stringMeta.set(value, { path, propName, originalValue: value })
53
+ },
54
+ registerNumber(path, propName, value) {
55
+ numberMeta.set(value, { path, propName, originalValue: value })
56
+ },
57
+ registerFunction(path, propName, value) {
58
+ fnMeta.set(value, { path, propName, originalValue: value })
59
+ },
52
60
  }
53
61
 
54
- const extractSpies = (value: unknown, seen = new WeakSet<object>()): { propName: string; path: string }[] => {
62
+ const extractSpies = (
63
+ value: unknown,
64
+ seen = new WeakSet<object>(),
65
+ ): { propName: string; path: string; embedded: boolean }[] => {
55
66
  if (typeof value === 'string') {
56
- return (value.match(SPY_REGEX) ?? [])
57
- .map((id) => {
58
- const meta = spyContext.getSpyMetadataByUniqueId(id)
59
- return meta ? { propName: meta.propName, path: meta.path } : null
60
- })
61
- .filter(Boolean) as { propName: string; path: string }[]
67
+ const results: { propName: string; path: string; embedded: boolean }[] = []
68
+ for (const [key, meta] of stringMeta) {
69
+ if (value.includes(key)) {
70
+ // embedded = spy marker was part of a longer string (e.g. `mailto:${email}`)
71
+ results.push({ propName: meta.propName, path: meta.path, embedded: value !== key })
72
+ }
73
+ }
74
+ return results
75
+ }
76
+ if (typeof value === 'number') {
77
+ const meta = numberMeta.get(value)
78
+ return meta ? [{ propName: meta.propName, path: meta.path, embedded: false }] : []
79
+ }
80
+ if (typeof value === 'function') {
81
+ const meta = fnMeta.get(value as (...args: unknown[]) => unknown)
82
+ return meta ? [{ propName: meta.propName, path: meta.path, embedded: false }] : []
62
83
  }
63
84
  if (value && typeof value === 'object') {
64
85
  // Prevent infinite recursion from circular references
@@ -79,8 +100,8 @@ export function createPropTrackerExtractor(): {
79
100
  name: 'prop-tracker',
80
101
 
81
102
  onBeforeRender(context: RenderContext): void {
82
- // Wrap props with spy proxies to track access
83
- context.props = spyContext.createAuditedProps(context.props, stores, () => context.componentInfo.componentName)
103
+ resetMockCounter()
104
+ context.props = generateMockProps(context.componentInfo, registrar)
84
105
  },
85
106
 
86
107
  onCreateElement(event: CreateElementEvent): void {
@@ -97,18 +118,18 @@ export function createPropTrackerExtractor(): {
97
118
 
98
119
  spies.forEach((spy) => {
99
120
  boundProps.add(spy.propName)
100
- const path = spy.path
101
- const entry = stores.writes.get(path) ?? { elements: new Map(), attributes: new Map() }
102
-
103
- if (!stores.writes.has(path)) {
104
- stores.writes.set(path, entry)
121
+ const path = spy.path.replace(/\[\d+\]/g, '')
122
+ if (!stores.propUsages.has(path)) {
123
+ stores.propUsages.set(path, { elements: new Map(), attributes: new Map() })
105
124
  }
125
+ const entry = stores.propUsages.get(path)!
106
126
 
107
127
  entry.elements.set(traceId, { tag, elementId: traceId })
108
- entry.attributes.set(`${traceId}:${key}`, { attr: key, concatenated: spies.length > 1 })
128
+ const isConcat = spies.length > 1 || spy.embedded
129
+ entry.attributes.set(`${traceId}:${key}`, { attr: key, concatenated: isConcat })
109
130
 
110
131
  // Track concatenated attributes
111
- if (spies.length > 1) {
132
+ if (isConcat) {
112
133
  concatenatedAttrs.set(key, spy.propName)
113
134
  }
114
135
  })
@@ -127,6 +148,6 @@ export function createPropTrackerExtractor(): {
127
148
 
128
149
  return {
129
150
  extractor,
130
- state: { stores, spyContext },
151
+ state: { stores },
131
152
  }
132
153
  }
@@ -42,13 +42,6 @@ export type {
42
42
  CoupledProp,
43
43
  TrackingStores,
44
44
  DOMBinding,
45
- PropReadInfo,
46
45
  PropWriteInfo,
47
46
  PropSpyMeta,
48
47
  } from './types'
49
-
50
- // ─────────────────────────────────────────────────────────────────────────────
51
- // Utility Exports
52
- // ─────────────────────────────────────────────────────────────────────────────
53
-
54
- export type { PropSpyContext } from './utils/prop-spy'
@@ -9,41 +9,23 @@ import type { ExtractedElement } from './extractors/core/tree-builder'
9
9
  // Prop Spy (for tracking prop access)
10
10
  // ─────────────────────────────────────────────────────────────────────────────
11
11
 
12
- export const PROP_SPY_SYMBOL = Symbol.for('__prop_spy__')
13
-
14
12
  export interface PropSpyMeta {
15
13
  path: string
16
14
  propName: string
17
- uniqueId: string
18
15
  originalValue: unknown
19
16
  }
20
17
 
21
- export interface PropSpy<T = unknown> {
22
- [PROP_SPY_SYMBOL]: true
23
- __meta: PropSpyMeta
24
- valueOf: () => T
25
- toString: () => string
26
- toJSON: () => T
27
- [Symbol.toPrimitive]?: (hint: string) => T | string | number
28
- }
29
-
30
18
  // ─────────────────────────────────────────────────────────────────────────────
31
19
  // Tracking Stores
32
20
  // ─────────────────────────────────────────────────────────────────────────────
33
21
 
34
- export interface PropReadInfo {
35
- components: Set<string>
36
- value: unknown
37
- }
38
-
39
22
  export interface PropWriteInfo {
40
23
  elements: Map<string, { tag: string; elementId: string }>
41
24
  attributes: Map<string, { attr: string; concatenated: boolean }>
42
25
  }
43
26
 
44
27
  export interface TrackingStores {
45
- reads: Map<string, PropReadInfo>
46
- writes: Map<string, PropWriteInfo>
28
+ propUsages: Map<string, PropWriteInfo>
47
29
  }
48
30
 
49
31
  // ─────────────────────────────────────────────────────────────────────────────
@@ -58,7 +40,8 @@ export interface DOMBinding {
58
40
  }
59
41
 
60
42
  export interface CoupledProp extends PropInfo {
61
- bindings: DOMBinding[]
43
+ /** Full stores.propUsages key for this prop, e.g. "props.linkUrl". */
44
+ propPath: string
62
45
  logicOnly: boolean
63
46
  }
64
47
 
@@ -67,4 +50,5 @@ export interface CoupledComponentInfo {
67
50
  props: Record<string, CoupledProp>
68
51
  elements: ExtractedElement[]
69
52
  innerElementProps?: Map<string, Record<string, CoupledProp>>
53
+ propUsages: TrackingStores['propUsages']
70
54
  }
@@ -6,21 +6,57 @@
6
6
  import { faker } from '@faker-js/faker'
7
7
  import type { ComponentInfo, DefaultValue, PropInfo, ResolvedType } from '../../ts/types'
8
8
 
9
+ export const PRESETS_WRAPPER_CLASS_NAME = 'mock-presets-wrapper-probe'
10
+
11
+ // Unique primes used as traceable number values. Each rendered number prop gets
12
+ // one; the value is distinct enough to be identified in DOM attributes later.
13
+ const TRACEABLE_PRIMES = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
14
+ const FALLBACK_NUMBER_BASE = 101
15
+ let primeIndex = 0
16
+
17
+ function nextTraceableNumber(): number {
18
+ const withinPrimeList = primeIndex < TRACEABLE_PRIMES.length
19
+ if (withinPrimeList) {
20
+ return TRACEABLE_PRIMES[primeIndex++]
21
+ }
22
+ const overflowOffset = primeIndex++ - TRACEABLE_PRIMES.length
23
+ return FALLBACK_NUMBER_BASE + overflowOffset
24
+ }
25
+
9
26
  /**
10
27
  * Reset faker's seed and internal state for reproducible results
11
28
  */
12
29
  export function resetMockCounter(): void {
13
30
  faker.seed(42)
31
+ primeIndex = 0
32
+ }
33
+
34
+ /**
35
+ * Narrow interface for registering spy markers during mock generation.
36
+ * Satisfied structurally by PropSpyContext.
37
+ */
38
+ export interface PropSpyRegistrar {
39
+ registerString(path: string, propName: string, value: string): void
40
+ registerNumber(path: string, propName: string, value: number): void
41
+ registerFunction(path: string, propName: string, value: (...args: unknown[]) => unknown): void
14
42
  }
15
43
 
16
44
  /**
17
- * Generate mock props object from ComponentInfo
45
+ * Generate mock props object from ComponentInfo.
46
+ * When a registrar is provided, string and number values are spy-instrumented
47
+ * for DOM binding detection.
18
48
  */
19
- export function generateMockProps(componentInfo: ComponentInfo): Record<string, unknown> {
49
+ export function generateMockProps(componentInfo: ComponentInfo, registrar?: PropSpyRegistrar): Record<string, unknown> {
20
50
  const mockProps: Record<string, unknown> = {}
21
51
 
22
52
  for (const [propName, propInfo] of Object.entries(componentInfo.props)) {
23
- mockProps[propName] = generateMockValue(propInfo, propName)
53
+ mockProps[propName] = generateMockValue(propInfo, propName, `props.${propName}`, registrar)
54
+ }
55
+
56
+ // Always inject wix renderer object; components that don't use it will ignore it
57
+ mockProps.wix = {
58
+ elementsRemovalState: {},
59
+ presetsWrapperProps: { className: PRESETS_WRAPPER_CLASS_NAME },
24
60
  }
25
61
 
26
62
  return mockProps
@@ -29,13 +65,13 @@ export function generateMockProps(componentInfo: ComponentInfo): Record<string,
29
65
  /**
30
66
  * Generate a mock value based on PropInfo
31
67
  */
32
- function generateMockValue(propInfo: PropInfo, propName: string): unknown {
33
- // If there's a default value, use it
34
- if (propInfo.defaultValue !== undefined) {
68
+ function generateMockValue(propInfo: PropInfo, propName: string, path: string, registrar?: PropSpyRegistrar): unknown {
69
+ // In plain mode (no registrar), honour default values for realistic rendering
70
+ if (!registrar && propInfo.defaultValue !== undefined) {
35
71
  return extractDefaultValueValue(propInfo.defaultValue)
36
72
  }
37
73
 
38
- return generateValueFromResolvedType(propInfo.resolvedType, propName)
74
+ return generateValueFromResolvedType(propInfo.resolvedType, propName, path, registrar)
39
75
  }
40
76
 
41
77
  /**
@@ -57,10 +93,15 @@ function extractDefaultValueValue(defaultValue: DefaultValue): unknown {
57
93
  /**
58
94
  * Generate a mock value from a ResolvedType
59
95
  */
60
- function generateValueFromResolvedType(resolvedType: ResolvedType, propName: string): unknown {
96
+ function generateValueFromResolvedType(
97
+ resolvedType: ResolvedType,
98
+ propName: string,
99
+ path: string,
100
+ registrar?: PropSpyRegistrar,
101
+ ): unknown {
61
102
  const kind = resolvedType.kind
62
103
 
63
- // Handle semantic types (from React or Wix packages)
104
+ // Handle semantic types (from React or Wix packages) — returned as plain objects
64
105
  if (kind === 'semantic') {
65
106
  return generateSemanticValue(resolvedType.value as string, propName)
66
107
  }
@@ -68,28 +109,28 @@ function generateValueFromResolvedType(resolvedType: ResolvedType, propName: str
68
109
  // Handle structural types
69
110
  switch (kind) {
70
111
  case 'primitive':
71
- return generatePrimitiveValue(resolvedType.value as string, propName)
112
+ return generatePrimitiveValue(resolvedType.value as string, propName, path, registrar)
72
113
 
73
114
  case 'literal':
74
115
  return resolvedType.value
75
116
 
76
117
  case 'union':
77
- return generateUnionValue(resolvedType, propName)
118
+ return generateUnionValue(resolvedType, propName, path, registrar)
78
119
 
79
120
  case 'intersection':
80
- return generateIntersectionValue(resolvedType, propName)
121
+ return generateIntersectionValue(resolvedType, propName, path, registrar)
81
122
 
82
123
  case 'array':
83
- return generateArrayValue(resolvedType, propName)
124
+ return generateArrayValue(resolvedType, propName, path, registrar)
84
125
 
85
126
  case 'object':
86
- return generateObjectValue(resolvedType, propName)
127
+ return generateObjectValue(resolvedType, propName, path, registrar)
87
128
 
88
129
  case 'enum':
89
130
  return generateEnumValue(resolvedType)
90
131
 
91
132
  case 'function':
92
- return generateMockFunction(propName)
133
+ return generateMockFunction(propName, path, registrar)
93
134
 
94
135
  default:
95
136
  // Default to a string for unknown types
@@ -155,12 +196,23 @@ function generateSemanticValue(semanticType: string, propName: string): unknown
155
196
  /**
156
197
  * Generate a primitive value
157
198
  */
158
- function generatePrimitiveValue(primitiveType: string, propName: string): unknown {
199
+ function generatePrimitiveValue(
200
+ primitiveType: string,
201
+ propName: string,
202
+ path: string,
203
+ registrar?: PropSpyRegistrar,
204
+ ): unknown {
159
205
  switch (primitiveType) {
160
- case 'string':
161
- return `mock_${propName}_${faker.string.alphanumeric(6)}`
162
- case 'number':
163
- return faker.number.int({ min: 1, max: 100 })
206
+ case 'string': {
207
+ const raw = `mock_${propName}_${faker.string.alphanumeric(6)}`
208
+ if (registrar) registrar.registerString(path, propName, raw)
209
+ return raw
210
+ }
211
+ case 'number': {
212
+ const val = nextTraceableNumber()
213
+ if (registrar) registrar.registerNumber(path, propName, val)
214
+ return val
215
+ }
164
216
  case 'boolean':
165
217
  return faker.datatype.boolean()
166
218
  case 'null':
@@ -175,7 +227,12 @@ function generatePrimitiveValue(primitiveType: string, propName: string): unknow
175
227
  /**
176
228
  * Generate a value from a union type (pick the first non-null option)
177
229
  */
178
- function generateUnionValue(resolvedType: ResolvedType, propName: string): unknown {
230
+ function generateUnionValue(
231
+ resolvedType: ResolvedType,
232
+ propName: string,
233
+ path: string,
234
+ registrar?: PropSpyRegistrar,
235
+ ): unknown {
179
236
  const types = resolvedType.types ?? []
180
237
 
181
238
  // Prefer string literals for textEnum-like unions
@@ -186,7 +243,7 @@ function generateUnionValue(resolvedType: ResolvedType, propName: string): unkno
186
243
 
187
244
  // Otherwise, use the first type
188
245
  if (types.length > 0) {
189
- return generateValueFromResolvedType(types[0], propName)
246
+ return generateValueFromResolvedType(types[0], propName, path, registrar)
190
247
  }
191
248
 
192
249
  return `mock_${propName}_${faker.string.alphanumeric(6)}`
@@ -195,14 +252,19 @@ function generateUnionValue(resolvedType: ResolvedType, propName: string): unkno
195
252
  /**
196
253
  * Generate a value from an intersection type (merge object properties)
197
254
  */
198
- function generateIntersectionValue(resolvedType: ResolvedType, propName: string): unknown {
255
+ function generateIntersectionValue(
256
+ resolvedType: ResolvedType,
257
+ propName: string,
258
+ path: string,
259
+ registrar?: PropSpyRegistrar,
260
+ ): unknown {
199
261
  const types = resolvedType.types ?? []
200
262
  const merged: Record<string, unknown> = {}
201
263
 
202
264
  for (const type of types) {
203
265
  if (type.kind === 'object' && type.properties) {
204
266
  for (const [key, propInfo] of Object.entries(type.properties)) {
205
- merged[key] = generateMockValue(propInfo, `${propName}.${key}`)
267
+ merged[key] = generateMockValue(propInfo, `${propName}.${key}`, `${path}.${key}`, registrar)
206
268
  }
207
269
  }
208
270
  }
@@ -213,29 +275,38 @@ function generateIntersectionValue(resolvedType: ResolvedType, propName: string)
213
275
  /**
214
276
  * Generate an array value
215
277
  */
216
- function generateArrayValue(resolvedType: ResolvedType, propName: string): unknown[] {
278
+ function generateArrayValue(
279
+ resolvedType: ResolvedType,
280
+ propName: string,
281
+ path: string,
282
+ registrar?: PropSpyRegistrar,
283
+ ): unknown[] {
217
284
  const elementType = resolvedType.elementType
218
285
 
219
286
  if (!elementType) {
220
287
  return [`mock_${propName}[0]_${faker.string.alphanumeric(6)}`]
221
288
  }
222
289
 
223
- // Generate 2-3 items for the array
224
290
  return [
225
- generateValueFromResolvedType(elementType, `${propName}[0]`),
226
- generateValueFromResolvedType(elementType, `${propName}[1]`),
291
+ generateValueFromResolvedType(elementType, `${propName}[0]`, `${path}[0]`, registrar),
292
+ generateValueFromResolvedType(elementType, `${propName}[1]`, `${path}[1]`, registrar),
227
293
  ]
228
294
  }
229
295
 
230
296
  /**
231
297
  * Generate an object value from properties
232
298
  */
233
- function generateObjectValue(resolvedType: ResolvedType, propName: string): Record<string, unknown> {
299
+ function generateObjectValue(
300
+ resolvedType: ResolvedType,
301
+ propName: string,
302
+ path: string,
303
+ registrar?: PropSpyRegistrar,
304
+ ): Record<string, unknown> {
234
305
  const properties = resolvedType.properties ?? {}
235
306
  const obj: Record<string, unknown> = {}
236
307
 
237
308
  for (const [key, propInfo] of Object.entries(properties)) {
238
- obj[key] = generateMockValue(propInfo, `${propName}.${key}`)
309
+ obj[key] = generateMockValue(propInfo, key, `${path}.${key}`, registrar)
239
310
  }
240
311
 
241
312
  return obj
@@ -258,11 +329,16 @@ function generateEnumValue(resolvedType: ResolvedType): unknown {
258
329
  /**
259
330
  * Generate a mock function
260
331
  */
261
- function generateMockFunction(propName: string): (...args: unknown[]) => void {
332
+ function generateMockFunction(
333
+ propName: string,
334
+ path: string,
335
+ registrar?: PropSpyRegistrar,
336
+ ): (...args: unknown[]) => void {
262
337
  const fn = function mockFn(): void {
263
338
  // No-op mock function
264
339
  }
265
340
  Object.defineProperty(fn, 'name', { value: `mock_${propName}` })
341
+ if (registrar) registrar.registerFunction(path, propName, fn)
266
342
  return fn
267
343
  }
268
344
 
@@ -109,6 +109,7 @@ export function processComponent(
109
109
  props: coupledProps,
110
110
  elements: convertElements(extractedElements),
111
111
  innerElementProps: innerElementProps.size > 0 ? innerElementProps : undefined,
112
+ propUsages: state.stores.propUsages,
112
113
  }
113
114
  } catch (error) {
114
115
  warnings.push({
@@ -128,9 +129,13 @@ export function processComponent(
128
129
  enhancedInfo = {
129
130
  componentName: componentInfo.componentName,
130
131
  props: Object.fromEntries(
131
- Object.entries(componentInfo.props).map(([name, info]) => [name, { ...info, bindings: [], logicOnly: false }]),
132
+ Object.entries(componentInfo.props).map(([name, info]) => [
133
+ name,
134
+ { ...info, logicOnly: false, propPath: `props.${name}` },
135
+ ]),
132
136
  ),
133
137
  elements: [],
138
+ propUsages: new Map(),
134
139
  }
135
140
  }
136
141
 
@@ -175,14 +180,12 @@ function buildCoupledProps(
175
180
  const result: Record<string, CoupledProp> = {}
176
181
 
177
182
  for (const [name, info] of Object.entries(componentInfo.props)) {
178
- const path = `props.${name}`
179
- const wasRead = stores.reads.has(path)
180
- const writeInfo = stores.writes.get(path)
183
+ const topLevelWriteInfo = stores.propUsages.get(`props.${name}`)
181
184
 
182
185
  result[name] = {
183
186
  ...info,
184
- logicOnly: wasRead && !writeInfo,
185
- bindings: writeInfo ? extractBindings(writeInfo) : [],
187
+ logicOnly: !topLevelWriteInfo,
188
+ propPath: `props.${name}`,
186
189
  }
187
190
  }
188
191
 
@@ -194,7 +197,7 @@ function buildCoupledProps(
194
197
  const ELEMENT_PROPS_PREFIX = 'props.elementProps.'
195
198
 
196
199
  /**
197
- * Processes stores.writes entries with paths starting with "props.elementProps."
200
+ * Processes stores.propUsages entries with paths starting with "props.elementProps."
198
201
  * to extract inner element prop bindings grouped by elementId (traceId).
199
202
  */
200
203
  function processElementPropsWrites(
@@ -206,7 +209,7 @@ function processElementPropsWrites(
206
209
  const elementPropsInfo = componentInfo.props.elementProps
207
210
  if (!elementPropsInfo) return result
208
211
 
209
- for (const [path, writeInfo] of stores.writes) {
212
+ for (const [path, writeInfo] of stores.propUsages) {
210
213
  if (!path.startsWith(ELEMENT_PROPS_PREFIX)) continue
211
214
 
212
215
  // Resolve the PropInfo for this leaf prop by walking the type tree
@@ -230,10 +233,9 @@ function processElementPropsWrites(
230
233
  propsForElement[leafName] = {
231
234
  ...propInfo,
232
235
  logicOnly: false,
233
- bindings: [],
236
+ propPath: path,
234
237
  }
235
238
  }
236
- propsForElement[leafName].bindings.push(binding)
237
239
  }
238
240
  }
239
241
 
@@ -268,7 +270,9 @@ function resolveInnerPropInfo(elementPropsPropInfo: PropInfo, relativePath: stri
268
270
  return null
269
271
  }
270
272
 
271
- function extractBindings(writeInfo: TrackingStores['writes'] extends Map<string, infer V> ? V : never): DOMBinding[] {
273
+ function extractBindings(
274
+ writeInfo: TrackingStores['propUsages'] extends Map<string, infer V> ? V : never,
275
+ ): DOMBinding[] {
272
276
  const bindings: DOMBinding[] = []
273
277
 
274
278
  for (const [key, attrInfo] of writeInfo.attributes) {
@@ -1,10 +0,0 @@
1
- import { PropSpyMeta, TrackingStores } from '../types';
2
- export interface PropSpyContext {
3
- createAuditedProps: <T extends object | null>(target: T, stores: TrackingStores, getComponent: () => string, basePath?: string) => T;
4
- getSpyMetadataByUniqueId: (id: string) => PropSpyMeta | null;
5
- }
6
- /**
7
- * Creates an encapsulated prop spy context.
8
- * Each context has its own ID counter and metadata map, avoiding global state.
9
- */
10
- export declare function createPropSpyContext(): PropSpyContext;