@genesislcap/ts-builder 14.431.0 → 14.432.1-FUI-2489.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;yBAIrC,KAAK,YAAY;AAAvC,wBAoDE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;yBAIrC,KAAK,YAAY;AAAvC,wBAsDE"}
@@ -1 +1 @@
1
- {"version":3,"file":"react-wrapper-generator.d.ts","sourceRoot":"","sources":["../src/react-wrapper-generator.ts"],"names":[],"mappings":"AAyCA,KAAK,cAAc,GACf;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,SAAS,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAswBzC,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAqChF"}
1
+ {"version":3,"file":"react-wrapper-generator.d.ts","sourceRoot":"","sources":["../src/react-wrapper-generator.ts"],"names":[],"mappings":"AAyCA,KAAK,cAAc,GAAG;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,SAAS,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AA66B/F,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAwChF"}
@@ -9,24 +9,73 @@ const node_path_1 = require("node:path");
9
9
  const PRIMITIVE_UNION_REGEX = /^(?:\s*(?:string|number|boolean|bigint|null|undefined|unknown|any|void|'[^']*'|"[^"]*"|`[^`]*`|(?:\d+(?:\.\d+)?))\s*)(?:\|\s*(?:string|number|boolean|bigint|null|undefined|unknown|any|void|'[^']*'|"[^"]*"|`[^`]*`|(?:\d+(?:\.\d+)?))\s*)*$/;
10
10
  const IDENTIFIER_TOKEN_REGEX = /[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*/g;
11
11
  const PRIMITIVE_TOKENS = new Set([
12
- 'true', 'false', 'null', 'undefined', 'string', 'number', 'boolean',
13
- 'bigint', 'symbol', 'unknown', 'any', 'void', 'never',
12
+ 'true',
13
+ 'false',
14
+ 'null',
15
+ 'undefined',
16
+ 'string',
17
+ 'number',
18
+ 'boolean',
19
+ 'bigint',
20
+ 'symbol',
21
+ 'unknown',
22
+ 'any',
23
+ 'void',
24
+ 'never',
14
25
  ]);
15
26
  const KNOWN_TYPE_NAMES = new Set([
16
- 'Array', 'ReadonlyArray', 'Promise', 'Record', 'Partial', 'Required', 'Pick', 'Omit',
17
- 'Map', 'Set', 'WeakMap', 'WeakSet', 'Date', 'RegExp', 'Error', 'Node', 'Element',
18
- 'HTMLElement', 'SVGElement', 'Event', 'CustomEvent', 'MouseEvent', 'KeyboardEvent',
19
- 'FocusEvent', 'InputEvent', 'PointerEvent', 'WheelEvent', 'DragEvent', 'SubmitEvent',
20
- 'AbortSignal', 'DOMRect', 'Document', 'Window', 'URL', 'URLSearchParams',
21
- 'CSSStyleDeclaration', 'Intl.Locale',
27
+ 'Array',
28
+ 'ReadonlyArray',
29
+ 'Promise',
30
+ 'Record',
31
+ 'Partial',
32
+ 'Required',
33
+ 'Pick',
34
+ 'Omit',
35
+ 'Map',
36
+ 'Set',
37
+ 'WeakMap',
38
+ 'WeakSet',
39
+ 'Date',
40
+ 'RegExp',
41
+ 'Error',
42
+ 'Node',
43
+ 'Element',
44
+ 'HTMLElement',
45
+ 'SVGElement',
46
+ 'Event',
47
+ 'CustomEvent',
48
+ 'MouseEvent',
49
+ 'KeyboardEvent',
50
+ 'FocusEvent',
51
+ 'InputEvent',
52
+ 'PointerEvent',
53
+ 'WheelEvent',
54
+ 'DragEvent',
55
+ 'SubmitEvent',
56
+ 'AbortSignal',
57
+ 'DOMRect',
58
+ 'Document',
59
+ 'Window',
60
+ 'URL',
61
+ 'URLSearchParams',
62
+ 'CSSStyleDeclaration',
63
+ 'Intl.Locale',
22
64
  ]);
23
65
  /**
24
66
  * DOM event classes that map directly to `(event: T) => void`.
25
67
  * Excludes bare `CustomEvent` which needs special handling for its detail type.
26
68
  */
27
69
  const DOM_EVENT_CLASS_NAMES = new Set([
28
- 'Event', 'MouseEvent', 'KeyboardEvent', 'FocusEvent', 'InputEvent',
29
- 'PointerEvent', 'WheelEvent', 'DragEvent', 'SubmitEvent',
70
+ 'Event',
71
+ 'MouseEvent',
72
+ 'KeyboardEvent',
73
+ 'FocusEvent',
74
+ 'InputEvent',
75
+ 'PointerEvent',
76
+ 'WheelEvent',
77
+ 'DragEvent',
78
+ 'SubmitEvent',
30
79
  ]);
31
80
  /**
32
81
  * React DOM reserves these `on*` prop names for native/synthetic events. When a CEM event
@@ -45,26 +94,96 @@ function loadReactEventHandlerNames() {
45
94
  for (const m of content.matchAll(/\b(on[A-Z][a-zA-Z]+)\??\s*:/g)) {
46
95
  names.add(m[1]);
47
96
  }
97
+ // oxlint-disable-next-line no-magic-numbers -- 20 is a sanity threshold for react event names
48
98
  if (names.size > 20)
49
99
  return names;
50
100
  }
51
101
  catch (_a) { }
52
102
  // Static snapshot — kept as fallback only.
53
103
  return new Set([
54
- 'onCopy', 'onCut', 'onPaste', 'onCompositionEnd', 'onCompositionStart', 'onCompositionUpdate',
55
- 'onFocus', 'onBlur', 'onChange', 'onBeforeInput', 'onInput', 'onReset', 'onSubmit',
56
- 'onInvalid', 'onLoad', 'onError', 'onKeyDown', 'onKeyPress', 'onKeyUp', 'onAbort',
57
- 'onCanPlay', 'onCanPlayThrough', 'onDurationChange', 'onEmptied', 'onEncrypted', 'onEnded',
58
- 'onLoadedData', 'onLoadedMetadata', 'onLoadStart', 'onPause', 'onPlay', 'onPlaying',
59
- 'onProgress', 'onRateChange', 'onResize', 'onSeeked', 'onSeeking', 'onStalled', 'onSuspend',
60
- 'onTimeUpdate', 'onVolumeChange', 'onWaiting', 'onAuxClick', 'onClick', 'onContextMenu',
61
- 'onDoubleClick', 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragExit', 'onDragLeave',
62
- 'onDragOver', 'onDragStart', 'onDrop', 'onMouseDown', 'onMouseEnter', 'onMouseLeave',
63
- 'onMouseMove', 'onMouseOut', 'onMouseOver', 'onMouseUp', 'onSelect', 'onTouchCancel',
64
- 'onTouchEnd', 'onTouchMove', 'onTouchStart', 'onPointerOver', 'onPointerEnter',
65
- 'onPointerDown', 'onPointerMove', 'onPointerUp', 'onPointerCancel', 'onPointerOut',
66
- 'onPointerLeave', 'onGotPointerCapture', 'onLostPointerCapture', 'onScroll', 'onWheel',
67
- 'onAnimationStart', 'onAnimationEnd', 'onAnimationIteration', 'onTransitionEnd', 'onToggle',
104
+ 'onCopy',
105
+ 'onCut',
106
+ 'onPaste',
107
+ 'onCompositionEnd',
108
+ 'onCompositionStart',
109
+ 'onCompositionUpdate',
110
+ 'onFocus',
111
+ 'onBlur',
112
+ 'onChange',
113
+ 'onBeforeInput',
114
+ 'onInput',
115
+ 'onReset',
116
+ 'onSubmit',
117
+ 'onInvalid',
118
+ 'onLoad',
119
+ 'onError',
120
+ 'onKeyDown',
121
+ 'onKeyPress',
122
+ 'onKeyUp',
123
+ 'onAbort',
124
+ 'onCanPlay',
125
+ 'onCanPlayThrough',
126
+ 'onDurationChange',
127
+ 'onEmptied',
128
+ 'onEncrypted',
129
+ 'onEnded',
130
+ 'onLoadedData',
131
+ 'onLoadedMetadata',
132
+ 'onLoadStart',
133
+ 'onPause',
134
+ 'onPlay',
135
+ 'onPlaying',
136
+ 'onProgress',
137
+ 'onRateChange',
138
+ 'onResize',
139
+ 'onSeeked',
140
+ 'onSeeking',
141
+ 'onStalled',
142
+ 'onSuspend',
143
+ 'onTimeUpdate',
144
+ 'onVolumeChange',
145
+ 'onWaiting',
146
+ 'onAuxClick',
147
+ 'onClick',
148
+ 'onContextMenu',
149
+ 'onDoubleClick',
150
+ 'onDrag',
151
+ 'onDragEnd',
152
+ 'onDragEnter',
153
+ 'onDragExit',
154
+ 'onDragLeave',
155
+ 'onDragOver',
156
+ 'onDragStart',
157
+ 'onDrop',
158
+ 'onMouseDown',
159
+ 'onMouseEnter',
160
+ 'onMouseLeave',
161
+ 'onMouseMove',
162
+ 'onMouseOut',
163
+ 'onMouseOver',
164
+ 'onMouseUp',
165
+ 'onSelect',
166
+ 'onTouchCancel',
167
+ 'onTouchEnd',
168
+ 'onTouchMove',
169
+ 'onTouchStart',
170
+ 'onPointerOver',
171
+ 'onPointerEnter',
172
+ 'onPointerDown',
173
+ 'onPointerMove',
174
+ 'onPointerUp',
175
+ 'onPointerCancel',
176
+ 'onPointerOut',
177
+ 'onPointerLeave',
178
+ 'onGotPointerCapture',
179
+ 'onLostPointerCapture',
180
+ 'onScroll',
181
+ 'onWheel',
182
+ 'onAnimationStart',
183
+ 'onAnimationEnd',
184
+ 'onAnimationIteration',
185
+ 'onTransitionEnd',
186
+ 'onToggle',
68
187
  ]);
69
188
  }
70
189
  const REACT_NATIVE_EVENT_HANDLER_NAMES = loadReactEventHandlerNames();
@@ -181,7 +300,7 @@ function canUseComplexType(typeText, typeImportState) {
181
300
  return false;
182
301
  if (/[{};=]/.test(typeText) || /=>/.test(typeText))
183
302
  return false;
184
- if (!/^[A-Za-z0-9_$<>\[\]()|&,.?'"`\s:-]+$/.test(typeText))
303
+ if (!/^[A-Za-z0-9_$<>[\]()|&,.?'"`\s:-]+$/.test(typeText))
185
304
  return false;
186
305
  for (const token of getIdentifierTokens(typeText)) {
187
306
  if (isPrimitiveToken(token) || isKnownTypeIdentifier(token))
@@ -205,6 +324,7 @@ function toSafeType(typeText, typeImportState) {
205
324
  return 'unknown';
206
325
  if (PRIMITIVE_UNION_REGEX.test(normalized))
207
326
  return normalized;
327
+ // oxlint-disable-next-line no-magic-numbers -- -2 strips trailing '[]'
208
328
  if (normalized.endsWith('[]') && PRIMITIVE_UNION_REGEX.test(normalized.slice(0, -2).trim())) {
209
329
  return normalized;
210
330
  }
@@ -260,15 +380,18 @@ function getCEMManifestPath(cwd, packageJson) {
260
380
  // CEM paths are relative to src/ (e.g. "src/entities/entities.ts").
261
381
  // react.mjs/cjs live in dist/ while compiled JS lives in dist/esm/.
262
382
  function cemModulePathToJsImport(modulePath) {
383
+ // oxlint-disable no-magic-numbers -- numeric offsets for known file extension lengths
263
384
  let p = modulePath.startsWith('src/') ? modulePath.slice(4) : modulePath;
264
385
  if (p.endsWith('.tsx'))
265
386
  p = `${p.slice(0, -4)}.js`;
266
387
  else if (p.endsWith('.ts'))
267
388
  p = `${p.slice(0, -3)}.js`;
389
+ // oxlint-enable no-magic-numbers
268
390
  return `./esm/${p}`;
269
391
  }
270
392
  function cemModulePathToDtsImport(modulePath) {
271
- let p = modulePath.startsWith('src/') ? modulePath.slice(4) : modulePath;
393
+ // oxlint-disable-next-line no-magic-numbers -- 4 = 'src/' prefix length
394
+ const p = modulePath.startsWith('src/') ? modulePath.slice(4) : modulePath;
272
395
  const lastDot = p.lastIndexOf('.');
273
396
  return `./${lastDot !== -1 ? p.slice(0, lastDot) : p}`;
274
397
  }
@@ -336,7 +459,8 @@ function mergeFastInheritanceFromManifest(cwd, entries) {
336
459
  return entry;
337
460
  }
338
461
  const inherited = (_f = (_c = byTagAndName.get(`${declaration.tagName}::${(_b = declaration.name) !== null && _b !== void 0 ? _b : ''}`)) !== null && _c !== void 0 ? _c : byTagAndName.get(`${declaration.tagName}::${(_e = (_d = declaration.superclass) === null || _d === void 0 ? void 0 : _d.name) !== null && _e !== void 0 ? _e : ''}`)) !== null && _f !== void 0 ? _f : byTag.get(declaration.tagName);
339
- return inherited ? Object.assign(Object.assign({}, entry), { declaration: mergeDeclarationMetadata(declaration, inherited) }) : entry;
462
+ return inherited
463
+ ? Object.assign(Object.assign({}, entry), { declaration: mergeDeclarationMetadata(declaration, inherited) }) : entry;
340
464
  });
341
465
  });
342
466
  }
@@ -478,9 +602,7 @@ function generateReactWrapperDts(entries, typeImportState) {
478
602
  for (const { declaration } of valid) {
479
603
  const name = declaration.name;
480
604
  // Build event lookup scoped to this element to avoid cross-element type pollution.
481
- const eventsByName = new Map(((_a = declaration.events) !== null && _a !== void 0 ? _a : [])
482
- .filter((e) => e.name)
483
- .map((e) => [e.name, e]));
605
+ const eventsByName = new Map(((_a = declaration.events) !== null && _a !== void 0 ? _a : []).filter((e) => e.name).map((e) => [e.name, e]));
484
606
  const eventLines = buildWrapperEventEntries(declaration).map(({ handlerName, eventName }) => {
485
607
  var _a;
486
608
  const event = eventsByName.get(eventName);
@@ -523,6 +645,7 @@ function collectFilesRecursively(rootDirectory, isTargetFile) {
523
645
  const stack = [rootDirectory];
524
646
  while (stack.length) {
525
647
  const dir = stack.pop();
648
+ // oxlint-disable-next-line no-await-in-loop -- iterative directory traversal, sequential by design
526
649
  const dirEntries = yield (0, promises_1.readdir)(dir, { withFileTypes: true });
527
650
  for (const entry of dirEntries) {
528
651
  const fullPath = (0, node_path_1.resolve)(dir, entry.name);
@@ -626,6 +749,7 @@ function findWorkspaceRoot(startDirectory) {
626
749
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
627
750
  let dir = startDirectory;
628
751
  while (true) {
752
+ // oxlint-disable-next-line no-await-in-loop -- upward directory search must be sequential
629
753
  const [hasPackages, hasPackageJson] = yield Promise.all([
630
754
  fileExists((0, node_path_1.resolve)(dir, 'packages')),
631
755
  fileExists((0, node_path_1.resolve)(dir, 'package.json')),
@@ -646,6 +770,7 @@ function getWorkspacePackageDirectoryByName(workspaceRoot, packageName) {
646
770
  return undefined;
647
771
  const packageJsonFiles = yield collectFilesRecursively(packagesDir, (n) => n === 'package.json');
648
772
  for (const jsonPath of packageJsonFiles) {
773
+ // oxlint-disable-next-line no-await-in-loop -- early-exit search, sequential is correct
649
774
  const pkg = JSON.parse(yield (0, promises_1.readFile)(jsonPath, 'utf8'));
650
775
  if (pkg.name === packageName)
651
776
  return (0, node_path_1.dirname)(jsonPath);
@@ -659,15 +784,20 @@ function enrichFromWorkspaceWildcardExports(cwd, state) {
659
784
  // for...of over a Set processes items added inside the loop (spec-guaranteed behaviour).
660
785
  const pending = new Set([...state.wildcardExportModules].filter((m) => m.startsWith('@genesislcap/')));
661
786
  for (const moduleSpecifier of pending) {
787
+ // oxlint-disable-next-line no-await-in-loop -- sequential per-package processing is intentional
662
788
  const pkgDir = yield getWorkspacePackageDirectoryByName(workspaceRoot, moduleSpecifier);
663
789
  if (!pkgDir)
664
790
  continue;
665
791
  const distDir = (0, node_path_1.resolve)(pkgDir, 'dist');
792
+ // oxlint-disable-next-line no-await-in-loop -- sequential per-package processing is intentional
666
793
  if (!(yield fileExists(distDir)))
667
794
  continue;
668
795
  const refState = createTypeImportState();
796
+ // oxlint-disable-next-line no-await-in-loop -- sequential per-package processing is intentional
669
797
  const { apiJsonFiles, dtsFiles } = yield collectTypeMetadataFiles(distDir);
798
+ // oxlint-disable-next-line no-await-in-loop -- sequential per-package processing is intentional
670
799
  yield parseApiJsonFiles(apiJsonFiles, refState);
800
+ // oxlint-disable-next-line no-await-in-loop -- sequential per-package processing is intentional
671
801
  yield parseDtsFiles(dtsFiles, refState);
672
802
  mergeTypeImportStateInto(state, refState);
673
803
  for (const mod of refState.wildcardExportModules) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/ts-builder",
3
3
  "description": "Typescript builder",
4
- "version": "14.431.0",
4
+ "version": "14.432.1-FUI-2489.1",
5
5
  "license": "SEE LICENSE IN license.txt",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@custom-elements-manifest/analyzer": "^0.8.2",
20
- "@genesislcap/build-kit": "14.431.0",
20
+ "@genesislcap/build-kit": "14.432.1-FUI-2489.1",
21
21
  "consola": "^3.0.2",
22
22
  "copyfiles": "^2.4.1",
23
23
  "pkg-types": "^1.0.2"
@@ -30,5 +30,5 @@
30
30
  "publishConfig": {
31
31
  "access": "public"
32
32
  },
33
- "gitHead": "4e523b6a77df321a9c70fcdf7c12a4ffcb98769a"
33
+ "gitHead": "9bae1c5f931d4787041aae3536be9493c11e6312"
34
34
  }
package/src/index.ts CHANGED
@@ -50,7 +50,9 @@ export default async (ctx: BuildContext) => {
50
50
  } else {
51
51
  // strictNullChecks is off in this workspace, so boolean literal narrowing
52
52
  // doesn't apply to the discriminated union — cast to access the skipped variant.
53
- consola.debug(`React wrappers skipped: ${(reactWrappersResult as { reason: string }).reason}`);
53
+ consola.debug(
54
+ `React wrappers skipped: ${(reactWrappersResult as { reason: string }).reason}`,
55
+ );
54
56
  }
55
57
  } else {
56
58
  throw new Error(`Unrecognized command: ${JSON.stringify(options)}`);
@@ -39,9 +39,7 @@ type TypeImportState = {
39
39
 
40
40
  // ── Public API return type ───────────────────────────────────────────────────
41
41
 
42
- type GenerateResult =
43
- | { generated: true; path: string }
44
- | { generated: false; reason: string };
42
+ type GenerateResult = { generated: true; path: string } | { generated: false; reason: string };
45
43
 
46
44
  // ── Constants ────────────────────────────────────────────────────────────────
47
45
 
@@ -51,17 +49,59 @@ const PRIMITIVE_UNION_REGEX =
51
49
  const IDENTIFIER_TOKEN_REGEX = /[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*/g;
52
50
 
53
51
  const PRIMITIVE_TOKENS = new Set([
54
- 'true', 'false', 'null', 'undefined', 'string', 'number', 'boolean',
55
- 'bigint', 'symbol', 'unknown', 'any', 'void', 'never',
52
+ 'true',
53
+ 'false',
54
+ 'null',
55
+ 'undefined',
56
+ 'string',
57
+ 'number',
58
+ 'boolean',
59
+ 'bigint',
60
+ 'symbol',
61
+ 'unknown',
62
+ 'any',
63
+ 'void',
64
+ 'never',
56
65
  ]);
57
66
 
58
67
  const KNOWN_TYPE_NAMES = new Set([
59
- 'Array', 'ReadonlyArray', 'Promise', 'Record', 'Partial', 'Required', 'Pick', 'Omit',
60
- 'Map', 'Set', 'WeakMap', 'WeakSet', 'Date', 'RegExp', 'Error', 'Node', 'Element',
61
- 'HTMLElement', 'SVGElement', 'Event', 'CustomEvent', 'MouseEvent', 'KeyboardEvent',
62
- 'FocusEvent', 'InputEvent', 'PointerEvent', 'WheelEvent', 'DragEvent', 'SubmitEvent',
63
- 'AbortSignal', 'DOMRect', 'Document', 'Window', 'URL', 'URLSearchParams',
64
- 'CSSStyleDeclaration', 'Intl.Locale',
68
+ 'Array',
69
+ 'ReadonlyArray',
70
+ 'Promise',
71
+ 'Record',
72
+ 'Partial',
73
+ 'Required',
74
+ 'Pick',
75
+ 'Omit',
76
+ 'Map',
77
+ 'Set',
78
+ 'WeakMap',
79
+ 'WeakSet',
80
+ 'Date',
81
+ 'RegExp',
82
+ 'Error',
83
+ 'Node',
84
+ 'Element',
85
+ 'HTMLElement',
86
+ 'SVGElement',
87
+ 'Event',
88
+ 'CustomEvent',
89
+ 'MouseEvent',
90
+ 'KeyboardEvent',
91
+ 'FocusEvent',
92
+ 'InputEvent',
93
+ 'PointerEvent',
94
+ 'WheelEvent',
95
+ 'DragEvent',
96
+ 'SubmitEvent',
97
+ 'AbortSignal',
98
+ 'DOMRect',
99
+ 'Document',
100
+ 'Window',
101
+ 'URL',
102
+ 'URLSearchParams',
103
+ 'CSSStyleDeclaration',
104
+ 'Intl.Locale',
65
105
  ]);
66
106
 
67
107
  /**
@@ -69,8 +109,15 @@ const KNOWN_TYPE_NAMES = new Set([
69
109
  * Excludes bare `CustomEvent` which needs special handling for its detail type.
70
110
  */
71
111
  const DOM_EVENT_CLASS_NAMES = new Set([
72
- 'Event', 'MouseEvent', 'KeyboardEvent', 'FocusEvent', 'InputEvent',
73
- 'PointerEvent', 'WheelEvent', 'DragEvent', 'SubmitEvent',
112
+ 'Event',
113
+ 'MouseEvent',
114
+ 'KeyboardEvent',
115
+ 'FocusEvent',
116
+ 'InputEvent',
117
+ 'PointerEvent',
118
+ 'WheelEvent',
119
+ 'DragEvent',
120
+ 'SubmitEvent',
74
121
  ]);
75
122
 
76
123
  /**
@@ -90,24 +137,94 @@ function loadReactEventHandlerNames(): Set<string> {
90
137
  for (const m of content.matchAll(/\b(on[A-Z][a-zA-Z]+)\??\s*:/g)) {
91
138
  names.add(m[1]);
92
139
  }
140
+ // oxlint-disable-next-line no-magic-numbers -- 20 is a sanity threshold for react event names
93
141
  if (names.size > 20) return names;
94
142
  } catch {}
95
143
  // Static snapshot — kept as fallback only.
96
144
  return new Set([
97
- 'onCopy', 'onCut', 'onPaste', 'onCompositionEnd', 'onCompositionStart', 'onCompositionUpdate',
98
- 'onFocus', 'onBlur', 'onChange', 'onBeforeInput', 'onInput', 'onReset', 'onSubmit',
99
- 'onInvalid', 'onLoad', 'onError', 'onKeyDown', 'onKeyPress', 'onKeyUp', 'onAbort',
100
- 'onCanPlay', 'onCanPlayThrough', 'onDurationChange', 'onEmptied', 'onEncrypted', 'onEnded',
101
- 'onLoadedData', 'onLoadedMetadata', 'onLoadStart', 'onPause', 'onPlay', 'onPlaying',
102
- 'onProgress', 'onRateChange', 'onResize', 'onSeeked', 'onSeeking', 'onStalled', 'onSuspend',
103
- 'onTimeUpdate', 'onVolumeChange', 'onWaiting', 'onAuxClick', 'onClick', 'onContextMenu',
104
- 'onDoubleClick', 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragExit', 'onDragLeave',
105
- 'onDragOver', 'onDragStart', 'onDrop', 'onMouseDown', 'onMouseEnter', 'onMouseLeave',
106
- 'onMouseMove', 'onMouseOut', 'onMouseOver', 'onMouseUp', 'onSelect', 'onTouchCancel',
107
- 'onTouchEnd', 'onTouchMove', 'onTouchStart', 'onPointerOver', 'onPointerEnter',
108
- 'onPointerDown', 'onPointerMove', 'onPointerUp', 'onPointerCancel', 'onPointerOut',
109
- 'onPointerLeave', 'onGotPointerCapture', 'onLostPointerCapture', 'onScroll', 'onWheel',
110
- 'onAnimationStart', 'onAnimationEnd', 'onAnimationIteration', 'onTransitionEnd', 'onToggle',
145
+ 'onCopy',
146
+ 'onCut',
147
+ 'onPaste',
148
+ 'onCompositionEnd',
149
+ 'onCompositionStart',
150
+ 'onCompositionUpdate',
151
+ 'onFocus',
152
+ 'onBlur',
153
+ 'onChange',
154
+ 'onBeforeInput',
155
+ 'onInput',
156
+ 'onReset',
157
+ 'onSubmit',
158
+ 'onInvalid',
159
+ 'onLoad',
160
+ 'onError',
161
+ 'onKeyDown',
162
+ 'onKeyPress',
163
+ 'onKeyUp',
164
+ 'onAbort',
165
+ 'onCanPlay',
166
+ 'onCanPlayThrough',
167
+ 'onDurationChange',
168
+ 'onEmptied',
169
+ 'onEncrypted',
170
+ 'onEnded',
171
+ 'onLoadedData',
172
+ 'onLoadedMetadata',
173
+ 'onLoadStart',
174
+ 'onPause',
175
+ 'onPlay',
176
+ 'onPlaying',
177
+ 'onProgress',
178
+ 'onRateChange',
179
+ 'onResize',
180
+ 'onSeeked',
181
+ 'onSeeking',
182
+ 'onStalled',
183
+ 'onSuspend',
184
+ 'onTimeUpdate',
185
+ 'onVolumeChange',
186
+ 'onWaiting',
187
+ 'onAuxClick',
188
+ 'onClick',
189
+ 'onContextMenu',
190
+ 'onDoubleClick',
191
+ 'onDrag',
192
+ 'onDragEnd',
193
+ 'onDragEnter',
194
+ 'onDragExit',
195
+ 'onDragLeave',
196
+ 'onDragOver',
197
+ 'onDragStart',
198
+ 'onDrop',
199
+ 'onMouseDown',
200
+ 'onMouseEnter',
201
+ 'onMouseLeave',
202
+ 'onMouseMove',
203
+ 'onMouseOut',
204
+ 'onMouseOver',
205
+ 'onMouseUp',
206
+ 'onSelect',
207
+ 'onTouchCancel',
208
+ 'onTouchEnd',
209
+ 'onTouchMove',
210
+ 'onTouchStart',
211
+ 'onPointerOver',
212
+ 'onPointerEnter',
213
+ 'onPointerDown',
214
+ 'onPointerMove',
215
+ 'onPointerUp',
216
+ 'onPointerCancel',
217
+ 'onPointerOut',
218
+ 'onPointerLeave',
219
+ 'onGotPointerCapture',
220
+ 'onLostPointerCapture',
221
+ 'onScroll',
222
+ 'onWheel',
223
+ 'onAnimationStart',
224
+ 'onAnimationEnd',
225
+ 'onAnimationIteration',
226
+ 'onTransitionEnd',
227
+ 'onToggle',
111
228
  ]);
112
229
  }
113
230
 
@@ -205,7 +322,11 @@ function createTypeImportState(): TypeImportState {
205
322
  };
206
323
  }
207
324
 
208
- function registerTypeImport(state: TypeImportState, identifier: string, moduleSpecifier: string): void {
325
+ function registerTypeImport(
326
+ state: TypeImportState,
327
+ identifier: string,
328
+ moduleSpecifier: string,
329
+ ): void {
209
330
  if (state.ambiguousIdentifiers.has(identifier)) return;
210
331
 
211
332
  const existing = state.importsByIdentifier.get(identifier);
@@ -220,7 +341,11 @@ function registerTypeImport(state: TypeImportState, identifier: string, moduleSp
220
341
  }
221
342
  }
222
343
 
223
- function trackImportedIdentifierUsage(state: TypeImportState, identifier: string, moduleSpecifier: string): void {
344
+ function trackImportedIdentifierUsage(
345
+ state: TypeImportState,
346
+ identifier: string,
347
+ moduleSpecifier: string,
348
+ ): void {
224
349
  if (!state.usedImports.has(moduleSpecifier)) {
225
350
  state.usedImports.set(moduleSpecifier, new Set());
226
351
  }
@@ -234,7 +359,7 @@ function isBareModuleSpecifier(moduleSpecifier: string): boolean {
234
359
  function canUseComplexType(typeText: string, typeImportState?: TypeImportState): boolean {
235
360
  if (!typeText) return false;
236
361
  if (/[{};=]/.test(typeText) || /=>/.test(typeText)) return false;
237
- if (!/^[A-Za-z0-9_$<>\[\]()|&,.?'"`\s:-]+$/.test(typeText)) return false;
362
+ if (!/^[A-Za-z0-9_$<>[\]()|&,.?'"`\s:-]+$/.test(typeText)) return false;
238
363
 
239
364
  for (const token of getIdentifierTokens(typeText)) {
240
365
  if (isPrimitiveToken(token) || isKnownTypeIdentifier(token)) continue;
@@ -245,7 +370,11 @@ function canUseComplexType(typeText: string, typeImportState?: TypeImportState):
245
370
  !typeImportState.ambiguousIdentifiers.has(root) &&
246
371
  typeImportState.importsByIdentifier.has(root)
247
372
  ) {
248
- trackImportedIdentifierUsage(typeImportState, root, typeImportState.importsByIdentifier.get(root)!);
373
+ trackImportedIdentifierUsage(
374
+ typeImportState,
375
+ root,
376
+ typeImportState.importsByIdentifier.get(root)!,
377
+ );
249
378
  continue;
250
379
  }
251
380
 
@@ -262,6 +391,7 @@ function toSafeType(typeText?: string, typeImportState?: TypeImportState): strin
262
391
 
263
392
  if (PRIMITIVE_UNION_REGEX.test(normalized)) return normalized;
264
393
 
394
+ // oxlint-disable-next-line no-magic-numbers -- -2 strips trailing '[]'
265
395
  if (normalized.endsWith('[]') && PRIMITIVE_UNION_REGEX.test(normalized.slice(0, -2).trim())) {
266
396
  return normalized;
267
397
  }
@@ -330,14 +460,17 @@ function getCEMManifestPath(cwd: string, packageJson: Record<string, unknown>):
330
460
  // CEM paths are relative to src/ (e.g. "src/entities/entities.ts").
331
461
  // react.mjs/cjs live in dist/ while compiled JS lives in dist/esm/.
332
462
  function cemModulePathToJsImport(modulePath: string): string {
463
+ // oxlint-disable no-magic-numbers -- numeric offsets for known file extension lengths
333
464
  let p = modulePath.startsWith('src/') ? modulePath.slice(4) : modulePath;
334
465
  if (p.endsWith('.tsx')) p = `${p.slice(0, -4)}.js`;
335
466
  else if (p.endsWith('.ts')) p = `${p.slice(0, -3)}.js`;
467
+ // oxlint-enable no-magic-numbers
336
468
  return `./esm/${p}`;
337
469
  }
338
470
 
339
471
  function cemModulePathToDtsImport(modulePath: string): string {
340
- let p = modulePath.startsWith('src/') ? modulePath.slice(4) : modulePath;
472
+ // oxlint-disable-next-line no-magic-numbers -- 4 = 'src/' prefix length
473
+ const p = modulePath.startsWith('src/') ? modulePath.slice(4) : modulePath;
341
474
  const lastDot = p.lastIndexOf('.');
342
475
  return `./${lastDot !== -1 ? p.slice(0, lastDot) : p}`;
343
476
  }
@@ -419,7 +552,9 @@ async function mergeFastInheritanceFromManifest(
419
552
  byTagAndName.get(`${declaration.tagName}::${declaration.superclass?.name ?? ''}`) ??
420
553
  byTag.get(declaration.tagName);
421
554
 
422
- return inherited ? { ...entry, declaration: mergeDeclarationMetadata(declaration, inherited) } : entry;
555
+ return inherited
556
+ ? { ...entry, declaration: mergeDeclarationMetadata(declaration, inherited) }
557
+ : entry;
423
558
  });
424
559
  }
425
560
 
@@ -435,7 +570,8 @@ function buildWrapperEventEntries(
435
570
  const normalized = normalizePropertyName(event.name);
436
571
  if (!normalized) continue;
437
572
  const handlerName = `on${toPascalCase(normalized)}`;
438
- if (!handlerName || REACT_NATIVE_EVENT_HANDLER_NAMES.has(handlerName) || seen.has(handlerName)) continue;
573
+ if (!handlerName || REACT_NATIVE_EVENT_HANDLER_NAMES.has(handlerName) || seen.has(handlerName))
574
+ continue;
439
575
  seen.add(handlerName);
440
576
  result.push({ handlerName, eventName: event.name });
441
577
  }
@@ -490,12 +626,18 @@ function generateReactWrapperJs(entries: CEMElementEntry[], format: 'esm' | 'cjs
490
626
  }
491
627
 
492
628
  for (const [modulePath, pathEntries] of [...groupEntriesByPath(valid).entries()].sort()) {
493
- const sorted = [...pathEntries].sort((a, b) => a.declaration.name!.localeCompare(b.declaration.name!));
629
+ const sorted = [...pathEntries].sort((a, b) =>
630
+ a.declaration.name!.localeCompare(b.declaration.name!),
631
+ );
494
632
  const jsPath = cemModulePathToJsImport(modulePath);
495
633
  if (esm) {
496
- lines.push(`import { ${sorted.map((e) => `${e.declaration.name} as ${e.declaration.name}WC`).join(', ')} } from '${jsPath}';`);
634
+ lines.push(
635
+ `import { ${sorted.map((e) => `${e.declaration.name} as ${e.declaration.name}WC`).join(', ')} } from '${jsPath}';`,
636
+ );
497
637
  } else {
498
- lines.push(`const { ${sorted.map((e) => `${e.declaration.name}: ${e.declaration.name}WC`).join(', ')} } = require('${jsPath}');`);
638
+ lines.push(
639
+ `const { ${sorted.map((e) => `${e.declaration.name}: ${e.declaration.name}WC`).join(', ')} } = require('${jsPath}');`,
640
+ );
499
641
  }
500
642
  }
501
643
 
@@ -525,7 +667,9 @@ function generateReactWrapperJs(entries: CEMElementEntry[], format: 'esm' | 'cjs
525
667
  lines.push(`${prefix} ${name} = React.forwardRef(function ${name}(props, ref) {`);
526
668
 
527
669
  if (events.length) {
528
- lines.push(` const { ${events.map((e) => e.handlerName).join(', ')}, children, ...rest } = props;`);
670
+ lines.push(
671
+ ` const { ${events.map((e) => e.handlerName).join(', ')}, children, ...rest } = props;`,
672
+ );
529
673
  lines.push(' const _innerRef = React.useRef(null);');
530
674
  for (const { handlerName } of events) {
531
675
  lines.push(` const _${handlerName}Ref = React.useRef(${handlerName});`);
@@ -544,10 +688,14 @@ function generateReactWrapperJs(entries: CEMElementEntry[], format: 'esm' | 'cjs
544
688
  }
545
689
  lines.push(' };');
546
690
  lines.push(' }, []);');
547
- lines.push(` return React.createElement(customElements.getName(${name}WC) ?? '${tagName}', { ...rest, ref: _mergeRefs(_innerRef, ref) }, children);`);
691
+ lines.push(
692
+ ` return React.createElement(customElements.getName(${name}WC) ?? '${tagName}', { ...rest, ref: _mergeRefs(_innerRef, ref) }, children);`,
693
+ );
548
694
  } else {
549
695
  lines.push(' const { children, ...rest } = props;');
550
- lines.push(` return React.createElement(customElements.getName(${name}WC) ?? '${tagName}', { ...rest, ref }, children);`);
696
+ lines.push(
697
+ ` return React.createElement(customElements.getName(${name}WC) ?? '${tagName}', { ...rest, ref }, children);`,
698
+ );
551
699
  }
552
700
 
553
701
  lines.push('});');
@@ -563,7 +711,10 @@ function generateReactWrapperJs(entries: CEMElementEntry[], format: 'esm' | 'cjs
563
711
  return lines.join('\n');
564
712
  }
565
713
 
566
- function generateReactWrapperDts(entries: CEMElementEntry[], typeImportState: TypeImportState): string {
714
+ function generateReactWrapperDts(
715
+ entries: CEMElementEntry[],
716
+ typeImportState: TypeImportState,
717
+ ): string {
567
718
  const valid = entries.filter((e) => e.declaration.name && e.declaration.tagName && e.modulePath);
568
719
  if (!valid.length) return '';
569
720
 
@@ -584,14 +735,16 @@ function generateReactWrapperDts(entries: CEMElementEntry[], typeImportState: Ty
584
735
 
585
736
  // Build event lookup scoped to this element to avoid cross-element type pollution.
586
737
  const eventsByName = new Map(
587
- (declaration.events ?? [])
588
- .filter((e) => e.name)
589
- .map((e) => [e.name!, e] as const),
738
+ (declaration.events ?? []).filter((e) => e.name).map((e) => [e.name!, e] as const),
590
739
  );
591
740
 
592
741
  const eventLines = buildWrapperEventEntries(declaration).map(({ handlerName, eventName }) => {
593
742
  const event = eventsByName.get(eventName);
594
- const handlerType = toEventHandlerType(event?.type?.text, wrapperTypeState, event?.description);
743
+ const handlerType = toEventHandlerType(
744
+ event?.type?.text,
745
+ wrapperTypeState,
746
+ event?.description,
747
+ );
595
748
  return ` ${handlerName}?: ${handlerType};`;
596
749
  });
597
750
 
@@ -645,6 +798,7 @@ async function collectFilesRecursively(
645
798
  const stack: string[] = [rootDirectory];
646
799
  while (stack.length) {
647
800
  const dir = stack.pop()!;
801
+ // oxlint-disable-next-line no-await-in-loop -- iterative directory traversal, sequential by design
648
802
  const dirEntries = await readdir(dir, { withFileTypes: true });
649
803
  for (const entry of dirEntries) {
650
804
  const fullPath = resolve(dir, entry.name);
@@ -704,7 +858,8 @@ function parseImportsFromDtsContent(content: string, state: TypeImportState): vo
704
858
  registerTypeImport(state, alias[2], moduleSpecifier);
705
859
  continue;
706
860
  }
707
- if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(entry)) registerTypeImport(state, entry, moduleSpecifier);
861
+ if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(entry))
862
+ registerTypeImport(state, entry, moduleSpecifier);
708
863
  }
709
864
  }
710
865
 
@@ -748,6 +903,7 @@ function mergeTypeImportStateInto(target: TypeImportState, source: TypeImportSta
748
903
  async function findWorkspaceRoot(startDirectory: string): Promise<string> {
749
904
  let dir = startDirectory;
750
905
  while (true) {
906
+ // oxlint-disable-next-line no-await-in-loop -- upward directory search must be sequential
751
907
  const [hasPackages, hasPackageJson] = await Promise.all([
752
908
  fileExists(resolve(dir, 'packages')),
753
909
  fileExists(resolve(dir, 'package.json')),
@@ -768,13 +924,17 @@ async function getWorkspacePackageDirectoryByName(
768
924
 
769
925
  const packageJsonFiles = await collectFilesRecursively(packagesDir, (n) => n === 'package.json');
770
926
  for (const jsonPath of packageJsonFiles) {
927
+ // oxlint-disable-next-line no-await-in-loop -- early-exit search, sequential is correct
771
928
  const pkg = JSON.parse(await readFile(jsonPath, 'utf8')) as Record<string, unknown>;
772
929
  if (pkg.name === packageName) return dirname(jsonPath);
773
930
  }
774
931
  return undefined;
775
932
  }
776
933
 
777
- async function enrichFromWorkspaceWildcardExports(cwd: string, state: TypeImportState): Promise<void> {
934
+ async function enrichFromWorkspaceWildcardExports(
935
+ cwd: string,
936
+ state: TypeImportState,
937
+ ): Promise<void> {
778
938
  const workspaceRoot = await findWorkspaceRoot(cwd);
779
939
  // for...of over a Set processes items added inside the loop (spec-guaranteed behaviour).
780
940
  const pending = new Set(
@@ -782,15 +942,20 @@ async function enrichFromWorkspaceWildcardExports(cwd: string, state: TypeImport
782
942
  );
783
943
 
784
944
  for (const moduleSpecifier of pending) {
945
+ // oxlint-disable-next-line no-await-in-loop -- sequential per-package processing is intentional
785
946
  const pkgDir = await getWorkspacePackageDirectoryByName(workspaceRoot, moduleSpecifier);
786
947
  if (!pkgDir) continue;
787
948
 
788
949
  const distDir = resolve(pkgDir, 'dist');
950
+ // oxlint-disable-next-line no-await-in-loop -- sequential per-package processing is intentional
789
951
  if (!(await fileExists(distDir))) continue;
790
952
 
791
953
  const refState = createTypeImportState();
954
+ // oxlint-disable-next-line no-await-in-loop -- sequential per-package processing is intentional
792
955
  const { apiJsonFiles, dtsFiles } = await collectTypeMetadataFiles(distDir);
956
+ // oxlint-disable-next-line no-await-in-loop -- sequential per-package processing is intentional
793
957
  await parseApiJsonFiles(apiJsonFiles, refState);
958
+ // oxlint-disable-next-line no-await-in-loop -- sequential per-package processing is intentional
794
959
  await parseDtsFiles(dtsFiles, refState);
795
960
  mergeTypeImportStateInto(state, refState);
796
961
 
@@ -821,7 +986,10 @@ export async function generateReactWrappers(cwd: string): Promise<GenerateResult
821
986
  return { generated: false, reason: 'No package.json found.' };
822
987
  }
823
988
 
824
- const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8')) as Record<string, unknown>;
989
+ const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8')) as Record<
990
+ string,
991
+ unknown
992
+ >;
825
993
  const manifestPath = getCEMManifestPath(cwd, packageJson);
826
994
  if (!(await fileExists(manifestPath))) {
827
995
  return { generated: false, reason: 'No custom elements manifest found.' };
package/tsconfig.json CHANGED
@@ -2,17 +2,10 @@
2
2
  "extends": "../../../../tsconfig.json",
3
3
  "compilerOptions": {
4
4
  "declarationDir": "./dist",
5
- "lib": [
6
- "ES2015",
7
- "ES2016",
8
- "ES2017",
9
- "ES2019",
10
- ],
5
+ "lib": ["ES2015", "ES2016", "ES2017", "ES2019"],
11
6
  "module": "commonjs",
12
7
  "outDir": "./dist",
13
- "rootDir": "./src",
8
+ "rootDir": "./src"
14
9
  },
15
- "include": [
16
- "src/**/*"
17
- ]
10
+ "include": ["src/**/*"]
18
11
  }