@mr.dj2u/doctor 0.1.5 → 0.1.6

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.
@@ -0,0 +1,4 @@
1
+ import type { DoctorCheckResult } from '../types.js';
2
+ export declare function checkAnimationPerformance(projectPath: string): Promise<DoctorCheckResult>;
3
+ export declare function scanFileAnimationPerformance(projectPath: string, filePath: string): Promise<DoctorCheckResult>;
4
+ //# sourceMappingURL=animation-performance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animation-performance.d.ts","sourceRoot":"","sources":["../../src/checks/animation-performance.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AASrD,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA2C/F;AAED,wBAAsB,4BAA4B,CAChD,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,iBAAiB,CAAC,CAuB5B"}
@@ -0,0 +1,115 @@
1
+ import path from 'node:path';
2
+ import { findFiles, pathExists, readOptionalText, relative, SOURCE_EXTENSIONS } from '../utils.js';
3
+ const ANIMATION_SIGNAL_RE = /\b(react-native-reanimated|useAnimatedStyle|useSharedValue|useAnimatedScrollHandler|interpolate|withTiming|withSpring|Animated\.|LottieView|FadeIn|FadeOut|LinearTransition|layout=|entering=|exiting=)\b/u;
4
+ const PERFORMANCE_NOTE_RE = /\b(animation performance|motion budget|performance note|motion note|parallax budget|release build|scroll budget)\b/i;
5
+ export async function checkAnimationPerformance(projectPath) {
6
+ if (!(await pathExists(projectPath))) {
7
+ return {
8
+ name: 'animation performance',
9
+ status: 'skip',
10
+ message: 'Project path does not exist, so animation checks were skipped.',
11
+ };
12
+ }
13
+ const sourceFiles = await findFiles(projectPath, (filePath) => SOURCE_EXTENSIONS.has(path.extname(filePath)));
14
+ const findings = [];
15
+ let scannedAnimatedFiles = 0;
16
+ for (const filePath of sourceFiles) {
17
+ const contents = await readOptionalText(filePath);
18
+ if (!contents || !ANIMATION_SIGNAL_RE.test(contents)) {
19
+ continue;
20
+ }
21
+ scannedAnimatedFiles += 1;
22
+ findings.push(...scanAnimationFile(projectPath, filePath, contents));
23
+ }
24
+ if (findings.length > 0) {
25
+ return {
26
+ name: 'animation performance',
27
+ status: 'warn',
28
+ message: 'Animation-heavy files have motion budget warnings.',
29
+ details: {
30
+ findings: findings.slice(0, 50),
31
+ truncated: findings.length > 50,
32
+ scannedAnimatedFiles,
33
+ },
34
+ };
35
+ }
36
+ return {
37
+ name: 'animation performance',
38
+ status: scannedAnimatedFiles > 0 ? 'pass' : 'skip',
39
+ message: scannedAnimatedFiles > 0
40
+ ? 'Animation-heavy files passed the lightweight motion scan.'
41
+ : 'No animation-heavy files detected.',
42
+ };
43
+ }
44
+ export async function scanFileAnimationPerformance(projectPath, filePath) {
45
+ const contents = (await readOptionalText(filePath)) ?? '';
46
+ if (!ANIMATION_SIGNAL_RE.test(contents)) {
47
+ return {
48
+ name: 'animation performance',
49
+ status: 'skip',
50
+ message: 'File does not contain animation-heavy signals.',
51
+ };
52
+ }
53
+ const findings = scanAnimationFile(projectPath, filePath, contents);
54
+ return findings.length > 0
55
+ ? {
56
+ name: 'animation performance',
57
+ status: 'warn',
58
+ message: 'File has animation performance warnings.',
59
+ details: { findings },
60
+ }
61
+ : {
62
+ name: 'animation performance',
63
+ status: 'pass',
64
+ message: 'File passed the lightweight motion scan.',
65
+ };
66
+ }
67
+ function scanAnimationFile(projectPath, filePath, contents) {
68
+ const findings = [];
69
+ const metrics = collectMetrics(contents);
70
+ const shortPath = relative(projectPath, filePath);
71
+ const isRouteFile = /(^|\/)(src\/)?app\//u.test(shortPath);
72
+ const hasPerformanceNote = PERFORMANCE_NOTE_RE.test(contents);
73
+ const scrollLinkedScore = metrics.interpolateCount + metrics.animatedStyleCount + metrics.scrollHandlerCount + metrics.parallaxHintCount;
74
+ if (metrics.repeatedMotionCount >= 4 &&
75
+ (metrics.flatListCount > 0 || metrics.mapCount > 0) &&
76
+ !hasPerformanceNote) {
77
+ findings.push(`${shortPath}: repeated animated rows or cards detected; add a motion budget note or simplify list-heavy motion.`);
78
+ }
79
+ if (metrics.parallaxHintCount > 0 &&
80
+ (scrollLinkedScore >= 10 || metrics.interpolateCount >= 6 || metrics.animatedStyleCount >= 4) &&
81
+ !hasPerformanceNote) {
82
+ findings.push(`${shortPath}: dense parallax or scroll-linked layers detected without a nearby motion/performance note.`);
83
+ }
84
+ if (isRouteFile &&
85
+ metrics.lineCount >= 260 &&
86
+ (metrics.interpolateCount + metrics.animatedStyleCount + metrics.sharedValueCount >= 8 ||
87
+ metrics.repeatedMotionCount >= 6)) {
88
+ findings.push(`${shortPath}: large route file mixes dense motion logic with route concerns; move interpolation-heavy logic into focused helpers or components.`);
89
+ }
90
+ if (metrics.lottieCount > 0 &&
91
+ metrics.lineCount >= 220 &&
92
+ metrics.repeatedMotionCount >= 6 &&
93
+ !hasPerformanceNote) {
94
+ findings.push(`${shortPath}: combines long-running animation with many other motion signals; confirm the scene has a measured release-build budget.`);
95
+ }
96
+ return findings;
97
+ }
98
+ function collectMetrics(contents) {
99
+ return {
100
+ lineCount: contents.split(/\r?\n/u).length,
101
+ interpolateCount: countMatches(contents, /\binterpolate\s*\(/gu),
102
+ animatedStyleCount: countMatches(contents, /\buseAnimatedStyle\s*\(/gu),
103
+ sharedValueCount: countMatches(contents, /\buseSharedValue\s*\(/gu),
104
+ scrollHandlerCount: countMatches(contents, /\b(useAnimatedScrollHandler|scrollEventThrottle|onScroll)\b/gu),
105
+ parallaxHintCount: countMatches(contents, /\b(parallax|scroll-linked|scroll linked|pinned|depth|layered|hero)\b/giu),
106
+ repeatedMotionCount: countMatches(contents, /\b(entering|exiting|layout)\s*=|<Animated\.|Fade(In|Out|Up|Down)|LinearTransition\b/gu),
107
+ flatListCount: countMatches(contents, /\b(FlatList|FlashList|SectionList)\b/gu),
108
+ mapCount: countMatches(contents, /\.map\s*\(/gu),
109
+ lottieCount: countMatches(contents, /\b(LottieView|lottie-react-native)\b/gu),
110
+ };
111
+ }
112
+ function countMatches(contents, pattern) {
113
+ return [...contents.matchAll(pattern)].length;
114
+ }
115
+ //# sourceMappingURL=animation-performance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animation-performance.js","sourceRoot":"","sources":["../../src/checks/animation-performance.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  export { checkAppArchitecture, scanFileAppArchitecture } from './app-architecture.js';
2
+ export { checkAnimationPerformance, scanFileAnimationPerformance, } from './animation-performance.js';
2
3
  export { checkEnvHygiene, scanFileEnvHygiene } from './env-hygiene.js';
3
4
  export { runEslintCheck } from './eslint.js';
4
5
  export { checkExpoConfiguration } from './expo-config.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/checks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/checks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EACL,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export { checkAppArchitecture, scanFileAppArchitecture } from './app-architecture.js';
2
+ export { checkAnimationPerformance, scanFileAnimationPerformance, } from './animation-performance.js';
2
3
  export { checkEnvHygiene, scanFileEnvHygiene } from './env-hygiene.js';
3
4
  export { runEslintCheck } from './eslint.js';
4
5
  export { checkExpoConfiguration } from './expo-config.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/checks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/checks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EACL,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG9D,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,YAAY,EACZ,WAAW,EACX,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CAkDvB;AAED,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,KAAK,CAAM,GACvC,OAAO,CAAC,YAAY,CAAC,CAEvB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG9D,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,YAAY,EACZ,WAAW,EACX,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CAmDvB;AAED,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,KAAK,CAAM,GACvC,OAAO,CAAC,YAAY,CAAC,CAEvB"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import path from 'node:path';
2
- import { checkAppArchitecture, checkEnvHygiene, checkExpoConfiguration, checkGitignoreEnv, checkPackageScripts, checkProjectDocs, checkSeoMetadata, checkStylingDependencies, checkTodoForContextMarkers, runScriptChecks, } from './checks/index.js';
2
+ import { checkAppArchitecture, checkAnimationPerformance, checkEnvHygiene, checkExpoConfiguration, checkGitignoreEnv, checkPackageScripts, checkProjectDocs, checkSeoMetadata, checkStylingDependencies, checkTodoForContextMarkers, runScriptChecks, } from './checks/index.js';
3
3
  import { createReport } from './reporter.js';
4
4
  import { pathExists, readPackageJson } from './utils.js';
5
5
  export { createReport, formatHumanReport, formatJsonReport } from './reporter.js';
@@ -34,6 +34,7 @@ export async function runDoctor(projectPath, options = {}) {
34
34
  checks.push(await checkExpoConfiguration(packageJson, resolvedProjectPath));
35
35
  checks.push(await checkEnvHygiene(resolvedProjectPath));
36
36
  checks.push(await checkAppArchitecture(resolvedProjectPath));
37
+ checks.push(await checkAnimationPerformance(resolvedProjectPath));
37
38
  checks.push(await checkSeoMetadata(resolvedProjectPath));
38
39
  if (options.runScripts !== false) {
39
40
  checks.push(...(await runScriptChecks({
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,wBAAwB,EACxB,0BAA0B,EAC1B,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAYzD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,WAAmB,EACnB,UAAyB,EAAE;IAE3B,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC;IACpC,MAAM,MAAM,GAAG,EAAE,CAAC;IAElB,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,OAAgB;YACxB,OAAO,EAAE,gCAAgC,mBAAmB,EAAE;SAC/D,CAAC,CAAC;QACH,OAAO,YAAY,CAAC,mBAAmB,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,cAAc,CAAC,CAAC;IACvE,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,eAAe,CAAC,CAAC;IAE3D,MAAM,CAAC,IAAI,CAAC,MAAM,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,CAAC;IACzD,MAAM,CAAC,IAAI,CAAC,MAAM,0BAA0B,CAAC,mBAAmB,CAAC,CAAC,CAAC;IACnE,MAAM,CAAC,IAAI,CAAC,MAAM,iBAAiB,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAE1D,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,MAAe;YACvB,OAAO,EAAE,4EAA4E;SACtF,CAAC,CAAC;QACH,OAAO,YAAY,CAAC,mBAAmB,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACnE,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,WAAW,CAAC,CAAC,CAAC;IACnD,MAAM,CAAC,IAAI,CAAC,MAAM,sBAAsB,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAC5E,MAAM,CAAC,IAAI,CAAC,MAAM,eAAe,CAAC,mBAAmB,CAAC,CAAC,CAAC;IACxD,MAAM,CAAC,IAAI,CAAC,MAAM,oBAAoB,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC7D,MAAM,CAAC,IAAI,CAAC,MAAM,yBAAyB,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAClE,MAAM,CAAC,IAAI,CAAC,MAAM,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAEzD,IAAI,OAAO,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;QACjC,MAAM,CAAC,IAAI,CACT,GAAG,CAAC,MAAM,eAAe,CAAC;YACxB,WAAW;YACX,WAAW,EAAE,mBAAmB;YAChC,IAAI;YACJ,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,KAAK;YACzB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,MAAO;SACxC,CAAC,CAAC,CACJ,CAAC;IACJ,CAAC;IAED,OAAO,YAAY,CAAC,mBAAmB,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,WAAmB,EACnB,UAAsC,EAAE;IAExC,OAAO,SAAS,CAAC,WAAW,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"scan-file.d.ts","sourceRoot":"","sources":["../src/scan-file.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGhE,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,YAAY,CAAC,CAqBvB"}
1
+ {"version":3,"file":"scan-file.d.ts","sourceRoot":"","sources":["../src/scan-file.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGhE,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,YAAY,CAAC,CAsBvB"}
package/dist/scan-file.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import path from 'node:path';
3
- import { scanFileAppArchitecture, scanFileEnvHygiene, scanFileSsrSafety } from './checks/index.js';
3
+ import { scanFileAnimationPerformance, scanFileAppArchitecture, scanFileEnvHygiene, scanFileSsrSafety, } from './checks/index.js';
4
4
  import { createReport } from './reporter.js';
5
5
  import { pathExists } from './utils.js';
6
6
  export async function scanFile(filePath, options = {}) {
@@ -19,6 +19,7 @@ export async function scanFile(filePath, options = {}) {
19
19
  scanFileEnvHygiene(projectPath, resolvedFilePath),
20
20
  scanFileSsrSafety(projectPath, resolvedFilePath),
21
21
  scanFileAppArchitecture(projectPath, resolvedFilePath),
22
+ scanFileAnimationPerformance(projectPath, resolvedFilePath),
22
23
  ]);
23
24
  return createReport(projectPath, 'fast', checks);
24
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scan-file.js","sourceRoot":"","sources":["../src/scan-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACnG,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,QAAgB,EAChB,UAA2B,EAAE;IAE7B,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,IAAI,eAAe,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAE3F,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC;QAC1C,OAAO,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE;YACvC;gBACE,IAAI,EAAE,WAAW;gBACjB,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,6BAA6B,gBAAgB,EAAE;aACzD;SACF,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC/B,kBAAkB,CAAC,WAAW,EAAE,gBAAgB,CAAC;QACjD,iBAAiB,CAAC,WAAW,EAAE,gBAAgB,CAAC;QAChD,uBAAuB,CAAC,WAAW,EAAE,gBAAgB,CAAC;KACvD,CAAC,CAAC;IAEH,OAAO,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACvC,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrC,OAAO,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;YACnD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"scan-file.js","sourceRoot":"","sources":["../src/scan-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,QAAgB,EAChB,UAA2B,EAAE;IAE7B,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,IAAI,eAAe,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAE3F,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC;QAC1C,OAAO,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE;YACvC;gBACE,IAAI,EAAE,WAAW;gBACjB,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,6BAA6B,gBAAgB,EAAE;aACzD;SACF,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC/B,kBAAkB,CAAC,WAAW,EAAE,gBAAgB,CAAC;QACjD,iBAAiB,CAAC,WAAW,EAAE,gBAAgB,CAAC;QAChD,uBAAuB,CAAC,WAAW,EAAE,gBAAgB,CAAC;QACtD,4BAA4B,CAAC,WAAW,EAAE,gBAAgB,CAAC;KAC5D,CAAC,CAAC;IAEH,OAAO,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACvC,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrC,OAAO,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;YACnD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mr.dj2u/doctor",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Production Doctor: multi-check engine for Expo apps (lint, tsc, expo doctor, architecture)",
5
5
  "type": "module",
6
6
  "bin": {