@wix/zero-config-implementation 1.5.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.
Files changed (78) hide show
  1. package/README.md +72 -0
  2. package/dist/component-loader.d.ts +42 -0
  3. package/dist/component-renderer.d.ts +31 -0
  4. package/dist/converters/data-item-builder.d.ts +15 -0
  5. package/dist/converters/index.d.ts +1 -0
  6. package/dist/converters/to-editor-component.d.ts +3 -0
  7. package/dist/converters/utils.d.ts +16 -0
  8. package/dist/errors.d.ts +230 -0
  9. package/dist/index.d.ts +42 -0
  10. package/dist/index.js +51978 -0
  11. package/dist/information-extractors/css/index.d.ts +3 -0
  12. package/dist/information-extractors/css/parse.d.ts +7 -0
  13. package/dist/information-extractors/css/selector-matcher.d.ts +3 -0
  14. package/dist/information-extractors/css/types.d.ts +49 -0
  15. package/dist/information-extractors/react/extractors/core/index.d.ts +6 -0
  16. package/dist/information-extractors/react/extractors/core/runner.d.ts +19 -0
  17. package/dist/information-extractors/react/extractors/core/store.d.ts +17 -0
  18. package/dist/information-extractors/react/extractors/core/tree-builder.d.ts +15 -0
  19. package/dist/information-extractors/react/extractors/core/types.d.ts +40 -0
  20. package/dist/information-extractors/react/extractors/css-properties.d.ts +20 -0
  21. package/dist/information-extractors/react/extractors/index.d.ts +11 -0
  22. package/dist/information-extractors/react/extractors/prop-tracker.d.ts +24 -0
  23. package/dist/information-extractors/react/index.d.ts +9 -0
  24. package/dist/information-extractors/react/types.d.ts +51 -0
  25. package/dist/information-extractors/react/utils/mock-generator.d.ts +9 -0
  26. package/dist/information-extractors/react/utils/prop-spy.d.ts +10 -0
  27. package/dist/information-extractors/ts/components.d.ts +9 -0
  28. package/dist/information-extractors/ts/css-imports.d.ts +2 -0
  29. package/dist/information-extractors/ts/index.d.ts +3 -0
  30. package/dist/information-extractors/ts/types.d.ts +47 -0
  31. package/dist/information-extractors/ts/utils/semantic-type-resolver.d.ts +3 -0
  32. package/dist/jsx-runtime-interceptor.d.ts +42 -0
  33. package/dist/jsx-runtime-interceptor.js +63 -0
  34. package/dist/jsx-runtime-loader.d.ts +23 -0
  35. package/dist/jsx-runtime-loader.js +7 -0
  36. package/dist/manifest-pipeline.d.ts +33 -0
  37. package/dist/schema.d.ts +167 -0
  38. package/dist/ts-compiler.d.ts +13 -0
  39. package/package.json +81 -0
  40. package/src/component-loader.test.ts +277 -0
  41. package/src/component-loader.ts +256 -0
  42. package/src/component-renderer.ts +192 -0
  43. package/src/converters/data-item-builder.ts +354 -0
  44. package/src/converters/index.ts +1 -0
  45. package/src/converters/to-editor-component.ts +167 -0
  46. package/src/converters/utils.ts +21 -0
  47. package/src/errors.ts +103 -0
  48. package/src/index.ts +223 -0
  49. package/src/information-extractors/css/README.md +3 -0
  50. package/src/information-extractors/css/index.ts +3 -0
  51. package/src/information-extractors/css/parse.ts +450 -0
  52. package/src/information-extractors/css/selector-matcher.ts +88 -0
  53. package/src/information-extractors/css/types.ts +56 -0
  54. package/src/information-extractors/react/extractors/core/index.ts +6 -0
  55. package/src/information-extractors/react/extractors/core/runner.ts +89 -0
  56. package/src/information-extractors/react/extractors/core/store.ts +36 -0
  57. package/src/information-extractors/react/extractors/core/tree-builder.ts +273 -0
  58. package/src/information-extractors/react/extractors/core/types.ts +48 -0
  59. package/src/information-extractors/react/extractors/css-properties.ts +214 -0
  60. package/src/information-extractors/react/extractors/index.ts +27 -0
  61. package/src/information-extractors/react/extractors/prop-tracker.ts +132 -0
  62. package/src/information-extractors/react/index.ts +53 -0
  63. package/src/information-extractors/react/types.ts +70 -0
  64. package/src/information-extractors/react/utils/mock-generator.ts +331 -0
  65. package/src/information-extractors/react/utils/prop-spy.ts +168 -0
  66. package/src/information-extractors/ts/components.ts +300 -0
  67. package/src/information-extractors/ts/css-imports.ts +26 -0
  68. package/src/information-extractors/ts/index.ts +3 -0
  69. package/src/information-extractors/ts/types.ts +56 -0
  70. package/src/information-extractors/ts/utils/semantic-type-resolver.ts +377 -0
  71. package/src/jsx-runtime-interceptor.ts +146 -0
  72. package/src/jsx-runtime-loader.ts +38 -0
  73. package/src/manifest-pipeline.ts +362 -0
  74. package/src/schema.ts +174 -0
  75. package/src/ts-compiler.ts +41 -0
  76. package/tsconfig.json +17 -0
  77. package/typedoc.json +18 -0
  78. package/vite.config.ts +45 -0
