gin-skills 1.0.4 → 1.0.5

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.
@@ -689,7 +689,7 @@
689
689
  <div class="container">
690
690
  <div class="hero-badge fade-up">
691
691
  <span class="dot"></span>
692
- <!-- AUTO:BADGE -->v1.0.3 &mdash; 17 Skills &middot; 6 Agents<!-- /AUTO:BADGE -->
692
+ <!-- AUTO:BADGE -->v1.0.4 &mdash; 17 Skills &middot; 6 Agents<!-- /AUTO:BADGE -->
693
693
  </div>
694
694
  <h1 class="fade-up"><span>Supercharge</span> Claude Code<br>with One Command</h1>
695
695
  <p class="hero-sub fade-up">
@@ -1220,7 +1220,7 @@
1220
1220
  <footer class="footer">
1221
1221
  <div class="container">
1222
1222
  <div class="footer-content">
1223
- <div class="footer-brand">GinStudio Skills v1.0.3</div>
1223
+ <div class="footer-brand">GinStudio Skills v1.0.4</div>
1224
1224
  <div class="footer-links">
1225
1225
  <a href="https://www.npmjs.com/package/gin-skills" target="_blank" rel="noopener">npm</a>
1226
1226
  <a href="https://github.com/vuduynhiennn/ginskills" target="_blank" rel="noopener">GitHub</a>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gin-skills",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Install GinStudio skills and agents for Claude Code",
5
5
  "homepage": "https://skills.ginstudio.asia",
