refactor: flatten Microsoft skills from nested to flat directory structure
Rewrote sync_microsoft_skills.py (v4) to use each SKILL.md's frontmatter 'name' field as the flat directory name under skills/, replacing the nested skills/official/microsoft/<lang>/<category>/<service>/ hierarchy. This fixes CI failures caused by the indexing, validation, and catalog scripts expecting skills/<id>/SKILL.md (depth 1). Changes: - Rewrite scripts/sync_microsoft_skills.py for flat output with collision detection - Update scripts/tests/inspect_microsoft_repo.py for flat name mapping - Update scripts/tests/test_comprehensive_coverage.py for name uniqueness checks - Delete skills/official/ nested directory - Add 129 Microsoft skills as flat directories (e.g. skills/azure-mgmt-botservice-dotnet/) - Move attribution files to docs/ (LICENSE-MICROSOFT, microsoft-skills-attribution.json) - Rebuild skills_index.json, CATALOG.md, README.md (845 total skills)
This commit is contained in:
68
skills/zustand-store-ts/SKILL.md
Normal file
68
skills/zustand-store-ts/SKILL.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
name: zustand-store-ts
|
||||
description: Create Zustand stores with TypeScript, subscribeWithSelector middleware, and proper state/action separation. Use when building React state management, creating global stores, or implementing reactive state patterns with Zustand.
|
||||
---
|
||||
|
||||
# Zustand Store
|
||||
|
||||
Create Zustand stores following established patterns with proper TypeScript types and middleware.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Copy the template from [assets/template.ts](assets/template.ts) and replace placeholders:
|
||||
- `{{StoreName}}` → PascalCase store name (e.g., `Project`)
|
||||
- `{{description}}` → Brief description for JSDoc
|
||||
|
||||
## Always Use subscribeWithSelector
|
||||
|
||||
```typescript
|
||||
import { create } from 'zustand';
|
||||
import { subscribeWithSelector } from 'zustand/middleware';
|
||||
|
||||
export const useMyStore = create<MyStore>()(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
// state and actions
|
||||
}))
|
||||
);
|
||||
```
|
||||
|
||||
## Separate State and Actions
|
||||
|
||||
```typescript
|
||||
export interface MyState {
|
||||
items: Item[];
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export interface MyActions {
|
||||
addItem: (item: Item) => void;
|
||||
loadItems: () => Promise<void>;
|
||||
}
|
||||
|
||||
export type MyStore = MyState & MyActions;
|
||||
```
|
||||
|
||||
## Use Individual Selectors
|
||||
|
||||
```typescript
|
||||
// Good - only re-renders when `items` changes
|
||||
const items = useMyStore((state) => state.items);
|
||||
|
||||
// Avoid - re-renders on any state change
|
||||
const { items, isLoading } = useMyStore();
|
||||
```
|
||||
|
||||
## Subscribe Outside React
|
||||
|
||||
```typescript
|
||||
useMyStore.subscribe(
|
||||
(state) => state.selectedId,
|
||||
(selectedId) => console.log('Selected:', selectedId)
|
||||
);
|
||||
```
|
||||
|
||||
## Integration Steps
|
||||
|
||||
1. Create store in `src/frontend/src/store/`
|
||||
2. Export from `src/frontend/src/store/index.ts`
|
||||
3. Add tests in `src/frontend/src/store/*.test.ts`
|
||||
Reference in New Issue
Block a user