update implementation documentation

This commit is contained in:
Smartsheet-JB-Brown 2025-04-15 13:50:53 -07:00
parent b669edd82b
commit 448fb3dd20
4 changed files with 862 additions and 1838 deletions

View file

@ -13,7 +13,8 @@ graph TD
User[User] -->|Interacts with| UI[Package Manager UI]
UI -->|Sends messages| MH[Message Handler]
MH -->|Processes requests| PM[PackageManagerManager]
PM -->|Loads data from| MS[MetadataScanner]
PM -->|Fetches repos| GF[GitFetcher]
GF -->|Scans metadata| MS[MetadataScanner]
MS -->|Reads| FS[File System / Git Repositories]
PM -->|Returns filtered data| MH
MH -->|Updates state| UI
@ -35,20 +36,23 @@ The Package Manager components interact through a well-defined message flow:
1. **Data Loading**:
- GitFetcher handles repository cloning and updates
- MetadataScanner loads package data from repositories
- PackageManagerManager stores and manages this data
- PackageManagerManager manages caching and concurrency
- UI requests data through the message handler
2. **Filtering and Search**:
- UI sends filter/search criteria to the backend
- PackageManagerManager applies filters to the data
- PackageManagerManager applies filters with match info
- Filtered results are returned to the UI
- State manager handles view-level filtering
3. **Source Management**:
- UI sends source management commands
- PackageManagerManager updates source configurations
- MetadataScanner reloads data from updated sources
- PackageManagerManager coordinates with GitFetcher
- Cache is managed with timeout protection
- Sources are processed with concurrency control
## Data Flow Diagram
@ -62,6 +66,7 @@ graph LR
end
subgraph Backend
GF[GitFetcher]
MS[MetadataScanner]
PM[PackageManagerManager]
MH[Message Handler]
@ -72,10 +77,11 @@ graph LR
State[State Management]
end
GR -->|Raw Data| MS
FS -->|Template Data| MS
MS -->|Parsed Metadata| PM
PM -->|Stored Items| PM
GR -->|Clone/Pull| GF
FS -->|Cache| GF
GF -->|Metadata| MS
MS -->|Parsed Data| PM
PM -->|Cached Items| PM
UI -->|User Actions| MH
MH -->|Messages| PM
PM -->|Filtered Data| MH
@ -95,16 +101,20 @@ sequenceDiagram
participant UI as UI Components
participant MH as Message Handler
participant PM as PackageManagerManager
participant GF as GitFetcher
participant MS as MetadataScanner
participant FS as File System/Git
User->>UI: Open Package Manager
UI->>MH: Send init message
MH->>PM: Initialize
PM->>MS: Request metadata scan
PM->>GF: Request repository data
GF->>FS: Clone/pull repository
GF->>MS: Request metadata scan
MS->>FS: Read repository data
FS-->>MS: Return raw data
MS-->>PM: Return parsed metadata
MS-->>GF: Return parsed metadata
GF-->>PM: Return repository data
PM-->>MH: Return initial items
MH-->>UI: Update with items
UI-->>User: Display packages
@ -118,23 +128,28 @@ This sequence diagram illustrates the search and filter process:
sequenceDiagram
participant User
participant UI as UI Components
participant State as State Manager
participant MH as Message Handler
participant PM as PackageManagerManager
User->>UI: Enter search term
UI->>MH: Send search message
UI->>State: Update filters
State->>MH: Send search message
MH->>PM: Apply search filter
PM->>PM: Filter items
PM->>PM: Filter items with match info
PM-->>MH: Return filtered items
MH-->>UI: Update with filtered items
MH-->>State: Update with filtered items
State-->>UI: Update view
UI-->>User: Display filtered results
User->>UI: Select type filter
UI->>MH: Send type filter message
UI->>State: Update type filter
State->>MH: Send type filter message
MH->>PM: Apply type filter
PM->>PM: Filter by type
PM->>PM: Filter by type with match info
PM-->>MH: Return type-filtered items
MH-->>UI: Update with type-filtered items
MH-->>State: Update filtered items
State-->>UI: Update view
UI-->>User: Display type-filtered results
```
@ -148,257 +163,178 @@ The following class diagram shows the main classes in the Package Manager system
classDiagram
class PackageManagerManager {
-currentItems: PackageManagerItem[]
-sources: PackageManagerSource[]
+getItems(): PackageManagerItem[]
-cache: Map
-gitFetcher: GitFetcher
-activeSourceOperations: Set
+getPackageManagerItems(): PackageManagerItem[]
+filterItems(filters): PackageManagerItem[]
+addSource(url): void
+removeSource(url): void
+refreshSources(): void
+sortItems(sortBy, order): PackageManagerItem[]
+refreshRepository(url): void
-queueOperation(operation): void
}
class GitFetcher {
-cacheDir: string
-metadataScanner: MetadataScanner
+fetchRepository(url): PackageManagerRepository
-cloneOrPullRepository(url): void
-validateRepositoryStructure(dir): void
-parseRepositoryMetadata(dir): RepositoryMetadata
}
class MetadataScanner {
-git: SimpleGit
+scanDirectory(path): PackageManagerItem[]
+scanRepository(url): PackageManagerItem[]
-parseMetadata(file): any
+parseMetadata(file): ComponentMetadata
-buildComponentHierarchy(items): PackageManagerItem[]
}
class PackageManagerMessageHandler {
+handleMessage(message): any
-handleSearchMessage(message): any
-handleFilterMessage(message): any
-handleSourceMessage(message): any
}
class PackageManagerItem {
+name: string
+description: string
+type: string
+items: any[]
+tags: string[]
+matchInfo: MatchInfo
}
class PackageManagerSource {
+url: string
+name: string
+enabled: boolean
}
PackageManagerManager --> PackageManagerItem: manages
PackageManagerManager --> PackageManagerSource: configures
PackageManagerManager --> MetadataScanner: uses
PackageManagerMessageHandler --> PackageManagerManager: calls
```
### UI Component Classes
This class diagram shows the main UI components:
```mermaid
classDiagram
class PackageManagerView {
class PackageManagerViewStateManager {
-items: PackageManagerItem[]
-filters: Filters
-activeTab: string
+render(): JSX
+handleFilterChange(): void
+handleSearch(): void
-sortBy: string
-sortOrder: string
+setFilters(filters): void
+getFilteredAndSortedItems(): PackageManagerItem[]
-itemMatchesFilters(item): boolean
}
class PackageManagerItemCard {
-item: PackageManagerItem
-filters: Filters
+render(): JSX
+handleTagClick(): void
}
class ExpandableSection {
-title: string
-isExpanded: boolean
+toggle(): void
+render(): JSX
}
class TypeGroup {
-type: string
-items: any[]
-searchTerm: string
+render(): JSX
}
PackageManagerView --> PackageManagerItemCard: contains
PackageManagerItemCard --> ExpandableSection: contains
ExpandableSection --> TypeGroup: contains
PackageManagerManager --> GitFetcher: uses
GitFetcher --> MetadataScanner: uses
PackageManagerManager --> PackageManagerViewStateManager: updates
```
## Component Responsibilities
### Backend Components
1. **MetadataScanner**
1. **GitFetcher**
- Scans directories and repositories for package metadata
- Handles Git repository operations
- Manages repository caching
- Validates repository structure
- Coordinates with MetadataScanner
2. **MetadataScanner**
- Scans directories and repositories
- Parses YAML metadata files
- Builds component hierarchies
- Handles file system and Git operations
- Handles file system operations
2. **PackageManagerManager**
3. **PackageManagerManager**
- Stores and manages package items
- Applies filters and search criteria
- Manages package sources
- Handles package operations
- Manages concurrent operations
- Handles caching with timeout protection
- Coordinates repository operations
- Provides filtering and sorting
3. **packageManagerMessageHandler**
4. **packageManagerMessageHandler**
- Routes messages between UI and backend
- Processes commands from the UI
- Returns data and status updates to the UI
- Returns data and status updates
- Handles error conditions
### Frontend Components
1. **PackageManagerView**
1. **PackageManagerViewStateManager**
- Main container component
- Manages overall UI state
- Handles tab navigation
- Displays filter controls
- Manages view-level state
- Handles filtering and sorting
- Maintains UI preferences
- Coordinates with backend state
2. **PackageManagerItemCard**
- Displays individual package information
- Displays package information
- Handles tag interactions
- Manages expandable details section
- Provides action buttons
- Manages expandable sections
- Shows match highlights
3. **ExpandableSection**
- Provides collapsible UI sections
- Provides collapsible sections
- Manages expand/collapse state
- Handles animations
- Displays section headers and badges
- Shows section metadata
4. **TypeGroup**
- Groups and displays components by type
- Groups items by type
- Formats item lists
- Highlights search matches
- Provides consistent styling
## Data Flow Patterns
### Message-Based Communication
The Package Manager uses a message-based architecture for communication between the frontend and backend:
1. **Message Structure**:
```typescript
{
type: string // The message type (e.g., "search", "filter", "addSource")
payload: any // The message data
}
```
2. **Common Message Types**:
- `search`: Apply a search term filter
- `filter`: Apply type or tag filters
- `addSource`: Add a new package source
- `removeSource`: Remove a package source
- `refreshSources`: Reload data from sources
3. **Response Structure**:
```typescript
{
type: string; // The response type
data: any; // The response data
error?: string; // Optional error message
}
```
### State Management
The Package Manager maintains state in several places:
1. **Backend State**:
- Current items in the PackageManagerManager
- Source configurations
- Cached metadata
2. **Frontend State**:
- Current filters and search terms
- UI state (active tab, expanded sections)
- Display preferences
3. **Persistent State**:
- Source configurations stored in extension settings
- User preferences
- Maintains consistent styling
## Performance Considerations
The Package Manager architecture addresses several performance challenges:
1. **Lazy Loading**:
1. **Concurrency Control**:
- Metadata is loaded on demand
- Repositories are scanned only when needed
- UI components render incrementally
- Source operations are locked to prevent conflicts
- Operations are queued during metadata scanning
- Cache timeouts prevent hanging operations
- Repository operations are atomic
2. **Efficient Filtering**:
2. **Efficient Caching**:
- Filtering happens on the backend to reduce data transfer
- Search algorithms optimize for common patterns
- Results are cached when possible
- Repository data is cached with expiry
- Cache is cleaned up automatically
- Forced refresh available when needed
- Cache directories managed efficiently
3. **Responsive UI**:
- Asynchronous operations prevent UI blocking
- Animations provide feedback during loading
- Pagination limits the number of items displayed at once
3. **Smart Filtering**:
- Match info tracks filter matches
- Filtering happens at multiple levels
- View state optimizes re-renders
- Search is case-insensitive and normalized
## Error Handling
The architecture includes robust error handling:
1. **Source Errors**:
1. **Repository Operations**:
- Invalid repositories are marked with error states
- Users are notified of access issues
- The system continues to function with other sources
- Git lock files are cleaned up
- Failed clones are retried
- Corrupt repositories are re-cloned
- Network timeouts are handled
2. **Parsing Errors**:
2. **Data Processing**:
- Malformed metadata is gracefully handled
- Partial results are displayed when possible
- Error details are logged for debugging
- Invalid metadata is gracefully handled
- Missing files are reported clearly
- Parse errors preserve partial data
- Type validation ensures consistency
3. **Network Errors**:
- Timeouts and retries for network operations
- Offline mode with cached data
- Clear error messages for user troubleshooting
3. **State Management**:
- Invalid filters are normalized
- Sort operations handle missing data
- View updates are atomic
- Error states are preserved
## Extensibility Points
The Package Manager architecture is designed for extensibility:
1. **New Component Types**:
1. **Repository Sources**:
- The system can be extended to support new component types
- Type-specific rendering can be added to the UI
- Backend processing adapts to new types
- Support for multiple Git providers
- Custom repository validation
- Flexible metadata formats
- Localization support
2. **Additional Filters**:
2. **Filtering System**:
- New filter types can be added to the system
- Filter logic can be extended in the PackageManagerManager
- UI can be updated to display new filter controls
- Custom filter types
- Extensible match info
- Flexible sort options
- View state customization
3. **Custom Sources**:
- The source system supports various repository types
- Custom source providers can be implemented
- Authentication mechanisms can be extended
3. **UI Components**:
- Custom item renderers
- Flexible layout system
- Theme integration
- Accessibility support
---