6
6
  "repository": {
@@ -8,8 +8,18 @@ echo "================================"
8
8
 
9
9
  # console.log without __DEV__ guard
10
10
  # Escalates to ERROR when on gesture/animation hot paths (60fps concern)
11
+ # Projects using a custom logger (e.g. appLog) should prefer that over raw console.log
11
12
  echo ""
12
13
  echo "--- console.log Without __DEV__ Guard ---"
14
+
15
+ # Auto-detect custom logger: check if the project has an appLog/logger utility
16
+ CUSTOM_LOGGER=""
17
+ CUSTOM_LOGGER_IMPORT=""
18
+ if grep -rql --include="*.ts" --include="*.tsx" 'export const appLog' "$DIR" 2>/dev/null; then
19
+ CUSTOM_LOGGER="appLog"
20
+ CUSTOM_LOGGER_IMPORT='import { appLog } from "@/shared/utils/logger"'
21
+ fi
22
+
13
23
  grep -rn --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" \
14
24
  'console\.log(' "$DIR" 2>/dev/null \
15
25
  | grep -v node_modules | grep -v '__tests__' | grep -v '\.test\.' | grep -v '\.spec\.' \
@@ -28,10 +38,22 @@ grep -rn --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" \
28
38
  ! echo "$file_context" | grep -q '= __DEV__'; then
29
39
  # Check if this console.log is on a gesture/animation hot path (runs every frame)
30
40
  hot_path_context=$(sed -n "$((lineno > 20 ? lineno - 20 : 1)),${lineno}p" "$file" 2>/dev/null)
41
+ is_worklet=false
42
+ if echo "$hot_path_context" | grep -q '"worklet"\|'\''worklet'\'''; then
43
+ is_worklet=true
44
+ fi
31
45
  if echo "$hot_path_context" | grep -qE 'onUpdate|onActive|Pan\.|onMove|onScroll|onGestureEvent|Gesture\.|worklet|runOnJS|requestAnimationFrame|\.addListener'; then
32
- echo "$file:$lineno [ERROR] console.log on gesture/animation hot path (runs every frame at 60fps) → Remove or wrap with __DEV__; serialization on hot paths causes jank"
46
+ if [ "$is_worklet" = true ]; then
47
+ echo "$file:$lineno — [ERROR] console.log in Reanimated worklet (runs on UI thread every frame) → Wrap with if (__DEV__) console.log(...); appLog cannot run in worklets"
48
+ else
49
+ echo "$file:$lineno — [ERROR] console.log on gesture/animation hot path (runs every frame at 60fps) → Remove or replace with ${CUSTOM_LOGGER:-__DEV__ guard}; serialization on hot paths causes jank"
50
+ fi
33
51
  else
34
- echo "$file:$lineno — [WARN] console.log without __DEV__ guard → Wrap with if (__DEV__) or use babel-plugin-transform-remove-console"
52
+ if [ -n "$CUSTOM_LOGGER" ]; then
53
+ echo "$file:$lineno — [WARN] raw console.log instead of project logger → Replace with $CUSTOM_LOGGER.debug(...) which is dev-only by default"
54
+ else
55
+ echo "$file:$lineno — [WARN] console.log without __DEV__ guard → Wrap with if (__DEV__) or use babel-plugin-transform-remove-console"
56
+ fi
35
57
  fi
36
58
  ISSUES=$((ISSUES + 1))
37
59
  fi
@@ -54,7 +76,11 @@ grep -rn --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" \
54
76
  file_context=$(sed -n "1,$((lineno - 1))p" "$file" 2>/dev/null)
55
77
  if ! echo "$context" | grep -q '__DEV__\|if.*DEV' && \
56
78
  ! echo "$file_context" | grep -q '= __DEV__'; then
57
- echo "$file:$lineno — [WARN] console.warn without __DEV__ guard → Wrap with if (__DEV__) or suppress in production logger"
79
+ if [ -n "$CUSTOM_LOGGER" ]; then
80
+ echo "$file:$lineno — [WARN] raw console.warn instead of project logger → Replace with $CUSTOM_LOGGER.warn(...) which is dev-only by default"
81
+ else
82
+ echo "$file:$lineno — [WARN] console.warn without __DEV__ guard → Wrap with if (__DEV__) or suppress in production logger"
83
+ fi
58
84
  ISSUES=$((ISSUES + 1))
59
85
  fi
60
86
  done
@@ -68,7 +94,11 @@ grep -rn --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" \
68
94
  | grep -v '__DEV__\|Sentry\|crashlytics\|bugsnag' \
69
95
  | while IFS= read -r line; do
70
96
  file_loc=$(echo "$line" | cut -d: -f1,2)
71
- echo "$file_loc — [INFO] console.error in production code → Use a crash reporting SDK (Sentry/Crashlytics) instead of console.error"
97
+ if [ -n "$CUSTOM_LOGGER" ]; then
98
+ echo "$file_loc — [INFO] raw console.error → Replace with $CUSTOM_LOGGER.error(...) or use a crash reporting SDK (Sentry/Crashlytics)"
99
+ else
100
+ echo "$file_loc — [INFO] console.error in production code → Use a crash reporting SDK (Sentry/Crashlytics) instead of console.error"
101
+ fi
72
102
  ISSUES=$((ISSUES + 1))
73
103
  done
74
104
 
@@ -80,7 +110,11 @@ grep -rn --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" \
80
110
  | grep -v node_modules | grep -v '__tests__' | grep -v '\.test\.' | grep -v '\.spec\.' \
81
111
  | while IFS= read -r line; do
82
112
  file_loc=$(echo "$line" | cut -d: -f1,2)
83
- echo "$file_loc — [WARN] console.info/debug in production code → Remove or guard with if (__DEV__)"
113
+ if [ -n "$CUSTOM_LOGGER" ]; then
114
+ echo "$file_loc — [WARN] raw console.info/debug → Replace with $CUSTOM_LOGGER.debug(...) which is dev-only by default"
115
+ else
116
+ echo "$file_loc — [WARN] console.info/debug in production code → Remove or guard with if (__DEV__)"
117
+ fi
84
118
  ISSUES=$((ISSUES + 1))
85
119
  done
86
120
 
@@ -147,6 +181,7 @@ grep -rn --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" \
147
181
  done
148
182
 
149
183
  # Production-critical logic inside __DEV__ blocks (anti-pattern)
184
+ # Skip __DEV__ blocks that only contain console.log (this is the correct pattern for worklet code)
150
185
  echo ""
151
186
  echo "--- Production Logic Inside __DEV__ Block ---"
152
187
  grep -rn --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" \
@@ -156,6 +191,11 @@ grep -rn --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" \
156
191
  file=$(echo "$line" | cut -d: -f1)
157
192
  lineno=$(echo "$line" | cut -d: -f2)
158
193
  context=$(sed -n "${lineno},$((lineno + 10))p" "$file" 2>/dev/null)
194
+ # Skip if the __DEV__ block only wraps console.log/warn/error (that's the correct pattern)
195
+ match_line=$(sed -n "${lineno}p" "$file" 2>/dev/null)
196
+ if echo "$match_line" | grep -q 'console\.\(log\|warn\|error\|debug\|info\)'; then
197
+ continue
198
+ fi
159
199
  if echo "$context" | grep -q 'navigate\|dispatch\|setState\|fetch(\|api\.'; then
160
200
  echo "$file:$lineno — [WARN] Production-critical logic inside __DEV__ block → State changes/navigation inside __DEV__ blocks will not run in production; this may be a bug"
161
201
  ISSUES=$((ISSUES + 1))
@@ -243,6 +243,29 @@ grep -rln --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js"
243
243
  fi
244
244
  done
245
245
 
246
+ # AbortSignal.addEventListener("abort", ...) without { once: true }
247
+ # When composing AbortControllers (e.g. timeout + user cancel), each listener on the
248
+ # upstream signal accumulates if not cleaned up. { once: true } auto-removes after firing.
249
+ echo ""
250
+ echo "--- AbortSignal addEventListener Without { once: true } ---"
251
+ grep -rn --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" \
252
+ '\.addEventListener.*abort' "$DIR" 2>/dev/null \
253
+ | grep -v node_modules | grep -v '__tests__' | grep -v '\.test\.' | grep -v '\.spec\.' \
254
+ | while IFS= read -r line; do
255
+ file=$(echo "$line" | cut -d: -f1)
256
+ lineno=$(echo "$line" | cut -d: -f2)
257
+ match_text=$(echo "$line" | cut -d: -f3-)
258
+ # Check if { once: true } is present on the same line or within the next 2 lines
259
+ context=$(sed -n "${lineno},$((lineno + 2))p" "$file" 2>/dev/null)
260
+ if ! echo "$context" | grep -q 'once.*true\|{ once: true }'; then
261
+ # Check if there's a matching removeEventListener for cleanup
262
+ if ! grep -q 'removeEventListener.*abort' "$file"; then
263
+ echo "$file:$lineno — [WARN] addEventListener(\"abort\", fn) without { once: true } → Listeners accumulate on reused signals causing memory leak; add { once: true } as 3rd arg or call removeEventListener in cleanup"
264
+ ISSUES=$((ISSUES + 1))
265
+ fi
266
+ fi
267
+ done
268
+
246
269
  # Reanimated useAnimatedReaction without cancelAnimation cleanup
247
270
  echo ""
248
271
  echo "--- useAnimatedReaction Without cancelAnimation Cleanup ---"