@lariocpt/flawless-react 0.0.0-stage → 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.
Files changed (143) hide show
  1. package/.agents/skills/flawless-a11y/SKILL.md +113 -0
  2. package/.agents/skills/flawless-api/SKILL.md +159 -0
  3. package/.agents/skills/flawless-api-fixtures/SKILL.md +144 -0
  4. package/.agents/skills/flawless-e2e/SKILL.md +155 -0
  5. package/.agents/skills/flawless-expo/SKILL.md +283 -0
  6. package/.agents/skills/flawless-findings/SKILL.md +116 -0
  7. package/.agents/skills/flawless-load/SKILL.md +112 -0
  8. package/.agents/skills/flawless-nextjs/SKILL.md +198 -0
  9. package/.agents/skills/flawless-perf-harness/SKILL.md +158 -0
  10. package/.agents/skills/flawless-perf-static/SKILL.md +131 -0
  11. package/.agents/skills/flawless-react/SKILL.md +403 -0
  12. package/.agents/skills/flawless-react-rules/SKILL.md +96 -0
  13. package/.agents/skills/flawless-regen/SKILL.md +135 -0
  14. package/.agents/skills/flawless-unit-browser/SKILL.md +178 -0
  15. package/LICENSE +21 -0
  16. package/README.md +611 -2
  17. package/bin/flawless-react +4 -0
  18. package/package.json +67 -4
  19. package/scripts/postinstall.d.mts +46 -0
  20. package/scripts/postinstall.mjs +127 -0
  21. package/src/analyse/authShims.ts +220 -0
  22. package/src/analyse/bootability.ts +257 -0
  23. package/src/analyse/childBridge.ts +302 -0
  24. package/src/analyse/childrenIntoSlot.ts +66 -0
  25. package/src/analyse/compoundFamily.ts +100 -0
  26. package/src/analyse/dataExports.ts +200 -0
  27. package/src/analyse/extractChildAttrs.ts +112 -0
  28. package/src/analyse/extractDataDeps.ts +857 -0
  29. package/src/analyse/extractDisclosures.ts +186 -0
  30. package/src/analyse/extractFetchCalls.ts +81 -0
  31. package/src/analyse/extractFlows.ts +239 -0
  32. package/src/analyse/extractGuards.ts +270 -0
  33. package/src/analyse/extractHooks.ts +237 -0
  34. package/src/analyse/extractInteractions.ts +1421 -0
  35. package/src/analyse/extractLogging.ts +45 -0
  36. package/src/analyse/extractNativeA11y.ts +138 -0
  37. package/src/analyse/extractPredicates.ts +784 -0
  38. package/src/analyse/extractPropUsage.ts +162 -0
  39. package/src/analyse/extractProps.ts +1212 -0
  40. package/src/analyse/extractRenderMode.ts +165 -0
  41. package/src/analyse/extractRootTag.ts +117 -0
  42. package/src/analyse/extractState.ts +361 -0
  43. package/src/analyse/extractStaticText.ts +212 -0
  44. package/src/analyse/extractVariants.ts +186 -0
  45. package/src/analyse/harvestApiEndpoints.ts +284 -0
  46. package/src/analyse/hostProps.ts +185 -0
  47. package/src/analyse/hostTag.ts +72 -0
  48. package/src/analyse/htmlContentModel.ts +94 -0
  49. package/src/analyse/index.ts +744 -0
  50. package/src/analyse/mountPathCalls.ts +442 -0
  51. package/src/analyse/nativeContentModel.ts +129 -0
  52. package/src/analyse/nativeDialect.ts +83 -0
  53. package/src/analyse/nativeProps.ts +339 -0
  54. package/src/analyse/ownReturns.ts +31 -0
  55. package/src/analyse/parseFile.ts +919 -0
  56. package/src/analyse/pos.ts +8 -0
  57. package/src/analyse/providerWraps.ts +1977 -0
  58. package/src/analyse/pureModule.ts +88 -0
  59. package/src/analyse/reexportTable.ts +148 -0
  60. package/src/analyse/refs.ts +195 -0
  61. package/src/analyse/renderPath.ts +441 -0
  62. package/src/analyse/resolveDepReturns.ts +370 -0
  63. package/src/analyse/resolveIndexKeys.ts +98 -0
  64. package/src/analyse/resolveModule.ts +431 -0
  65. package/src/analyse/resolveTagRootTags.ts +103 -0
  66. package/src/analyse/serverActionReturns.ts +213 -0
  67. package/src/analyse/sourceCache.ts +263 -0
  68. package/src/analyse/spreadSiblings.ts +98 -0
  69. package/src/analyse/walkChildren.ts +98 -0
  70. package/src/analyse/zodSchema.ts +424 -0
  71. package/src/bin.ts +23 -0
  72. package/src/changed.ts +221 -0
  73. package/src/cli.ts +560 -0
  74. package/src/cliFlags.ts +281 -0
  75. package/src/core.ts +1229 -0
  76. package/src/docLine.ts +122 -0
  77. package/src/emitPaths.ts +51 -0
  78. package/src/expo/detect.ts +184 -0
  79. package/src/expo/refusal.ts +62 -0
  80. package/src/expo/routes.ts +145 -0
  81. package/src/index.ts +95 -0
  82. package/src/mcp/analysisTools.ts +720 -0
  83. package/src/mcp/infoTools.ts +135 -0
  84. package/src/mcp/protocol.ts +130 -0
  85. package/src/mcp/run.ts +269 -0
  86. package/src/mcp/runTools.ts +362 -0
  87. package/src/mcp/server.ts +279 -0
  88. package/src/mcp/spec.ts +86 -0
  89. package/src/mcp/support.ts +268 -0
  90. package/src/mcp/tools.ts +75 -0
  91. package/src/nextjs/apiRoutes.ts +116 -0
  92. package/src/nextjs/detect.ts +397 -0
  93. package/src/nextjs/emit.ts +106 -0
  94. package/src/nextjs/liveSpec.ts +79 -0
  95. package/src/nextjs/mswHandlers.ts +55 -0
  96. package/src/nextjs/providerWrapper.ts +603 -0
  97. package/src/nextjs/routes.ts +86 -0
  98. package/src/nextjs/swagger.ts +32 -0
  99. package/src/packageJson.ts +414 -0
  100. package/src/platform.ts +18 -0
  101. package/src/prompt.ts +132 -0
  102. package/src/reactCompiler.ts +165 -0
  103. package/src/reporters/findings.ts +156 -0
  104. package/src/reporters/report.ts +463 -0
  105. package/src/runner/runTests.ts +402 -0
  106. package/src/scaffold/adoptStyle.ts +181 -0
  107. package/src/scaffold/index.ts +253 -0
  108. package/src/scaffold/openapi.ts +183 -0
  109. package/src/scaffold/templates.ts +2379 -0
  110. package/src/scaffold-tests/index.ts +463 -0
  111. package/src/scaffold-tests/mockValues.ts +208 -0
  112. package/src/scaffold-tests/mocks.ts +794 -0
  113. package/src/scaffold-tests/nativeIndex.ts +52 -0
  114. package/src/scaffold-tests/nativeTemplates.ts +1528 -0
  115. package/src/scaffold-tests/postDispatch.ts +152 -0
  116. package/src/scaffold-tests/registry.ts +443 -0
  117. package/src/scaffold-tests/selectors.ts +493 -0
  118. package/src/scaffold-tests/selectorsNative.ts +273 -0
  119. package/src/scaffold-tests/stamp.ts +79 -0
  120. package/src/scaffold-tests/templates.ts +3578 -0
  121. package/src/skills/cli.ts +248 -0
  122. package/src/skills/compat.ts +166 -0
  123. package/src/skills/data.ts +192 -0
  124. package/src/skills/md.d.ts +7 -0
  125. package/src/skills/menu.ts +55 -0
  126. package/src/skills/spec.ts +227 -0
  127. package/src/suiteScripts.ts +110 -0
  128. package/src/tasks/a11yNative.ts +281 -0
  129. package/src/tasks/a11yScan.ts +67 -0
  130. package/src/tasks/biomeRunner.ts +301 -0
  131. package/src/tasks/biomeSweep.ts +166 -0
  132. package/src/tasks/e2eExpo.ts +436 -0
  133. package/src/tasks/e2eRoutes.ts +756 -0
  134. package/src/tasks/eslintReactRules.ts +67 -0
  135. package/src/tasks/index.ts +24 -0
  136. package/src/tasks/loadExpo.ts +273 -0
  137. package/src/tasks/loadPipes.ts +750 -0
  138. package/src/tasks/perfHarness.ts +145 -0
  139. package/src/tasks/staticPerfAnalysis.ts +510 -0
  140. package/src/tasks/types.ts +1 -0
  141. package/src/tasks/unitAndBrowser.ts +462 -0
  142. package/src/types.ts +1419 -0
  143. package/src/version.ts +12 -0