View file

@ -2,172 +2,190 @@
This document provides detailed information about the core components of the Package Manager system, their responsibilities, implementation details, and interactions.
## GitFetcher
The GitFetcher is responsible for managing Git repository operations, including cloning, pulling, and caching repository data.
### Responsibilities
- Cloning and updating Git repositories
- Managing repository cache
- Validating repository structure
- Coordinating with MetadataScanner
- Handling repository timeouts and errors
### Implementation Details
```typescript
class GitFetcher {
private readonly cacheDir: string
private metadataScanner: MetadataScanner
private git?: SimpleGit
/**
* Fetch repository data
* @param repoUrl Repository URL
* @param forceRefresh Whether to bypass cache
* @param sourceName Optional source name
* @returns Repository data
*/
public async fetchRepository(
repoUrl: string,
forceRefresh = false,
sourceName?: string,
): Promise<PackageManagerRepository> {
// Implementation details
}
/**
* Clone or pull repository
* @param repoUrl Repository URL
* @param repoDir Repository directory
* @param forceRefresh Whether to force refresh
*/
private async cloneOrPullRepository(repoUrl: string, repoDir: string, forceRefresh: boolean): Promise<void> {
// Implementation details
}
/**
* Clean up git locks
* @param repoDir Repository directory
*/
private async cleanupGitLocks(repoDir: string): Promise<void> {
// Implementation details
}
}
```
### Key Algorithms
#### Repository Management
The repository management process includes:
1. **Cache Management**:
- Check if repository exists in cache
- Validate cache freshness
- Clean up stale cache entries
- Handle cache directory creation
2. **Repository Operations**:
- Clone new repositories
- Pull updates for existing repos
- Handle git lock files
- Clean up failed operations
3. **Error Recovery**:
- Handle network timeouts
- Recover from corrupt repositories
- Clean up partial clones
- Retry failed operations
## MetadataScanner
The MetadataScanner is responsible for reading and parsing package metadata from various sources, including local file systems and remote Git repositories.
The MetadataScanner is responsible for reading and parsing package metadata from repositories.
### Responsibilities
- Scanning directories for package metadata files
- Parsing YAML metadata into structured objects
- Building component hierarchies
- Handling file system and Git operations
- Supporting localized metadata
- Validating metadata structure
### Implementation Details
```typescript
class MetadataScanner {
private git: SimpleGit
private localizationOptions: LocalizationOptions
/**
* Scans a directory for package metadata
* @param directoryPath Path to the directory to scan
* @param baseUrl Base URL for the repository (for remote sources)
* Scan directory for package metadata
* @param directoryPath Directory to scan
* @param baseUrl Base repository URL
* @param sourceName Source repository name
* @returns Array of package items
*/
public async scanDirectory(directoryPath: string, baseUrl?: string): Promise<PackageManagerItem[]> {
public async scanDirectory(
directoryPath: string,
baseUrl?: string,
sourceName?: string,
): Promise<PackageManagerItem[]> {
// Implementation details
}
/**
* Scans a Git repository for package metadata
* @param repoUrl URL of the Git repository
* @returns Array of package items
* Parse metadata file
* @param filePath Path to metadata file
* @returns Parsed metadata
*/
public async scanRepository(repoUrl: string): Promise<PackageManagerItem[]> {
// Implementation details
}
/**
* Parses a YAML metadata file
* @param filePath Path to the metadata file
* @returns Parsed metadata object
*/
private async parseMetadataFile(filePath: string): Promise<any> {
// Implementation details
}
/**
* Builds a component hierarchy from flat items
* @param items Array of items to organize
* @returns Hierarchical structure of items
*/
private buildComponentHierarchy(items: any[]): PackageManagerItem[] {
private async parseMetadataFile(filePath: string): Promise<ComponentMetadata> {
// Implementation details
}
}
```
### Key Algorithms
#### Directory Scanning
The directory scanning algorithm recursively traverses directories looking for metadata files:
1. Start at the root directory
2. Look for `metadata.*.yml` files in the current directory
3. Parse found metadata files
4. For each subdirectory:
- Determine the component type based on directory name
- Recursively scan the subdirectory
- Associate child components with parent components
5. Build the component hierarchy
#### Metadata Parsing
The metadata parsing process handles multiple formats and localizations:
1. Read the YAML file content
2. Parse the YAML into a JavaScript object
3. Extract the locale from the filename (e.g., `en` from `metadata.en.yml`)
4. Validate required fields (name, description, version)
5. Process optional fields (tags, author, etc.)
6. Return a structured metadata object
### Error Handling
The MetadataScanner includes robust error handling:
- Invalid YAML files are reported with specific parsing errors
- Missing required fields trigger validation errors
- File system access issues are caught and reported
- Network errors during Git operations are handled gracefully
- Partial results are returned when possible, with error flags
## PackageManagerManager
The PackageManagerManager is the central component that manages package items, applies filters, and handles package operations.
The PackageManagerManager is the central component that manages package data, caching, and operations.
### Responsibilities
- Storing and managing package items
- Applying filters and search criteria
- Managing concurrent operations
- Handling repository caching
- Coordinating with GitFetcher
- Applying filters and sorting
- Managing package sources
- Handling package operations
- Maintaining state between sessions
### Implementation Details
```typescript
class PackageManagerManager {
private currentItems: PackageManagerItem[] = []
private sources: PackageManagerSource[] = []
private cache: Map<string, { data: PackageManagerRepository; timestamp: number }>
private gitFetcher: GitFetcher
private activeSourceOperations = new Set<string>()
private isMetadataScanActive = false
private pendingOperations: Array<() => Promise<void>> = []
/**
* Constructor
* @param context VS Code extension context
* Queue an operation to run when no metadata scan is active
*/
constructor(private context: vscode.ExtensionContext) {
// Initialize from stored state
private async queueOperation(operation: () => Promise<void>): Promise<void> {
// Implementation details
}
/**
* Get all items
* @returns Array of all package items
* Get package manager items from sources
*/
public getItems(): PackageManagerItem[] {
return this.currentItems
public async getPackageManagerItems(
sources: PackageManagerSource[],
): Promise<{ items: PackageManagerItem[]; errors?: string[] }> {
// Implementation details
}
/**
* Filter items based on criteria
* @param filters Filter criteria
* @returns Filtered array of items
*/
public filterItems(filters: { type?: string; search?: string; tags?: string[] }): PackageManagerItem[] {
public filterItems(
items: PackageManagerItem[],
filters: { type?: ComponentType; search?: string; tags?: string[] },
): PackageManagerItem[] {
// Implementation details
}
/**
* Add a new package source
* @param url Source repository URL
* @param name Optional source name
* @returns Success status
* Sort items by field
*/
public async addSource(url: string, name?: string): Promise<boolean> {
// Implementation details
}
/**
* Remove a package source
* @param url Source repository URL
* @returns Success status
*/
public removeSource(url: string): boolean {
// Implementation details
}
/**
* Refresh all sources
* @returns Updated items
*/
public async refreshSources(): Promise<PackageManagerItem[]> {
// Implementation details
}
/**
* Save state to persistent storage
*/
private saveState(): void {
public sortItems(
items: PackageManagerItem[],
sortBy: keyof Pick<PackageManagerItem, "name" | "author" | "lastUpdated">,
sortOrder: "asc" | "desc",
sortSubcomponents: boolean = false,
): PackageManagerItem[] {
// Implementation details
}
}
@ -175,362 +193,139 @@ class PackageManagerManager {
### Key Algorithms
#### Item Filtering
#### Concurrency Control
The filtering algorithm applies multiple criteria to the package items:
The manager implements sophisticated concurrency control:
1. Start with the complete set of items
2. If a search term and/or filter is specified:
- Check item name, description, and author for matches
- Check subcomponents for matches
- Keep items that match or have matching subcomponents
- Add match information to the items
3. Return the filtered items with match information
1. **Operation Queueing**:
#### Source Management
- Queue operations during active scans
- Process operations sequentially
- Handle operation dependencies
- Maintain operation order
The source management process handles adding, removing, and refreshing sources:
2. **Source Locking**:
1. For adding a source:
- Lock sources during operations
- Prevent concurrent source access
- Handle lock timeouts
- Clean up stale locks
- Validate the repository URL
- Check if the source already exists
- Add the source to the list
- Scan the repository for items
- Add the items to the current set
- Save the updated source list
3. **Cache Management**:
- Implement cache expiration
- Handle cache invalidation
- Clean up unused cache
- Optimize cache storage
2. For removing a source:
#### Advanced Filtering
- Find the source in the list
- Remove items from that source
- Remove the source from the list
- Save the updated source list
The filtering system provides rich functionality:
3. For refreshing sources:
- Clear the current items
- For each enabled source:
- Scan the repository for items
- Add the items to the current set
- Return the updated items
1. **Multi-level Filtering**:
### State Persistence
- Filter parent items
- Filter subcomponents
- Handle package-specific logic
- Track match information
The PackageManagerManager maintains state between sessions:
2. **Match Information**:
- Track match reasons
- Handle partial matches
- Support highlighting
- Maintain match context
- Source configurations are stored in extension global state
- User preferences are persisted
- Cached metadata can be stored for performance
- State is loaded during initialization
- State is saved after significant changes
## PackageManagerViewStateManager
## packageManagerMessageHandler
The packageManagerMessageHandler is responsible for routing messages between the UI and the backend components.
The PackageManagerViewStateManager handles UI state and view-level operations.
### Responsibilities
- Processing messages from the UI
- Calling appropriate PackageManagerManager methods
- Returning results to the UI
- Handling errors and status updates
- Managing asynchronous operations
- Managing view-level state
- Handling UI filters
- Coordinating sorting
- Managing item visibility
### Implementation Details
```typescript
/**
* Handle package manager messages
* @param message The message to handle
* @param packageManager The package manager instance
* @returns Response object
*/
export async function handlePackageManagerMessages(message: any, packageManager: PackageManagerManager): Promise<any> {
switch (message.type) {
case "getItems":
return {
type: "items",
data: packageManager.getItems(),
}
class PackageManagerViewStateManager {
private items: PackageManagerItem[] = []
private sortBy: "name" | "lastUpdated" = "name"
private sortOrder: "asc" | "desc" = "asc"
private filters: Filters = { type: "", search: "", tags: [] }
case "search":
return {
type: "searchResults",
data: packageManager.filterItems({
search: message.search,
type: message.typeFilter,
tags: message.tagFilters,
}),
}
/**
* Get filtered and sorted items
*/
public getFilteredAndSortedItems(): PackageManagerItem[] {
// Implementation details
}
case "addSource":
try {
const success = await packageManager.addSource(message.url, message.name)
return {
type: "sourceAdded",
data: { success },
}
} catch (error) {
return {
type: "error",
error: error.message,
}
}
// Additional message handlers...
default:
return {
type: "error",
error: `Unknown message type: ${message.type}`,
}
/**
* Check if item matches current filters
*/
private itemMatchesFilters(item: PackageManagerItem | Subcomponent): boolean {
// Implementation details
}
}
```
### Message Types
## Component Integration
The message handler processes several types of messages:
The components work together through well-defined interfaces:
#### Input Messages
### Data Flow
1. **getItems**: Request all package items
1. **Repository Operations**:
```typescript
{
type: "getItems"
}
```
2. **search**: Apply search and filter criteria
```typescript
{
type: "search",
search: "search term",
typeFilter: "mode",
tagFilters: ["tag1", "tag2"]
}
```
3. **addSource**: Add a new package source
```typescript
{
type: "addSource",
url: "https://github.com/username/repo.git",
name: "Custom Source"
}
```
4. **removeSource**: Remove a package source
```typescript
{
type: "removeSource",
url: "https://github.com/username/repo.git"
}
```
5. **refreshSources**: Refresh all sources
```typescript
{
type: "refreshSources"
}
```
#### Output Messages
1. **items**: Response with all items
```typescript
{
type: "items",
data: [/* package items */]
}
```
2. **searchResults**: Response with filtered items
```typescript
{
type: "searchResults",
data: [/* filtered items */]
}
```
3. **sourceAdded**: Response after adding a source
```typescript
{
type: "sourceAdded",
data: { success: true }
}
```
4. **error**: Error response
```typescript
{
type: "error",
error: "Error message"
}
```
### Asynchronous Processing
The message handler manages asynchronous operations:
1. Asynchronous methods return promises
2. Errors are caught and returned as error messages
3. Long-running operations can provide progress updates
4. The UI can display loading indicators during processing
## UI Components
The Package Manager includes several key UI components that render the interface and handle user interactions.
### PackageManagerView
The main container component that manages the overall UI:
```tsx
const PackageManagerView: React.FC = () => {
const [items, setItems] = useState<PackageManagerItem[]>([])
const [filters, setFilters] = useState({ type: "", search: "", tags: [] })
const [activeTab, setActiveTab] = useState<"browse" | "sources">("browse")
// Implementation details...
return (
<div className="package-manager-container">
<div className="tabs">
<button className={activeTab === "browse" ? "active" : ""} onClick={() => setActiveTab("browse")}>
Browse
</button>
<button className={activeTab === "sources" ? "active" : ""} onClick={() => setActiveTab("sources")}>
Sources
</button>
</div>
{activeTab === "browse" ? (
<div className="browse-container">
<FilterPanel filters={filters} setFilters={setFilters} />
<div className="results-area">
{items.map((item) => (
<PackageManagerItemCard
key={item.name}
item={item}
filters={filters}
setFilters={setFilters}
activeTab={activeTab}
setActiveTab={setActiveTab}
/>
))}
</div>
</div>
) : (
<SourcesPanel />
)}
</div>
)
}
```
### Component Interactions
The UI components interact through props and state:
1. **Parent-Child Communication**:
- Parent components pass data and callbacks to children
- Children invoke callbacks to notify parents of events
- PackageManagerManager coordinates with GitFetcher
- GitFetcher manages repository state
- MetadataScanner processes repository content
- Results flow back to PackageManagerManager
2. **State Management**:
- Component state for UI-specific state
- Shared state for filters and active tab
- Backend state accessed through messages
- PackageManagerManager maintains backend state
- ViewStateManager handles UI state
- State changes trigger UI updates
- Components react to state changes
3. **Event Handling**:
3. **User Interactions**:
- UI events trigger state updates
- State updates cause re-renders
- Messages are sent to the backend when needed
### Accessibility Features
The UI components include several accessibility features:
1. **Keyboard Navigation**:
- Tab order follows logical flow
- Focus indicators are visible
- Keyboard shortcuts for common actions
2. **Screen Reader Support**:
- ARIA attributes for dynamic content
- Semantic HTML structure
- Descriptive labels and announcements
3. **Visual Accessibility**:
- High contrast mode support
- Resizable text
- Color schemes that work with color blindness
## Component Integration
The core components work together to provide a complete package management experience:
### Initialization Flow
1. The Package Manager is activated
2. The PackageManagerManager loads stored state
3. The UI sends an initial "getItems" message
4. The message handler calls PackageManagerManager.getItems()
5. The UI receives and displays the items
### Search and Filter Flow
1. The user enters a search term or selects filters
2. The UI sends a "search" message with the criteria
3. The message handler calls PackageManagerManager.filterItems()
4. The PackageManagerManager applies the filters
5. The UI receives and displays the filtered items
### Source Management Flow
1. The user adds a new source
2. The UI sends an "addSource" message
3. The message handler calls PackageManagerManager.addSource()
4. The PackageManagerManager adds the source and scans for items
5. The UI receives confirmation and updates the display
- ViewStateManager processes changes
- Changes propagate to backend
- Results update UI state
## Performance Optimizations
The core components include several performance optimizations:
The system includes several optimizations:
1. **Lazy Loading**:
1. **Concurrent Operations**:
- Items are loaded on demand
- Heavy operations are deferred
- Components render incrementally
- Operation queueing
- Source locking
- Parallel processing where safe
- Resource management
2. **Caching**:
2. **Efficient Caching**:
- Parsed metadata is cached
- Filter results can be cached
- Repository data is cached when possible
- Multi-level cache
- Cache invalidation
- Lazy loading
- Cache cleanup
3. **Efficient Filtering**:
3. **Smart Filtering**:
- Filtering happens on the backend
- Only necessary data is transferred
- Algorithms optimize for common cases
- Optimized algorithms
- Match tracking
- Incremental updates
- Result caching
4. **UI Optimizations**:
- Virtual scrolling for large lists
- Debounced search input
- Optimized rendering of complex components
4. **State Management**:
- Minimal updates
- State normalization
- Change batching
- Update optimization
---

View file

@ -22,131 +22,30 @@ These types represent the different kinds of components that can be managed by t
3. **package**: Collections of related components
4. **mcp server**: Model Context Protocol servers that provide additional functionality
The type system is extensible, allowing for new component types to be added in the future.
## Core Data Structures
## Metadata Interfaces
The Package Manager uses a set of interfaces to define the structure of metadata for different components:
### BaseMetadata
### PackageManagerRepository
```typescript
/**
* Base metadata interface
* Represents a repository with its metadata and items
*/
export interface BaseMetadata {
name: string
description: string
version: string
tags?: string[]
export interface PackageManagerRepository {
metadata: RepositoryMetadata
items: PackageManagerItem[]
url: string
defaultBranch: string
error?: string
}
```
This interface defines the common properties shared by all metadata types:
This interface represents a complete repository:
- **name**: The display name of the component
- **description**: A detailed explanation of the component's purpose
- **version**: The semantic version number
- **tags**: Optional array of relevant keywords
### RepositoryMetadata
```typescript
/**
* Repository root metadata
*/
export interface RepositoryMetadata extends BaseMetadata {}
```
This interface represents the metadata for a package source repository. It currently inherits all properties from BaseMetadata without adding additional fields, but is defined separately to allow for future repository-specific extensions.
### ComponentMetadata
```typescript
/**
* Component metadata with type
*/
export interface ComponentMetadata extends BaseMetadata {
type: ComponentType
}
```
This interface extends BaseMetadata to include a type field, which specifies the component type.
### PackageMetadata
```typescript
/**
* Package metadata with optional subcomponents
*/
export interface PackageMetadata extends ComponentMetadata {
type: "package"
items?: {
type: ComponentType
path: string
metadata?: ComponentMetadata
}[]
}
```
This interface represents packages that can contain subcomponents:
- **type**: Always "package" for this interface
- **items**: Optional array of subcomponents, each with:
- **type**: The subcomponent type
- **path**: The file system path to the subcomponent
- **metadata**: Optional metadata for the subcomponent
### SubcomponentMetadata
```typescript
/**
* Subcomponent metadata with parent reference
*/
export interface SubcomponentMetadata extends ComponentMetadata {
parentPackage: {
name: string
path: string
}
}
```
This interface represents components that are part of a parent package:
- All fields from ComponentMetadata
- **parentPackage**: Reference to the parent package
- **name**: The name of the parent package
- **path**: The file system path to the parent package
## Item Structures
The Package Manager uses several interfaces to represent items in the UI:
### MatchInfo
```typescript
/**
* Information about why an item matched search/filter criteria
*/
export interface MatchInfo {
matched: boolean
matchReason?: {
nameMatch?: boolean
descriptionMatch?: boolean
tagMatch?: boolean
hasMatchingSubcomponents?: boolean
}
}
```
This interface provides information about why an item matched search or filter criteria:
- **matched**: Boolean indicating if the item matched
- **matchReason**: Optional object with specific match reasons
- **nameMatch**: True if the name matched
- **descriptionMatch**: True if the description matched
- **tagMatch**: True if a tag matched
- **hasMatchingSubcomponents**: True if a subcomponent matched
- **metadata**: The repository metadata
- **items**: Array of items in the repository
- **url**: The URL to the repository
- **defaultBranch**: The default Git branch (e.g., "main")
- **error**: Optional error message if there was a problem
### PackageManagerItem
@ -166,6 +65,7 @@ export interface PackageManagerItem {
version?: string
lastUpdated?: string
sourceUrl?: string
defaultBranch?: string
items?: {
type: ComponentType
path: string
@ -177,27 +77,145 @@ export interface PackageManagerItem {
}
```
This interface represents a complete package manager item as displayed in the UI:
Key changes:
- **name**: The display name of the item
- **description**: A detailed explanation of the item's purpose
- **type**: The component type
- **url**: The URL to the item's source
- **repoUrl**: The URL to the repository containing the item
- **sourceName**: Optional name of the source repository
- **author**: Optional author name
- **tags**: Optional array of relevant keywords
- **version**: Optional semantic version number
- **lastUpdated**: Optional date of last update
- **sourceUrl**: Optional URL to additional documentation
- **items**: Optional array of subcomponents
- **matchInfo**: Optional information about search/filter matches
- Added **defaultBranch** field for Git branch tracking
- Enhanced **matchInfo** structure for better filtering
- Improved subcomponent handling
### MatchInfo
```typescript
/**
* Information about why an item matched search/filter criteria
*/
export interface MatchInfo {
matched: boolean
matchReason?: {
nameMatch?: boolean
descriptionMatch?: boolean
typeMatch?: boolean
tagMatch?: boolean
hasMatchingSubcomponents?: boolean
}
}
```
Enhanced match tracking:
- Added **typeMatch** for component type filtering
- More detailed match reasons
- Support for subcomponent matching
## State Management Structures
### ViewState
```typescript
/**
* View-level state management
*/
interface ViewState {
items: PackageManagerItem[]
sortBy: "name" | "lastUpdated"
sortOrder: "asc" | "desc"
filters: Filters
}
```
Manages UI state:
- Current items
- Sort configuration
- Filter state
### Filters
```typescript
/**
* Filter criteria
*/
interface Filters {
type: string
search: string
tags: string[]
}
```
Enhanced filtering:
- Component type filtering
- Text search
- Tag-based filtering
## Metadata Interfaces
### BaseMetadata
```typescript
/**
* Base metadata interface
*/
export interface BaseMetadata {
name: string
description: string
version: string
tags?: string[]
}
```
Common metadata properties:
- **name**: Display name
- **description**: Detailed explanation
- **version**: Semantic version
- **tags**: Optional keywords
### ComponentMetadata
```typescript
/**
* Component metadata with type
*/
export interface ComponentMetadata extends BaseMetadata {
type: ComponentType
lastUpdated?: string
}
```
Added:
- **lastUpdated** field for tracking changes
### PackageMetadata
```typescript
/**
* Package metadata with subcomponents
*/
export interface PackageMetadata extends ComponentMetadata {
type: "package"
items?: {
type: ComponentType
path: string
metadata?: ComponentMetadata
lastUpdated?: string
}[]
}
```
Enhanced with:
- Subcomponent tracking
- Last update timestamps
## Source Management
### PackageManagerSource
```typescript
/**
* Represents a Git repository source for package manager items
* Git repository source
*/
export interface PackageManagerSource {
url: string
@ -206,462 +224,202 @@ export interface PackageManagerSource {
}
```
This interface represents a package source repository:
Repository source configuration:
- **url**: The URL to the Git repository
- **name**: Optional display name for the source
- **enabled**: Boolean indicating if the source is active
- **url**: Git repository URL
- **name**: Optional display name
- **enabled**: Source status
### PackageManagerRepository
### SourceOperation
```typescript
/**
* Represents a repository with its metadata and items
* Source operation tracking
*/
export interface PackageManagerRepository {
metadata: RepositoryMetadata
items: PackageManagerItem[]
interface SourceOperation {
url: string
error?: string
type: "clone" | "pull" | "refresh"
timestamp: number
}
```
This interface represents a complete repository with its metadata and items:
Tracks repository operations:
- **metadata**: The repository metadata
- **items**: Array of items in the repository
- **url**: The URL to the repository
- **error**: Optional error message if there was a problem loading the repository
- Operation type
- Timestamp
- Source URL
### LocalizedMetadata
## Cache Management
### CacheEntry
```typescript
/**
* Utility type for metadata files with locale
* Cache entry structure
*/
export type LocalizedMetadata<T> = {
[locale: string]: T
interface CacheEntry<T> {
data: T
timestamp: number
}
```
This utility type represents metadata that can be localized to different languages:
Generic cache structure:
- **[locale: string]**: Keys are locale identifiers (e.g., "en", "fr")
- **T**: The type of metadata being localized
- Cached data
- Timestamp for expiry
## UI Component Props
The Package Manager UI components use several prop interfaces:
### PackageManagerItemCardProps
### RepositoryCache
```typescript
interface PackageManagerItemCardProps {
item: PackageManagerItem
filters: { type: string; search: string; tags: string[] }
setFilters: React.Dispatch<React.SetStateAction<{ type: string; search: string; tags: string[] }>>
activeTab: "browse" | "sources"
setActiveTab: React.Dispatch<React.SetStateAction<"browse" | "sources">>
}
/**
* Repository cache management
*/
type RepositoryCache = Map<string, CacheEntry<PackageManagerRepository>>
```
This interface defines the props for the PackageManagerItemCard component:
Specialized for repositories:
- **item**: The package item to display
- **filters**: The current filter state
- **setFilters**: Function to update filters
- **activeTab**: The currently active tab
- **setActiveTab**: Function to change the active tab
### ExpandableSectionProps
```typescript
interface ExpandableSectionProps {
title: string
children: React.ReactNode
className?: string
defaultExpanded?: boolean
badge?: string
}
```
This interface defines the props for the ExpandableSection component:
- **title**: The section header text
- **children**: The content to display when expanded
- **className**: Optional CSS class name
- **defaultExpanded**: Optional flag to set initial expanded state
- **badge**: Optional badge text to display
### TypeGroupProps
```typescript
interface TypeGroupProps {
type: string
items: Array<{
name: string
description?: string
metadata?: any
path?: string
}>
className?: string
searchTerm?: string
}
```
This interface defines the props for the TypeGroup component:
- **type**: The component type to display
- **items**: Array of items of this type
- **className**: Optional CSS class name
- **searchTerm**: Optional search term for highlighting matches
## Grouped Items Structure
The Package Manager uses a specialized structure for grouping items by type:
### GroupedItems
```typescript
export interface GroupedItems {
[type: string]: {
type: string
items: Array<{
name: string
description?: string
metadata?: any
path?: string
}>
}
}
```
This interface represents items grouped by their type:
- **[type: string]**: Keys are component types
- **type**: The component type (redundant with the key)
- **items**: Array of items of this type
- **name**: The item name
- **description**: Optional item description
- **metadata**: Optional additional metadata
- **path**: Optional file system path
## Filter and Sort Structures
The Package Manager uses several structures for filtering and sorting:
### Filters
```typescript
interface Filters {
type: string
search: string
tags: string[]
}
```
This interface represents the filter criteria:
- **type**: The component type filter
- **search**: The search term
- **tags**: Array of tag filters
### SortConfig
```typescript
interface SortConfig {
by: string
order: "asc" | "desc"
}
```
This interface represents the sort configuration:
- **by**: The field to sort by (e.g., "name", "author")
- **order**: The sort order ("asc" for ascending, "desc" for descending)
- URL-based lookup
- Timestamp-based expiry
- Full repository data
## Message Structures
The Package Manager uses a message-based architecture for communication:
### Input Messages
```typescript
// Get all items
{ type: "getItems" }
// Apply search and filter criteria
{
type: "search",
search: string,
typeFilter: string,
tagFilters: string[]
}
// Add a new package source
{
type: "addSource",
url: string,
name?: string
}
// Remove a package source
{
type: "removeSource",
url: string
}
// Refresh all sources
{ type: "refreshSources" }
type PackageManagerMessage =
| { type: "getItems" }
| {
type: "search"
search: string
typeFilter: string
tagFilters: string[]
}
| {
type: "addSource"
url: string
name?: string
}
| {
type: "removeSource"
url: string
}
| { type: "refreshSources" }
```
### Output Messages
```typescript
// Response with all items
{
type: "items",
data: PackageManagerItem[]
}
// Response with filtered items
{
type: "searchResults",
data: PackageManagerItem[]
}
// Response after adding a source
{
type: "sourceAdded",
data: { success: boolean }
}
// Error response
{
type: "error",
error: string
}
type PackageManagerResponse =
| {
type: "items"
data: PackageManagerItem[]
}
| {
type: "searchResults"
data: PackageManagerItem[]
filters: Filters
}
| {
type: "sourceAdded" | "sourceRemoved"
data: { success: boolean }
}
| {
type: "error"
error: string
}
```
## Template Structure
Enhanced with:
The Package Manager uses a specific directory structure for templates:
### Basic Template Structure
```
package-manager-template/
├── metadata.en.yml # Repository metadata
├── README.md # Repository documentation
├── packages/ # Directory for package components
│ └── data-platform/ # Example package
│ └── metadata.en.yml # Package metadata
├── modes/ # Directory for mode components
│ └── developer-mode/ # Example mode
│ └── metadata.en.yml # Mode metadata
├── mcp servers/ # Directory for MCP server components
│ ├── example-server/ # Example server
│ │ └── metadata.en.yml # Server metadata
│ └── file-analyzer/ # Another example server
│ └── metadata.en.yml # Server metadata
└── groups/ # Directory for grouping components
└── data-engineering/ # Example group
└── metadata.en.yml # Group metadata
```
### Metadata File Structure
```yaml
# Repository metadata (metadata.en.yml)
name: "Package Manager Template"
description: "A template repository for creating package manager sources"
version: "1.0.0"
# Component metadata (e.g., modes/developer-mode/metadata.en.yml)
name: "Developer Mode"
description: "A specialized mode for software development tasks"
version: "1.0.0"
type: "mode"
tags:
- development
- coding
- software
```
## Data Flow and Transformations
The Package Manager transforms data through several stages:
### From File System to Metadata
1. Raw YAML files are read from the file system
2. YAML is parsed into JavaScript objects
3. Objects are validated against metadata interfaces
4. Localized metadata is combined into a single structure
### From Metadata to Items
1. Metadata objects are transformed into PackageManagerItem objects
2. File paths are converted to URLs
3. Parent-child relationships are established
4. Additional information is added (e.g., lastUpdated)
### From Items to UI
1. Items are filtered based on user criteria
2. Match information is added to items
3. Items are sorted according to user preferences
4. Items are grouped by type for display
- Filter state in search results
- Operation success tracking
- Detailed error reporting
## Data Validation
The Package Manager includes validation at several levels:
### Metadata Validation
```typescript
function validateMetadata(metadata: any): boolean {
// Required fields
if (!metadata.name || !metadata.description || !metadata.version) {
return false
}
/**
* Validate component metadata
*/
function validateMetadata(metadata: unknown): metadata is ComponentMetadata {
if (!isObject(metadata)) return false
// Type validation for components
if (metadata.type && !["mode", "prompt", "package", "mcp server"].includes(metadata.type)) {
return false
}
// Additional validation...
return true
return (
typeof metadata.name === "string" &&
typeof metadata.description === "string" &&
typeof metadata.version === "string" &&
(metadata.tags === undefined || Array.isArray(metadata.tags)) &&
isValidComponentType(metadata.type)
)
}
```
### URL Validation
```typescript
function isValidUrl(urlString: string): boolean {
try {
new URL(urlString)
return true
} catch (e) {
return false
}
/**
* Validate Git repository URL
*/
function isValidGitUrl(url: string): boolean {
if (!url) return false
// Support common Git URL formats
return /^(https?:\/\/|git@)/.test(url) && /\.git$/.test(url)
}
```
### Tag Validation
## Data Flow
```typescript
function validateTags(tags: any[]): string[] {
if (!Array.isArray(tags)) {
return []
}
The Package Manager transforms data through several stages:
return tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0).map((tag) => tag.trim())
}
```
1. **Repository Level**:
- Clone/pull Git repositories
- Parse metadata files
- Build component hierarchy
2. **Cache Level**:
- Store repository data
- Track timestamps
- Handle expiration
3. **View Level**:
- Apply filters
- Sort items
- Track matches
- Manage UI state
## Data Relationships
The Package Manager maintains several important relationships between data structures:
### Parent-Child Relationships
Packages can contain subcomponents, creating a hierarchical structure:
### Component Hierarchy
```
Package
├── Mode
├── MCP Server
├── Prompt
└── Nested Package
├── Mode
└── MCP Server
Repository
├── Metadata
└── Items
├── Package
│ ├── Mode
│ ├── MCP Server
│ └── Prompt
└── Standalone Components
```
This relationship is represented in the data structures:
### State Flow
- Packages have an `items` array containing subcomponents
- Subcomponents have a `parentPackage` reference
### Source-Item Relationships
Items are associated with their source repositories:
- Each item has a `repoUrl` field pointing to its source
- Sources have a list of items they provide
- When a source is disabled, its items are hidden
### Type-Group Relationships
Items are grouped by their type for display:
- The `GroupedItems` interface organizes items by type
- Each type group contains items of that type
- The UI displays these groups separately
## Serialization and Persistence
The Package Manager serializes data for persistence:
### Source Persistence
```typescript
// Save sources to extension state
private saveState(): void {
this.context.globalState.update("packageManagerSources", this.sources);
}
// Load sources from extension state
private loadState(): void {
const savedSources = this.context.globalState.get<PackageManagerSource[]>("packageManagerSources", []);
this.sources = savedSources;
}
```
Git Repository → Cache → PackageManager → ViewState → UI
```
### Metadata Caching
### Filter Chain
```typescript
// Cache metadata to improve performance
private cacheMetadata(url: string, metadata: any): void {
const cacheKey = `metadata_${url}`;
this.context.globalState.update(cacheKey, {
timestamp: Date.now(),
data: metadata
});
}
// Retrieve cached metadata
private getCachedMetadata(url: string): any | null {
const cacheKey = `metadata_${url}`;
const cached = this.context.globalState.get(cacheKey);
if (!cached || Date.now() - cached.timestamp > CACHE_TTL) {
return null;
}
return cached.data;
}
```
## Data Structure Evolution
The Package Manager's data structures are designed for evolution:
### Versioning Strategy
- Interfaces include version fields
- New fields are added as optional
- Breaking changes are avoided when possible
- Migration code handles legacy data formats
### Extensibility Points
- The ComponentType can be extended with new types
- Metadata interfaces can be extended with new fields
- The message system can handle new message types
- The UI can adapt to display new data formats
Raw Items → Type Filter → Search Filter → Tag Filter → Sorted Results
```
---