-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e0f4523
commit fe7b584
Showing
20 changed files
with
3,180 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,245 @@ | ||
--- | ||
description: Guidelines for using the Podman Desktop extension API | ||
globs: ["src/extension.ts", "src/**/provider.ts"] | ||
--- | ||
|
||
# Extension API Development Rules | ||
|
||
## Extension Lifecycle | ||
|
||
### Activation | ||
- Implement async activate function | ||
- Handle all setup operations | ||
- Register disposables with context | ||
```typescript | ||
export async function activate(context: extensionApi.ExtensionContext): Promise<void> { | ||
// Setup providers | ||
const provider = extensionApi.provider.createProvider({ | ||
name: 'MyProvider', | ||
id: 'my-provider', | ||
status: 'not-installed', | ||
images: { | ||
icon: './resources/icon.png', | ||
logo: './resources/logo.png', | ||
}, | ||
}); | ||
|
||
// Register disposables | ||
context.subscriptions.push(provider); | ||
|
||
// Initialize async resources | ||
await provider.initialize(); | ||
} | ||
``` | ||
|
||
### Deactivation | ||
- Implement deactivate function for cleanup | ||
- Handle async cleanup operations | ||
```typescript | ||
export async function deactivate(): Promise<void> { | ||
// Perform cleanup | ||
await provider.dispose(); | ||
} | ||
``` | ||
|
||
## Provider Management | ||
|
||
### Provider Status | ||
- Use appropriate ProviderStatus values | ||
- Update status based on actual state | ||
```typescript | ||
const validStates: ProviderStatus[] = [ | ||
'not-installed', | ||
'installed', | ||
'configured', | ||
'ready', | ||
'started', | ||
'stopped', | ||
'starting', | ||
'stopping', | ||
'error', | ||
'unknown' | ||
]; | ||
|
||
// Update status appropriately | ||
provider.updateStatus('starting'); | ||
await performStartup(); | ||
provider.updateStatus('started'); | ||
``` | ||
|
||
### Connection Status | ||
- Handle connection state changes | ||
- Implement proper error handling | ||
```typescript | ||
provider.updateStatus('starting'); | ||
try { | ||
await establishConnection(); | ||
provider.updateStatus('started'); | ||
} catch (error) { | ||
provider.updateStatus('error'); | ||
throw new Error(`Connection failed: ${error.message}`); | ||
} | ||
``` | ||
|
||
## Command Registration | ||
|
||
### Command Definition | ||
- Register commands with unique identifiers | ||
- Implement command handlers | ||
```typescript | ||
const command = extensionApi.commands.registerCommand('my-provider.start', async () => { | ||
try { | ||
await provider.start(); | ||
await extensionApi.window.showInformationMessage('Provider started successfully'); | ||
} catch (error) { | ||
await extensionApi.window.showErrorMessage(`Failed to start provider: ${error.message}`); | ||
} | ||
}); | ||
context.subscriptions.push(command); | ||
``` | ||
|
||
### Command Categories | ||
- Group related commands | ||
- Use consistent naming patterns | ||
```typescript | ||
{ | ||
"contributes": { | ||
"commands": [ | ||
{ | ||
"command": "my-provider.start", | ||
"title": "Start Provider", | ||
"category": "My Provider" | ||
}, | ||
{ | ||
"command": "my-provider.stop", | ||
"title": "Stop Provider", | ||
"category": "My Provider" | ||
} | ||
] | ||
} | ||
} | ||
``` | ||
|
||
## UI Integration | ||
|
||
### Status Bar Items | ||
- Create informative status bar items | ||
- Update status bar items based on state | ||
```typescript | ||
const statusBarItem = extensionApi.window.createStatusBarItem( | ||
extensionApi.StatusBarAlignLeft, | ||
100 | ||
); | ||
statusBarItem.text = 'My Provider'; | ||
statusBarItem.command = 'my-provider.showMenu'; | ||
context.subscriptions.push(statusBarItem); | ||
``` | ||
|
||
### Notifications | ||
- Use appropriate notification types | ||
- Provide actionable information | ||
```typescript | ||
// DO | ||
await extensionApi.window.showInformationMessage( | ||
'Provider requires configuration', | ||
'Configure Now', | ||
'Later' | ||
); | ||
|
||
// DON'T | ||
await extensionApi.window.showInformationMessage( | ||
'Provider error occurred' | ||
); | ||
``` | ||
|
||
## Configuration Management | ||
|
||
### Settings Definition | ||
- Define settings in package.json | ||
- Use appropriate types and validation | ||
```json | ||
{ | ||
"contributes": { | ||
"configuration": { | ||
"title": "My Provider", | ||
"properties": { | ||
"my-provider.endpoint": { | ||
"type": "string", | ||
"default": "http://localhost:8080", | ||
"description": "Provider endpoint URL" | ||
} | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### Settings Access | ||
- Use configuration API to access settings | ||
- Handle configuration changes | ||
```typescript | ||
const config = extensionApi.workspace.getConfiguration('my-provider'); | ||
const endpoint = config.get<string>('endpoint'); | ||
|
||
extensionApi.workspace.onDidChangeConfiguration(e => { | ||
if (e.affectsConfiguration('my-provider.endpoint')) { | ||
// Handle configuration change | ||
updateEndpoint(); | ||
} | ||
}); | ||
``` | ||
|
||
## Resource Management | ||
|
||
### Disposables | ||
- Register all disposables with extension context | ||
- Implement proper cleanup | ||
```typescript | ||
// DO | ||
const disposables: extensionApi.Disposable[] = []; | ||
disposables.push( | ||
extensionApi.commands.registerCommand('my-provider.command', () => {}), | ||
extensionApi.window.createStatusBarItem() | ||
); | ||
context.subscriptions.push(...disposables); | ||
|
||
// DON'T | ||
extensionApi.commands.registerCommand('my-provider.command', () => {}); | ||
``` | ||
|
||
### Event Handling | ||
- Use proper event subscription patterns | ||
- Clean up event listeners | ||
```typescript | ||
const listener = provider.onDidChangeStatus(status => { | ||
updateUI(status); | ||
}); | ||
context.subscriptions.push(listener); | ||
``` | ||
|
||
## Error Handling | ||
|
||
### API Errors | ||
- Handle API-specific errors | ||
- Provide user feedback | ||
```typescript | ||
try { | ||
await provider.performOperation(); | ||
} catch (error) { | ||
if (error instanceof extensionApi.ProviderError) { | ||
await extensionApi.window.showErrorMessage( | ||
`Provider error: ${error.message}`, | ||
'Retry', | ||
'Cancel' | ||
); | ||
} else { | ||
throw error; | ||
} | ||
} | ||
``` | ||
|
||
### Recovery Strategies | ||
- Implement graceful degradation | ||
- Provide recovery options | ||
```typescript | ||
async function handleProviderFailure(): Promise<voi |
Oops, something went wrong.