@@ -0,0 +1,162 @@
1
+ import ts from "typescript";
2
+ import type { PropUsage } from "../types.ts";
3
+ import { posOf } from "./pos.ts";
4
+ import { type ComponentScope, collectRefs, hookCalleeName } from "./refs.ts";
5
+
6
+ /**
7
+ * Classifies every prop reference in the component body by where it flows
8
+ * (JSX, hook deps/args, calls, conditions). Rules run in fixed precedence;
9
+ * the first match wins. Purely syntactic — see refs.ts for the shared limits.
10
+ */
11
+
12
+ const DEPS_HOOKS = new Set([
13
+ "useEffect",
14
+ "useLayoutEffect",
15
+ "useMemo",
16
+ "useCallback",
17
+ "useImperativeHandle",
18
+ ]);
19
+
20
+ type Classified = Pick<PropUsage, "kind" | "tag" | "attr" | "hook">;
21
+
22
+ export function extractPropUsage(
23
+ bodyNode: ts.Node,
24
+ sourceFile: ts.SourceFile,
25
+ scope: ComponentScope,
26
+ ): PropUsage[] {
27
+ const names = new Set<string>([...scope.propNames, ...scope.propAliases.keys()]);
28
+ const out: PropUsage[] = [];
29
+
30
+ for (const ref of collectRefs(bodyNode, sourceFile, names, scope.paramName)) {
31
+ // For `props.x` references classification anchors on the whole access node.
32
+ const refExpr: ts.Node = ref.viaParam ? ref.node.parent : ref.node;
33
+ const usage: PropUsage = {
34
+ propName: scope.propAliases.get(ref.name) ?? ref.name,
35
+ ...classify(refExpr, bodyNode),
36
+ pos: posOf(ref.node, sourceFile),
37
+ };
38
+ const chain = memberChain(refExpr);
39
+ if (chain !== undefined) {
40
+ usage.member = chain[0];
41
+ if (chain.length > 1) usage.chain = chain;
42
+ }
43
+ out.push(usage);
44
+ }
45
+ return out;
46
+ }
47
+
48
+ function classify(refExpr: ts.Node, bodyNode: ts.Node): Classified {
49
+ // 1 — element of the deps array of a deps-taking hook.
50
+ for (let n = refExpr; n !== bodyNode && n.parent; n = n.parent) {
51
+ if (!ts.isArrayLiteralExpression(n)) continue;
52
+ const call = n.parent;
53
+ if (!ts.isCallExpression(call) || call.arguments[call.arguments.length - 1] !== n) continue;
54
+ const hook = hookCalleeName(call.expression);
55
+ if (hook !== undefined && DEPS_HOOKS.has(hook)) return { kind: "hook-dep", hook };
56
+ }
57
+
58
+ // 2 — value of a JSX attribute, unless a function boundary intervenes.
59
+ for (let n = refExpr.parent; n && n !== bodyNode; n = n.parent) {
60
+ if (isFunctionBoundary(n)) break;
61
+ if (!ts.isJsxAttribute(n)) continue;
62
+ const tag = owningTag(n);
63
+ return {
64
+ kind: /^[A-Z]/.test(tag) ? "passed-to-child" : "jsx-attr",
65
+ tag,
66
+ attr: attrNameText(n.name),
67
+ };
68
+ }
69
+
70
+ // 3 — expression child of an element or fragment (nearest JsxExpression only).
71
+ for (let n = refExpr.parent; n && n !== bodyNode; n = n.parent) {
72
+ if (!ts.isJsxExpression(n)) continue;
73
+ if (ts.isJsxElement(n.parent)) {
74
+ return { kind: "jsx-child", tag: tagText(n.parent.openingElement.tagName) };
75
+ }
76
+ if (ts.isJsxFragment(n.parent)) return { kind: "jsx-child", tag: "<fragment>" };
77
+ break;
78
+ }
79
+
80
+ // 4 — the reference itself is called.
81
+ const parent = refExpr.parent;
82
+ if (parent && ts.isCallExpression(parent) && parent.expression === refExpr) {
83
+ return { kind: "call" };
84
+ }
85
+
86
+ // 5 — inside any argument of a custom-hook call.
87
+ for (let n = refExpr; n !== bodyNode && n.parent; n = n.parent) {
88
+ const p = n.parent;
89
+ if (!ts.isCallExpression(p) || !p.arguments.some((a) => a === n)) continue;
90
+ const hook = hookCalleeName(p.expression);
91
+ if (hook !== undefined && /^use[A-Z]/.test(hook)) return { kind: "hook-arg", hook };
92
+ }
93
+
94
+ // 6 — receiver of a property access (`prop.member`).
95
+ if (parent && ts.isPropertyAccessExpression(parent) && parent.expression === refExpr) {
96
+ return { kind: "member-access" };
97
+ }
98
+
99
+ // 7 — flows into a branching condition before any function boundary.
100
+ for (let n = refExpr; n !== bodyNode && n.parent; n = n.parent) {
101
+ const p = n.parent;
102
+ if (isFunctionBoundary(p)) break;
103
+ if (ts.isIfStatement(p) && p.expression === n) return { kind: "conditional" };
104
+ if (ts.isConditionalExpression(p) && p.condition === n) return { kind: "conditional" };
105
+ if (
106
+ ts.isBinaryExpression(p) &&
107
+ p.left === n &&
108
+ (p.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken ||
109
+ p.operatorToken.kind === ts.SyntaxKind.BarBarToken)
110
+ ) {
111
+ return { kind: "conditional" };
112
+ }
113
+ if (ts.isSwitchStatement(p) && p.expression === n) return { kind: "conditional" };
114
+ }
115
+
116
+ return { kind: "other" };
117
+ }
118
+
119
+ /**
120
+ * `prop.a.b` → ["a","b"]; applies to the `props.x` access node for viaParam
121
+ * refs. A {} floor survives one hop and dies on the second, so the FULL
122
+ * path is the evidence — `drop.body.length` needs the head to carry a value.
123
+ */
124
+ function memberChain(refExpr: ts.Node): string[] | undefined {
125
+ const out: string[] = [];
126
+ let n: ts.Node = refExpr;
127
+ while (n.parent && ts.isPropertyAccessExpression(n.parent) && n.parent.expression === n) {
128
+ out.push(n.parent.name.text);
129
+ n = n.parent;
130
+ }
131
+ return out.length > 0 ? out : undefined;
132
+ }
133
+
134
+ function isFunctionBoundary(n: ts.Node): boolean {
135
+ return ts.isArrowFunction(n) || ts.isFunctionExpression(n) || ts.isFunctionDeclaration(n);
136
+ }
137
+
138
+ function owningTag(attr: ts.JsxAttribute): string {
139
+ const owner = attr.parent.parent;
140
+ return ts.isJsxOpeningElement(owner) || ts.isJsxSelfClosingElement(owner)
141
+ ? tagText(owner.tagName)
142
+ : "<dynamic>";
143
+ }
144
+
145
+ function attrNameText(name: ts.JsxAttributeName): string {
146
+ return ts.isIdentifier(name) ? name.text : `${name.namespace.text}:${name.name.text}`;
147
+ }
148
+
149
+ function tagText(tag: ts.JsxTagNameExpression): string {
150
+ if (ts.isIdentifier(tag)) return tag.text;
151
+ if (ts.isPropertyAccessExpression(tag)) return propertyAccessText(tag);
152
+ return "<dynamic>";
153
+ }
154
+
155
+ function propertyAccessText(p: ts.PropertyAccessExpression): string {
156
+ const head = ts.isIdentifier(p.expression)
157
+ ? p.expression.text
158
+ : ts.isPropertyAccessExpression(p.expression)
159
+ ? propertyAccessText(p.expression)
160
+ : "<dynamic>";
161
+ return `${head}.${p.name.text}`;
162
+ }