@@ -0,0 +1,331 @@
1
+ /**
2
+ * Mock Value Generator - Creates mock values from PropInfo types for DOM coupling analysis
3
+ * Uses @faker-js/faker for realistic mock data generation
4
+ */
5
+
6
+ import { faker } from '@faker-js/faker'
7
+ import type { ComponentInfo, DefaultValue, PropInfo, ResolvedType } from '../../ts/types'
8
+
9
+ /**
10
+ * Reset faker's seed and internal state for reproducible results
11
+ */
12
+ export function resetMockCounter(): void {
13
+ faker.seed(42)
14
+ }
15
+
16
+ /**
17
+ * Generate mock props object from ComponentInfo
18
+ */
19
+ export function generateMockProps(componentInfo: ComponentInfo): Record<string, unknown> {
20
+ const mockProps: Record<string, unknown> = {}
21
+
22
+ for (const [propName, propInfo] of Object.entries(componentInfo.props)) {
23
+ mockProps[propName] = generateMockValue(propInfo, propName)
24
+ }
25
+
26
+ return mockProps
27
+ }
28
+
29
+ /**
30
+ * Generate a mock value based on PropInfo
31
+ */
32
+ function generateMockValue(propInfo: PropInfo, propName: string): unknown {
33
+ // If there's a default value, use it
34
+ if (propInfo.defaultValue !== undefined) {
35
+ return extractDefaultValueValue(propInfo.defaultValue)
36
+ }
37
+
38
+ return generateValueFromResolvedType(propInfo.resolvedType, propName)
39
+ }
40
+
41
+ /**
42
+ * Extract the actual value from a DefaultValue object
43
+ */
44
+ function extractDefaultValueValue(defaultValue: DefaultValue): unknown {
45
+ switch (defaultValue.kind) {
46
+ case 'string':
47
+ case 'number':
48
+ case 'boolean':
49
+ case 'null':
50
+ return defaultValue.value
51
+ case 'unresolved':
52
+ // For unresolved values, return the raw string (e.g., MY_CONST)
53
+ return defaultValue.value
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Generate a mock value from a ResolvedType
59
+ */
60
+ function generateValueFromResolvedType(resolvedType: ResolvedType, propName: string): unknown {
61
+ const kind = resolvedType.kind
62
+
63
+ // Handle semantic types (from React or Wix packages)
64
+ if (kind === 'semantic') {
65
+ return generateSemanticValue(resolvedType.value as string, propName)
66
+ }
67
+
68
+ // Handle structural types
69
+ switch (kind) {
70
+ case 'primitive':
71
+ return generatePrimitiveValue(resolvedType.value as string, propName)
72
+
73
+ case 'literal':
74
+ return resolvedType.value
75
+
76
+ case 'union':
77
+ return generateUnionValue(resolvedType, propName)
78
+
79
+ case 'intersection':
80
+ return generateIntersectionValue(resolvedType, propName)
81
+
82
+ case 'array':
83
+ return generateArrayValue(resolvedType, propName)
84
+
85
+ case 'object':
86
+ return generateObjectValue(resolvedType, propName)
87
+
88
+ case 'enum':
89
+ return generateEnumValue(resolvedType)
90
+
91
+ case 'function':
92
+ return generateMockFunction(propName)
93
+
94
+ default:
95
+ // Default to a string for unknown types
96
+ return `mock_${propName}_${faker.string.alphanumeric(6)}`
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Generate a mock value for semantic types (React or Wix types)
102
+ */
103
+ function generateSemanticValue(semanticType: string, propName: string): unknown {
104
+ switch (semanticType) {
105
+ // Wix semantic types
106
+ case 'Image':
107
+ case 'ImageUri':
108
+ return generateMockImage()
109
+ case 'Video':
110
+ case 'VideoUri':
111
+ return generateMockVideo()
112
+ case 'Link':
113
+ return generateMockLink()
114
+ case 'A11y':
115
+ return generateMockA11y()
116
+ case 'VectorArt':
117
+ return generateMockVectorArt()
118
+ case 'Audio':
119
+ case 'AudioUri':
120
+ return generateMockAudio()
121
+ case 'RichText':
122
+ return `<p>${faker.lorem.paragraph()}</p>`
123
+ case 'LocalDate':
124
+ return faker.date.recent().toISOString().split('T')[0]
125
+ case 'LocalTime':
126
+ return faker.date.recent().toISOString().split('T')[1].split('.')[0]
127
+ case 'LocalDateTime':
128
+ return faker.date.recent().toISOString().replace('Z', '')
129
+ case 'WebUrl':
130
+ return faker.internet.url()
131
+ case 'Direction':
132
+ return faker.helpers.arrayElement(['ltr', 'rtl'])
133
+ case 'MenuItems':
134
+ return generateMockMenuItems()
135
+ case 'Container':
136
+ return null // React children - typically null for testing
137
+
138
+ // React types
139
+ case 'ReactNode':
140
+ case 'ReactElement':
141
+ return null // Return null for React nodes in mock testing
142
+
143
+ case 'CSSProperties':
144
+ return {
145
+ color: faker.color.rgb(),
146
+ fontSize: faker.number.int({ min: 12, max: 24 }),
147
+ }
148
+
149
+ default:
150
+ // Default to a string for unknown semantic types
151
+ return `mock_${propName}_${faker.string.alphanumeric(6)}`
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Generate a primitive value
157
+ */
158
+ function generatePrimitiveValue(primitiveType: string, propName: string): unknown {
159
+ 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 })
164
+ case 'boolean':
165
+ return faker.datatype.boolean()
166
+ case 'null':
167
+ return null
168
+ case 'undefined':
169
+ return undefined
170
+ default:
171
+ return `mock_${propName}_${faker.string.alphanumeric(6)}`
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Generate a value from a union type (pick the first non-null option)
177
+ */
178
+ function generateUnionValue(resolvedType: ResolvedType, propName: string): unknown {
179
+ const types = resolvedType.types ?? []
180
+
181
+ // Prefer string literals for textEnum-like unions
182
+ const stringLiteral = types.find((t) => t.kind === 'literal' && typeof t.value === 'string')
183
+ if (stringLiteral) {
184
+ return stringLiteral.value
185
+ }
186
+
187
+ // Otherwise, use the first type
188
+ if (types.length > 0) {
189
+ return generateValueFromResolvedType(types[0], propName)
190
+ }
191
+
192
+ return `mock_${propName}_${faker.string.alphanumeric(6)}`
193
+ }
194
+
195
+ /**
196
+ * Generate a value from an intersection type (merge object properties)
197
+ */
198
+ function generateIntersectionValue(resolvedType: ResolvedType, propName: string): unknown {
199
+ const types = resolvedType.types ?? []
200
+ const merged: Record<string, unknown> = {}
201
+
202
+ for (const type of types) {
203
+ if (type.kind === 'object' && type.properties) {
204
+ for (const [key, propInfo] of Object.entries(type.properties)) {
205
+ merged[key] = generateMockValue(propInfo, `${propName}.${key}`)
206
+ }
207
+ }
208
+ }
209
+
210
+ return Object.keys(merged).length > 0 ? merged : `mock_${propName}_${faker.string.alphanumeric(6)}`
211
+ }
212
+
213
+ /**
214
+ * Generate an array value
215
+ */
216
+ function generateArrayValue(resolvedType: ResolvedType, propName: string): unknown[] {
217
+ const elementType = resolvedType.elementType
218
+
219
+ if (!elementType) {
220
+ return [`mock_${propName}[0]_${faker.string.alphanumeric(6)}`]
221
+ }
222
+
223
+ // Generate 2-3 items for the array
224
+ return [
225
+ generateValueFromResolvedType(elementType, `${propName}[0]`),
226
+ generateValueFromResolvedType(elementType, `${propName}[1]`),
227
+ ]
228
+ }
229
+
230
+ /**
231
+ * Generate an object value from properties
232
+ */
233
+ function generateObjectValue(resolvedType: ResolvedType, propName: string): Record<string, unknown> {
234
+ const properties = resolvedType.properties ?? {}
235
+ const obj: Record<string, unknown> = {}
236
+
237
+ for (const [key, propInfo] of Object.entries(properties)) {
238
+ obj[key] = generateMockValue(propInfo, `${propName}.${key}`)
239
+ }
240
+
241
+ return obj
242
+ }
243
+
244
+ /**
245
+ * Generate an enum value (pick the first option)
246
+ */
247
+ function generateEnumValue(resolvedType: ResolvedType): unknown {
248
+ const types = resolvedType.types ?? []
249
+ const firstLiteral = types.find((t) => t.kind === 'literal')
250
+
251
+ if (firstLiteral) {
252
+ return firstLiteral.value
253
+ }
254
+
255
+ return 'default'
256
+ }
257
+
258
+ /**
259
+ * Generate a mock function
260
+ */
261
+ function generateMockFunction(propName: string): (...args: unknown[]) => void {
262
+ const fn = function mockFn(): void {
263
+ // No-op mock function
264
+ }
265
+ Object.defineProperty(fn, 'name', { value: `mock_${propName}` })
266
+ return fn
267
+ }
268
+
269
+ // ─────────────────────────────────────────────────────────────────────────────
270
+ // Wix Semantic Type Generators (built from faker primitives)
271
+ // ─────────────────────────────────────────────────────────────────────────────
272
+
273
+ function generateMockImage(): Record<string, unknown> {
274
+ return {
275
+ uri: faker.system.fileName({ extensionCount: 1 }),
276
+ url: faker.image.url(),
277
+ width: faker.number.int({ min: 100, max: 1920 }),
278
+ height: faker.number.int({ min: 100, max: 1080 }),
279
+ name: faker.lorem.words(2),
280
+ alt: faker.lorem.sentence(),
281
+ }
282
+ }
283
+
284
+ function generateMockVideo(): Record<string, unknown> {
285
+ return {
286
+ url: `${faker.internet.url()}/video.mp4`,
287
+ width: faker.number.int({ min: 640, max: 1920 }),
288
+ height: faker.number.int({ min: 480, max: 1080 }),
289
+ duration: faker.number.int({ min: 10, max: 300 }),
290
+ name: faker.lorem.words(2),
291
+ }
292
+ }
293
+
294
+ function generateMockLink(): Record<string, unknown> {
295
+ return {
296
+ href: faker.internet.url(),
297
+ target: faker.helpers.arrayElement(['_blank', '_self']),
298
+ rel: 'noopener noreferrer',
299
+ }
300
+ }
301
+
302
+ function generateMockA11y(): Record<string, unknown> {
303
+ return {
304
+ ariaLabel: faker.lorem.sentence(),
305
+ role: faker.helpers.arrayElement(['button', 'link', 'img', 'region']),
306
+ tabIndex: faker.helpers.arrayElement([0, -1]),
307
+ }
308
+ }
309
+
310
+ function generateMockVectorArt(): Record<string, unknown> {
311
+ return {
312
+ svgId: faker.string.uuid(),
313
+ url: `${faker.internet.url()}/icon.svg`,
314
+ }
315
+ }
316
+
317
+ function generateMockAudio(): Record<string, unknown> {
318
+ return {
319
+ url: `${faker.internet.url()}/audio.mp3`,
320
+ duration: faker.number.int({ min: 30, max: 600 }),
321
+ name: faker.music.songName(),
322
+ }
323
+ }
324
+
325
+ function generateMockMenuItems(): unknown[] {
326
+ return Array.from({ length: faker.number.int({ min: 2, max: 5 }) }, () => ({
327
+ id: faker.string.uuid(),
328
+ label: faker.lorem.words(2),
329
+ link: generateMockLink(),
330
+ }))
331
+ }
@@ -0,0 +1,168 @@
1
+ import type { PropSpy, PropSpyMeta, TrackingStores } from '../types'
2
+ import { PROP_SPY_SYMBOL } from '../types'
3
+
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ // Types
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+
8
+ export interface PropSpyContext {
9
+ createAuditedProps: <T extends object | null>(
10
+ target: T,
11
+ stores: TrackingStores,
12
+ getComponent: () => string,
13
+ basePath?: string,
14
+ ) => T
15
+ getSpyMetadataByUniqueId: (id: string) => PropSpyMeta | null
16
+ }
17
+
18
+ // ─────────────────────────────────────────────────────────────────────────────
19
+ // Factory
20
+ // ─────────────────────────────────────────────────────────────────────────────
21
+
22
+ /**
23
+ * Creates an encapsulated prop spy context.
24
+ * Each context has its own ID counter and metadata map, avoiding global state.
25
+ */
26
+ export function createPropSpyContext(): PropSpyContext {
27
+ let idCounter = 0
28
+ const metadataMap = new Map<string, PropSpyMeta>()
29
+
30
+ // ─────────────────────────────────────────────────────────────────────────────
31
+ // Helpers
32
+ // ─────────────────────────────────────────────────────────────────────────────
33
+
34
+ const isPropSpy = (val: unknown): val is PropSpy => !!(val && typeof val === 'object' && PROP_SPY_SYMBOL in val)
35
+
36
+ const isReactInternal = (val: unknown): boolean => {
37
+ if (!val || typeof val !== 'object') return false
38
+ const obj = val as Record<string, unknown>
39
+ return !!(obj.$$typeof || obj._owner || obj._store || (obj.prototype as Record<string, unknown>)?.isReactComponent)
40
+ }
41
+
42
+ const logRead = (stores: TrackingStores, path: string, component: string, value: unknown) => {
43
+ const record = stores.reads.get(path) ?? { components: new Set(), value }
44
+ record.components.add(component)
45
+ stores.reads.set(path, record)
46
+ }
47
+
48
+ const createMeta = (
49
+ path: string,
50
+ propName: string,
51
+ originalValue: unknown,
52
+ ): { meta: PropSpyMeta; uniqueId: string } => {
53
+ const uniqueId = `__spy_${++idCounter}__`
54
+ const meta = { path, propName, uniqueId, originalValue }
55
+ return { meta, uniqueId }
56
+ }
57
+
58
+ // ─────────────────────────────────────────────────────────────────────────────
59
+ // Primitive Wrapping
60
+ // ─────────────────────────────────────────────────────────────────────────────
61
+
62
+ const wrapPrimitiveOrFunction = (
63
+ value: string | number | boolean | ((...args: unknown[]) => unknown),
64
+ path: string,
65
+ propName: string,
66
+ stores: TrackingStores,
67
+ getComponent: () => string,
68
+ ) => {
69
+ // Functions: Wrap to log execution
70
+ if (typeof value === 'function') {
71
+ const spy = function (this: unknown, ...args: unknown[]) {
72
+ logRead(stores, path, getComponent(), value)
73
+ return value.apply(this, args)
74
+ }
75
+ Object.defineProperties(spy, {
76
+ name: { value: value.name || propName },
77
+ length: { value: value.length },
78
+ })
79
+ return spy
80
+ }
81
+
82
+ const { meta, uniqueId } = createMeta(path, propName, value)
83
+
84
+ // Strings: Embed markers
85
+ if (typeof value === 'string') {
86
+ metadataMap.set(uniqueId, meta)
87
+ return `${uniqueId}${value}${uniqueId}`
88
+ }
89
+
90
+ // Numbers/Booleans: Wrapper Objects
91
+ // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
92
+ type SpyWrapper = (number | boolean) & { [PROP_SPY_SYMBOL]?: boolean; __meta?: PropSpyMeta }
93
+ let spy: SpyWrapper | undefined
94
+ if (typeof value === 'number') spy = new Number(value) as SpyWrapper
95
+ if (typeof value === 'boolean') spy = new Boolean(value) as SpyWrapper
96
+
97
+ if (spy) {
98
+ spy[PROP_SPY_SYMBOL] = true
99
+ spy.__meta = meta
100
+ return spy
101
+ }
102
+
103
+ return value
104
+ }
105
+
106
+ // ─────────────────────────────────────────────────────────────────────────────
107
+ // Core Logic
108
+ // ─────────────────────────────────────────────────────────────────────────────
109
+
110
+ const createAuditedProps = <T extends object | null>(
111
+ target: T,
112
+ stores: TrackingStores,
113
+ getComponent: () => string,
114
+ basePath = 'props',
115
+ ): T => {
116
+ if (!target || typeof target !== 'object' || isPropSpy(target)) return target
117
+
118
+ return new Proxy(target, {
119
+ get(obj, prop, receiver) {
120
+ const value = Reflect.get(obj, prop, receiver)
121
+ const propKey = String(prop)
122
+
123
+ // Ignore symbols and known React internal properties
124
+ if (typeof prop === 'symbol' || propKey === '$$typeof' || propKey.startsWith('_')) {
125
+ return value
126
+ }
127
+
128
+ const path = Array.isArray(target) ? `${basePath}[${propKey}]` : `${basePath}.${propKey}`
129
+ const component = getComponent()
130
+
131
+ // 1. Handle React internals or nulls (Log but don't wrap)
132
+ if (value == null || isReactInternal(value)) {
133
+ logRead(stores, path, component, value)
134
+ return value
135
+ }
136
+
137
+ // 2. Handle Primitives & Functions (Wrap & Log)
138
+ if (typeof value !== 'object' || typeof value === 'function') {
139
+ const wrapped = wrapPrimitiveOrFunction(
140
+ value as string | number | boolean | ((...args: unknown[]) => unknown),
141
+ path,
142
+ propKey,
143
+ stores,
144
+ getComponent,
145
+ )
146
+ logRead(stores, path, component, wrapped)
147
+ return wrapped
148
+ }
149
+
150
+ // 3. Handle Objects/Arrays (Recurse Proxy & Log)
151
+ const audited = createAuditedProps(value, stores, getComponent, path)
152
+ logRead(stores, path, component, audited)
153
+ return audited
154
+ },
155
+ ownKeys: (obj) => Reflect.ownKeys(obj),
156
+ getOwnPropertyDescriptor: (obj, prop) => Reflect.getOwnPropertyDescriptor(obj, prop),
157
+ })
158
+ }
159
+
160
+ const getSpyMetadataByUniqueId = (id: string): PropSpyMeta | null => {
161
+ return metadataMap.get(id) ?? null
162
+ }
163
+
164
+ return {
165
+ createAuditedProps,
166
+ getSpyMetadataByUniqueId,
167
+ }
168
+ }