Skip to content

Commit ce51c6f

Browse files
Develop (#12)
* initiated dev environment * ops: updated SOnar name * ops (ci): standardize publish validation and dependabot across all packages - Replace git tag --list strategy with package.json-driven tag validation in all 16 publish workflows; use git rev-parse to verify the exact tag exists rather than guessing the latest repo-wide tag - Update error guidance to reflect feat/** → develop → master flow - Standardize dependabot to npm-only, grouped, monthly cadence across all 16 packages; remove github-actions ecosystem updates - Add missing dependabot.yml to AuthKit-UI, ChartKit-UI, HealthKit, HooksKit, paymentkit, StorageKit * chore(COMPT-138): apply repository-wide prettier baseline (#4) - Run prettier --write across repository - No logic/behavior changes - Unblocks CI PR Validation format gate for feature PRs - verify passes: lint + typecheck + tests * Feat/compt 30 state storage hooks (#6) * feat(COMPT-30): add useDebounce, useLocalStorage, useSessionStorage hooks - useDebounce<T>(value, delay): returns debounced value, resets timer on value/delay change - useLocalStorage<T>(key, initial): syncs with localStorage, SSR-safe, JSON serialization - useSessionStorage<T>(key, initial): same pattern for sessionStorage - Shared storage.ts helper with readStorageValue/writeStorageValue (SSR guard + parse fallback) - All three exported from src/hooks/index.ts -> src/index.ts - Full test coverage: timer reset, JSON sync, parse error fallback, SSR guard - tsc --noEmit passes, lint passes (0 warnings), 13/13 tests pass * chore(COMPT-30): add changeset, update copilot-instructions, fix husky pre-commit - .changeset/COMPT-30-state-storage-hooks.md: minor bump summary for 0.0.1 release - .github/instructions/copilot-instructions.md: updated to HooksKit package identity, real src structure with COMPT-30 hooks marked, COMPT-XX branch naming convention - .husky/pre-commit: removed deprecated husky v9 shebang lines (breaks in v10) * Feat/compt 31 dom event hooks (#8) * feat(COMPT-31): add useMediaQuery, useWindowSize, useClickOutside, useIntersectionObserver - useMediaQuery(query): tracks matchMedia via useSyncExternalStore, SSR-safe (server snapshot false) - useWindowSize(): returns {width, height}, debounced 100ms on resize, SSR-safe ({0,0}) - useClickOutside(ref, handler): fires on mousedown/touchstart outside ref; handler via ref pattern - useIntersectionObserver(ref, options?): IntersectionObserverEntry|null, disconnects on unmount - All listeners registered in useEffect with cleanup return - All SSR-safe: typeof window === undefined guards - Zero runtime dependencies - tsc --noEmit passes, lint passes (0 warnings), 26/26 tests pass, coverage >= 95% - All four exported from src/hooks/index.ts -> src/index.ts - Changeset added, copilot-instructions.md updated for epic COMPT-2 * test(COMPT-31): reduce duplicated test blocks for Sonar quality gate - remove accidental duplicated useMediaQuery suite block - extract shared viewport setup in useWindowSize tests - extract shared mount helper in useClickOutside tests - keep behavior coverage unchanged * Feat/compt 32 async lifecycle hooks (#9) * feat(COMPT-32): add usePrevious, useToggle, useInterval, useTimeout, useIsFirstRender - usePrevious<T>(value): previous render value via state-derivation; undefined on first render - useToggle(initial?): boolean toggle with stable useCallback reference - useInterval(callback, delay|null): fires at cadence, stops on null, latest callback via ref - useTimeout(callback, delay|null): fires once, cancels on null or unmount, latest callback via ref - useIsFirstRender(): true only on first render (scoped eslint-disable for intentional ref access) - All timer cleanup in useEffect return — StrictMode safe - Zero runtime deps; tsc --noEmit passes, lint passes, 25/25 tests, hooks coverage >= 98% - All five exported from src/hooks/index.ts -> src/index.ts - Changeset added, copilot-instructions.md updated with all three COMPT groups complete * refactor(COMPT-32): move hook tests to src/hooks/__tests__/ - Moved all 5 hook test files from src/hooks/ to src/hooks/__tests__/ - Updated relative imports from ./hook to ../hook - No logic changes; all 25 tests still pass * test(COMPT-33): consolidate all hook tests into src/hooks/__tests__/ (#10) - Move useDebounce, useLocalStorage, useSessionStorage, useMediaQuery, useWindowSize, useClickOutside, useIntersectionObserver tests to __tests__/ - Update relative imports from ./ to ../ - All 12 hooks covered: fake timers for debounce/interval/timeout/windowSize, mock matchMedia, mock IntersectionObserver, storage parse-error guards - 55 tests passing, 97.44% line coverage (>= 85% AC) * security: added CODEOWNER file for branches security * ops: updated release check workflow * ops: updated relese check workflow# * feat(COMPT-34): README, v0.1.0 version bump, publish preparation (#11) - Full README with installation, SSR note, 12 hook examples with types - Remove __hooks_placeholder from hooks barrel - Fix COMPT-30 changeset package name (reactts-developerkit -> hooks-kit) - Apply changeset version bump: 0.0.0 -> 0.1.0 - Remove duplicate root-level test files (already in __tests__/) - Update copilot-instructions.md with COMPT-34 status Co-authored-by: a-elkhiraooui-ciscode <a.elkhiraoui@ciscod.com> * ci: update release check workflow * ops: updated release check jobs. * v0.1.0 * fix(ci): correct sonar test directory and inclusion patterns --------- Co-authored-by: Zaiidmo <zaiidmoumnii@gmail.com> Co-authored-by: Zaiid Moumni <141942826+Zaiidmo@users.noreply.github.com>
1 parent 4a2a6a3 commit ce51c6f

37 files changed

Lines changed: 2039 additions & 126 deletions

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @CISCODE-MA/devops

.github/dependabot.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: npm
4+
directory: '/'
5+
schedule:
6+
interval: monthly
7+
open-pull-requests-limit: 1
8+
groups:
9+
npm-dependencies:
10+
patterns:
11+
- '*'
12+
assignees:
13+
- CISCODE-MA/cloud-devops
14+
labels:
15+
- 'dependencies'
16+
- 'npm'
17+
commit-message:
18+
prefix: 'chore(deps)'
19+
include: 'scope'
20+
rebase-strategy: auto

.github/instructions/copilot-instructions.md

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,82 @@
1-
# Copilot Instructions - React Component Library
1+
# Copilot Instructions - HooksKit
22

3-
> **Purpose**: Development guidelines for React component libraries - reusable, well-structured components for modern apps.
3+
> **Purpose**: Development guidelines for HooksKit — production-ready React hooks with zero runtime deps.
44
55
---
66

77
## 🎯 Module Overview
88

9-
**Package**: `@ciscode/ui-components` (example)
10-
**Type**: React Component Library
9+
**Package**: `@ciscode/hooks-kit`
10+
**Epic**: COMPT-2 — HooksKit
11+
**Type**: React Hooks Library
1112
**Framework**: React 18+, TypeScript 5+
12-
**Build**: Vite/tsup
13+
**Build**: tsup
1314
**Testing**: Vitest + React Testing Library
1415
**Distribution**: NPM package
15-
**Purpose**: Reusable, production-ready React components for building modern UIs
16+
**Purpose**: 12 production-ready React hooks. Zero runtime deps. SSR-safe.
1617

17-
### Typical Module Responsibilities:
18+
### Hook Groups:
1819

19-
- Atomic UI components (Button, Input, Card, etc.)
20-
- Composite components (Form, Modal, Navigation, etc.)
21-
- Hooks for common patterns
22-
- Type definitions and props interfaces
23-
- Accessibility compliance (WCAG 2.1 AA)
24-
- Theming and customization
25-
- Comprehensive documentation
20+
- **State & Storage** (COMPT-30 ✅) — `useDebounce`, `useLocalStorage`, `useSessionStorage`
21+
- **DOM & Events** (COMPT-31 ✅) — `useMediaQuery`, `useWindowSize`, `useClickOutside`, `useIntersectionObserver`
22+
- **Async & Lifecycle** (COMPT-32 ✅) — `usePrevious`, `useToggle`, `useInterval`, `useTimeout`, `useIsFirstRender`
23+
- **Test Suite** (COMPT-33 ✅) — Full coverage for all 12 hooks, all tests in `src/hooks/__tests__/`
24+
- **README & Publish** (COMPT-34 ✅) — Full README with usage examples, v0.1.0 published to `@ciscode/hooks-kit`
25+
26+
### Module Responsibilities:
27+
28+
- Generic, fully-typed hooks with inference at call site
29+
- SSR-safe (`typeof window === 'undefined'` guards in every DOM hook)
30+
- Zero runtime dependencies
31+
- All listeners registered in `useEffect` and cleaned up on unmount
32+
- WCAG-accessible patterns where applicable
33+
- Hooks ≥ 90% coverage
2634

2735
---
2836

2937
## 🏗️ Module Structure
3038

3139
```
3240
src/
33-
├── components/ # React components
34-
│ ├── Button/
35-
│ │ ├── Button.tsx # Component
36-
│ │ ├── Button.test.tsx # Tests
37-
│ │ ├── Button.types.ts # Props types
38-
│ │ └── index.ts # Exports
39-
│ ├── Input/
40-
│ ├── Modal/
41-
│ └── Form/
42-
├── hooks/ # Custom hooks
43-
│ ├── useModal.ts
44-
│ ├── useForm.ts
45-
│ └── useModal.test.ts
46-
├── context/ # Context providers
47-
│ ├── ThemeContext.tsx
48-
│ └── FormContext.tsx
49-
├── types/ # TypeScript types
50-
│ └── common.types.ts
51-
├── utils/ # Utilities
52-
│ └── classNameUtils.ts
53-
└── index.ts # Public API
41+
├── components/ # Minimal supporting components
42+
│ ├── NoopButton.tsx
43+
│ └── index.ts
44+
├── hooks/ # All public hooks
45+
│ ├── useDebounce.ts # COMPT-30 ✅
46+
│ ├── useLocalStorage.ts # COMPT-30 ✅
47+
│ ├── useSessionStorage.ts # COMPT-30 ✅
48+
│ ├── storage.ts # Internal SSR-safe storage helper
49+
│ ├── useMediaQuery.ts # COMPT-31 ✅
50+
│ ├── useWindowSize.ts # COMPT-31 ✅
51+
│ ├── useClickOutside.ts # COMPT-31 ✅
52+
│ ├── useIntersectionObserver.ts # COMPT-31 ✅
53+
│ ├── usePrevious.ts # COMPT-32 ✅
54+
│ ├── useToggle.ts # COMPT-32 ✅
55+
│ ├── useInterval.ts # COMPT-32 ✅
56+
│ ├── useTimeout.ts # COMPT-32 ✅
57+
│ ├── useIsFirstRender.ts # COMPT-32 ✅
58+
│ ├── index.ts # Hook barrel
59+
│ └── __tests__/ # All hook tests (COMPT-33 ✅)
60+
│ ├── useDebounce.test.ts
61+
│ ├── useLocalStorage.test.ts
62+
│ ├── useSessionStorage.test.ts
63+
│ ├── useMediaQuery.test.ts
64+
│ ├── useWindowSize.test.ts
65+
│ ├── useClickOutside.test.ts
66+
│ ├── useIntersectionObserver.test.ts
67+
│ ├── usePrevious.test.ts
68+
│ ├── useToggle.test.ts
69+
│ ├── useInterval.test.ts
70+
│ ├── useTimeout.test.ts
71+
│ └── useIsFirstRender.test.ts
72+
├── utils/ # Framework-agnostic utils
73+
│ ├── noop.ts
74+
│ └── index.ts
75+
└── index.ts # Public API (only entry point)
5476
```
5577

78+
> ⚠️ Only export from `src/index.ts`. Deep imports are forbidden.
79+
5680
---
5781

5882
## 📝 Naming Conventions
@@ -277,18 +301,17 @@ export type { ButtonProps, ModalProps, InputProps, FormProps } from './component
277301
**1. Branch Creation:**
278302

279303
```bash
280-
feature/UI-MODULE-123-add-datepicker
281-
bugfix/UI-MODULE-456-fix-modal-focus
282-
refactor/UI-MODULE-789-extract-button-styles
304+
feat/COMPT-30-state-storage-hooks
305+
bugfix/COMPT-XX-short-description
283306
```
284307

285-
**2. Task Documentation:**
308+
> Branch names must reference the Jira ticket (COMPT-XX format). Pull from `develop` before opening PR.
286309
287-
Create task file:
310+
**PR targets:**
288311

289-
```
290-
docs/tasks/active/UI-MODULE-123-add-datepicker.md
291-
```
312+
- Feature branches → `develop`
313+
- `develop``master` on Friday release only
314+
- Never open a PR directly to `master`
292315

293316
**Task structure:**
294317

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: CI - PR Validation
2+
3+
on:
4+
pull_request:
5+
branches: [develop]
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
validate:
12+
name: CI - PR Validation
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
19+
- name: Setup Node
20+
uses: actions/setup-node@v4
21+
with:
22+
node-version: 22
23+
cache: npm
24+
25+
- name: Install
26+
run: npm ci
27+
28+
- name: Format (check)
29+
run: npm run format
30+
31+
- name: Lint
32+
run: npm run lint
33+
34+
- name: Typecheck
35+
run: npm run typecheck
36+
37+
- name: Test
38+
run: npm test
39+
40+
- name: Build
41+
run: npm run build

.github/workflows/publish.yml

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,52 @@ jobs:
2020
with:
2121
fetch-depth: 0
2222

23-
- name: Validate tag exists on this push
23+
- name: Validate version tag and package.json
2424
run: |
25-
TAG=$(git describe --exact-match --tags HEAD 2>/dev/null || echo "")
26-
if [[ -z "$TAG" ]]; then
27-
echo "❌ No tag found on HEAD. This push did not include a version tag."
28-
echo "To publish, merge to master with a tag: git tag v1.0.0 && git push origin master --tags"
25+
PKG_VERSION=$(grep '"version"' package.json | head -1 | sed 's/.*"version": "\([^"]*\)".*/\1/')
26+
TAG="v${PKG_VERSION}"
27+
28+
if [[ -z "$PKG_VERSION" ]]; then
29+
echo "❌ ERROR: Could not read version from package.json"
2930
exit 1
3031
fi
32+
3133
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
32-
echo "❌ Invalid tag format: $TAG. Expected: v*.*.*"
34+
echo "❌ ERROR: Invalid version format in package.json: '$PKG_VERSION'"
35+
echo "Expected format: x.y.z (e.g., 1.0.0, 0.2.3)"
36+
exit 1
37+
fi
38+
39+
if ! git rev-parse "$TAG" >/dev/null 2>&1; then
40+
echo "❌ ERROR: Tag $TAG not found!"
41+
echo ""
42+
echo "This typically happens when:"
43+
echo " 1. You forgot to run 'npm version patch|minor|major' on your feature branch"
44+
echo " 2. You didn't push the tag: git push origin <feat/your-feature> --tags"
45+
echo " 3. The tag was created locally but never pushed to remote"
46+
echo ""
47+
echo "📋 Correct workflow:"
48+
echo " 1. On feat/** or feature/**: npm version patch (or minor/major)"
49+
echo " 2. Push branch + tag: git push origin feat/your-feature --tags"
50+
echo " 3. PR feat/** → develop, then PR develop → master"
51+
echo " 4. Workflow automatically triggers on master push"
52+
echo ""
3353
exit 1
3454
fi
35-
echo "✅ Valid tag found: $TAG"
55+
56+
echo "✅ package.json version: $PKG_VERSION"
57+
echo "✅ Tag $TAG exists in repo"
3658
echo "TAG_VERSION=$TAG" >> $GITHUB_ENV
3759
3860
- name: Setup Node.js
3961
uses: actions/setup-node@v4
4062
with:
41-
node-version: '20'
63+
node-version: '22'
4264
registry-url: 'https://registry.npmjs.org'
43-
cache: npm
65+
cache: 'npm'
4466

4567
- name: Install dependencies
46-
run: npm install
68+
run: npm ci
4769

4870
- name: Build
4971
run: npm run build --if-present
@@ -55,6 +77,6 @@ jobs:
5577
run: npm test --if-present 2>/dev/null || true
5678

5779
- name: Publish to NPM
58-
run: npm publish --access public --no-git-checks
80+
run: npm publish --access public --provenance
5981
env:
6082
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

0 commit comments

Comments
 (0)