mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-01-23 02:36:05 +00:00
feat(plugin-api): create foundational plugin API package
- Add @super-productivity/plugin-api package with TypeScript definitions - Define core plugin interfaces, types, and manifest structure - Add plugin hooks system for event-driven architecture - Create plugin API type definitions and constants - Add documentation and development guidelines
This commit is contained in:
parent
296f987698
commit
d4d81bf511
248 changed files with 50093 additions and 683 deletions
1
packages/plugin-api/.gitignore
vendored
Normal file
1
packages/plugin-api/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
node_modules
|
||||
8
packages/plugin-api/.npmignore
Normal file
8
packages/plugin-api/.npmignore
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
src/
|
||||
tsconfig.json
|
||||
.git
|
||||
.gitignore
|
||||
*.log
|
||||
node_modules/
|
||||
.DS_Store
|
||||
*.tgz
|
||||
149
packages/plugin-api/DEVELOPMENT.md
Normal file
149
packages/plugin-api/DEVELOPMENT.md
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
# Plugin API Development Guide
|
||||
|
||||
## For Plugin Developers
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
npm install @super-productivity/plugin-api
|
||||
```
|
||||
|
||||
### TypeScript Setup
|
||||
|
||||
Create a `tsconfig.json` in your plugin project:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"lib": ["ES2020", "DOM"],
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
```
|
||||
|
||||
### Basic Plugin Structure
|
||||
|
||||
```
|
||||
my-plugin/
|
||||
├── src/
|
||||
│ └── plugin.ts
|
||||
├── dist/
|
||||
│ └── plugin.js
|
||||
├── manifest.json
|
||||
├── index.html (optional)
|
||||
├── icon.svg (optional)
|
||||
├── package.json
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
### Development Workflow
|
||||
|
||||
1. **Write TypeScript code** with full type safety
|
||||
2. **Compile to JavaScript** for Super Productivity
|
||||
3. **Test in Super Productivity** plugin system
|
||||
|
||||
### Example Build Script
|
||||
|
||||
Add to your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"build:watch": "tsc --watch",
|
||||
"dev": "tsc --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@super-productivity/plugin-api": "^1.0.0",
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Plugin Template
|
||||
|
||||
See `example/my-plugin.ts` for a complete TypeScript plugin example.
|
||||
|
||||
## For Core Developers
|
||||
|
||||
### Updating the API
|
||||
|
||||
When adding new features to the plugin system:
|
||||
|
||||
1. **Update `src/types.ts`** with new interfaces/types
|
||||
2. **Update `src/index.ts`** to export new types
|
||||
3. **Update `README.md`** with usage examples
|
||||
4. **Version bump** the package
|
||||
5. **Rebuild and test**
|
||||
6. **Publish to npm**
|
||||
|
||||
### Syncing with Main Project
|
||||
|
||||
The main Super Productivity project should eventually import types from this package instead of maintaining local definitions:
|
||||
|
||||
```typescript
|
||||
// Before:
|
||||
import { PluginManifest } from './plugin-api.model';
|
||||
|
||||
// After:
|
||||
import type { PluginManifest } from '@super-productivity/plugin-api';
|
||||
```
|
||||
|
||||
### Testing Changes
|
||||
|
||||
1. Build the package: `npm run build`
|
||||
2. Test locally: `npm link` in this directory
|
||||
3. In test project: `npm link @super-productivity/plugin-api`
|
||||
4. Verify types work correctly
|
||||
|
||||
### Release Process
|
||||
|
||||
1. Update version: `npm version patch|minor|major`
|
||||
2. Build: `npm run build`
|
||||
3. Test: `npm pack --dry-run`
|
||||
4. Publish: `npm publish --access public`
|
||||
|
||||
## Available Types Reference
|
||||
|
||||
### Core Interfaces
|
||||
|
||||
- `PluginAPI` - Main API interface
|
||||
- `PluginManifest` - Plugin configuration
|
||||
- `PluginBaseCfg` - Runtime configuration
|
||||
|
||||
### Hook Types
|
||||
|
||||
- `PluginHooks` - Available hook events
|
||||
- `PluginHookHandler` - Hook function signature
|
||||
|
||||
### Data Types
|
||||
|
||||
- `TaskData` - Task information
|
||||
- `ProjectData` - Project information
|
||||
- `TagData` - Tag information
|
||||
- `PluginCreateTaskData` - Task creation data
|
||||
|
||||
### UI Types
|
||||
|
||||
- `DialogCfg` - Dialog configuration
|
||||
- `DialogButtonCfg` - Dialog button configuration
|
||||
- `SnackCfg` - Notification configuration
|
||||
- `NotifyCfg` - System notification configuration
|
||||
- `PluginMenuEntryCfg` - Menu entry configuration
|
||||
- `PluginShortcutCfg` - Keyboard shortcut configuration
|
||||
- `PluginHeaderBtnCfg` - Header button configuration
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always use TypeScript** for plugin development
|
||||
2. **Import types only** to avoid runtime dependencies
|
||||
3. **Follow semantic versioning** for plugin releases
|
||||
4. **Test thoroughly** before publishing
|
||||
5. **Document your plugins** for other developers
|
||||
91
packages/plugin-api/PUBLISHING.md
Normal file
91
packages/plugin-api/PUBLISHING.md
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# Publishing @super-productivity/plugin-api
|
||||
|
||||
## Overview
|
||||
|
||||
This package provides TypeScript definitions for Super Productivity plugin development. It's published to npm as `@super-productivity/plugin-api`.
|
||||
|
||||
## Publishing Process
|
||||
|
||||
### 1. Update Version
|
||||
|
||||
Update the version in `package.json`:
|
||||
|
||||
```bash
|
||||
cd packages/plugin-api
|
||||
npm version patch # or minor/major
|
||||
```
|
||||
|
||||
### 2. Build the Package
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 3. Test the Build
|
||||
|
||||
```bash
|
||||
npm pack --dry-run
|
||||
```
|
||||
|
||||
### 4. Publish to npm
|
||||
|
||||
For stable releases:
|
||||
|
||||
```bash
|
||||
npm publish --access public
|
||||
```
|
||||
|
||||
For beta releases:
|
||||
|
||||
```bash
|
||||
npm publish --tag beta --access public
|
||||
```
|
||||
|
||||
## Project Integration
|
||||
|
||||
### Updating the Main Project
|
||||
|
||||
When updating the plugin API types, you need to:
|
||||
|
||||
1. **Update this package** with new types/interfaces
|
||||
2. **Rebuild the package**: `npm run build`
|
||||
3. **Update the main project** to use the new types from this package instead of local definitions
|
||||
4. **Test the integration** to ensure everything works
|
||||
|
||||
### Using in the Main Project
|
||||
|
||||
The main project should import types from this package:
|
||||
|
||||
```typescript
|
||||
// Instead of local imports:
|
||||
// import { PluginManifest } from './plugin-api.model';
|
||||
|
||||
// Use the npm package:
|
||||
import type { PluginManifest } from '@super-productivity/plugin-api';
|
||||
```
|
||||
|
||||
## Package Structure
|
||||
|
||||
```
|
||||
packages/plugin-api/
|
||||
├── src/
|
||||
│ ├── index.ts # Main export file
|
||||
│ └── types.ts # All type definitions
|
||||
├── dist/ # Built output (generated)
|
||||
├── package.json # Package configuration
|
||||
├── tsconfig.json # TypeScript configuration
|
||||
├── README.md # User documentation
|
||||
├── PUBLISHING.md # This file
|
||||
└── .npmignore # Files to exclude from npm
|
||||
```
|
||||
|
||||
## Maintenance
|
||||
|
||||
- Keep types in sync with the main project's plugin system
|
||||
- Update documentation when adding new features
|
||||
- Follow semantic versioning for releases
|
||||
- Test changes with actual plugin development
|
||||
|
||||
## Version History
|
||||
|
||||
- `1.0.0` - Initial release with core plugin API types
|
||||
171
packages/plugin-api/README.md
Normal file
171
packages/plugin-api/README.md
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
# @super-productivity/plugin-api
|
||||
|
||||
Official TypeScript definitions for developing [Super Productivity](https://github.com/johannesjo/super-productivity) plugins.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @super-productivity/plugin-api
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### TypeScript Plugin Development
|
||||
|
||||
```typescript
|
||||
import type {
|
||||
PluginAPI,
|
||||
PluginManifest,
|
||||
PluginHooks,
|
||||
} from '@super-productivity/plugin-api';
|
||||
|
||||
// Your plugin code with full type support
|
||||
PluginAPI.registerHook(PluginHooks.TASK_COMPLETE, (taskData) => {
|
||||
console.log('Task completed!', taskData);
|
||||
|
||||
PluginAPI.showSnack({
|
||||
msg: 'Task completed successfully!',
|
||||
type: 'SUCCESS',
|
||||
ico: 'celebration',
|
||||
});
|
||||
});
|
||||
|
||||
// Register a header button
|
||||
PluginAPI.registerHeaderButton({
|
||||
label: 'My Plugin',
|
||||
icon: 'extension',
|
||||
onClick: () => {
|
||||
PluginAPI.showIndexHtmlAsView();
|
||||
},
|
||||
});
|
||||
|
||||
// Register a keyboard shortcut
|
||||
PluginAPI.registerShortcut({
|
||||
id: 'my_shortcut',
|
||||
label: 'My Custom Shortcut',
|
||||
onExec: () => {
|
||||
PluginAPI.showSnack({
|
||||
msg: 'Shortcut executed!',
|
||||
type: 'SUCCESS',
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Plugin Manifest
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "My Awesome Plugin",
|
||||
"id": "my-awesome-plugin",
|
||||
"manifestVersion": 1,
|
||||
"version": "1.0.0",
|
||||
"minSupVersion": "13.0.0",
|
||||
"description": "An awesome plugin for Super Productivity",
|
||||
"hooks": ["taskComplete", "taskUpdate"],
|
||||
"permissions": ["showSnack", "getTasks", "addTask", "showIndexHtmlAsView"],
|
||||
"iFrame": true,
|
||||
"icon": "icon.svg"
|
||||
}
|
||||
```
|
||||
|
||||
## Available Types
|
||||
|
||||
### Core Types
|
||||
|
||||
- `PluginAPI` - Main plugin API interface
|
||||
- `PluginManifest` - Plugin configuration
|
||||
- `PluginHooks` - Available hook types
|
||||
- `PluginBaseCfg` - Runtime configuration
|
||||
|
||||
### Data Types
|
||||
|
||||
- `TaskData` - Task information
|
||||
- `ProjectData` - Project information
|
||||
- `TagData` - Tag information
|
||||
|
||||
### UI Types
|
||||
|
||||
- `DialogCfg` - Dialog configuration
|
||||
- `SnackCfg` - Notification configuration
|
||||
- `PluginMenuEntryCfg` - Menu entry configuration
|
||||
- `PluginShortcutCfg` - Keyboard shortcut configuration
|
||||
|
||||
## Plugin Development Guide
|
||||
|
||||
### 1. Available Hooks
|
||||
|
||||
```typescript
|
||||
enum PluginHooks {
|
||||
TASK_COMPLETE = 'taskComplete',
|
||||
TASK_UPDATE = 'taskUpdate',
|
||||
TASK_DELETE = 'taskDelete',
|
||||
FINISH_DAY = 'finishDay',
|
||||
LANGUAGE_CHANGE = 'languageChange',
|
||||
PERSISTED_DATA_UPDATE = 'persistedDataUpdate',
|
||||
ACTION = 'action',
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Required Permissions
|
||||
|
||||
Add these to your manifest.json based on what your plugin needs:
|
||||
|
||||
- `showSnack` - Show notifications
|
||||
- `notify` - System notifications
|
||||
- `showIndexHtmlAsView` - Display plugin UI
|
||||
- `openDialog` - Show dialogs
|
||||
- `getTasks` - Read tasks
|
||||
- `getArchivedTasks` - Read archived tasks
|
||||
- `getCurrentContextTasks` - Read current context tasks
|
||||
- `addTask` - Create tasks
|
||||
- `getAllProjects` - Read projects
|
||||
- `addProject` - Create projects
|
||||
- `getAllTags` - Read tags
|
||||
- `addTag` - Create tags
|
||||
- `persistDataSynced` - Persist plugin data
|
||||
|
||||
### 3. Plugin Structure
|
||||
|
||||
```
|
||||
my-plugin/
|
||||
├── manifest.json
|
||||
├── plugin.js
|
||||
├── index.html (optional, if iFrame: true)
|
||||
└── icon.svg (optional)
|
||||
```
|
||||
|
||||
### 4. Example Plugin
|
||||
|
||||
```javascript
|
||||
// plugin.js
|
||||
console.log('My Plugin initializing...', PluginAPI);
|
||||
|
||||
// Register hook for task completion
|
||||
PluginAPI.registerHook(PluginAPI.Hooks.TASK_COMPLETE, function (taskData) {
|
||||
console.log('Task completed!', taskData);
|
||||
|
||||
PluginAPI.showSnack({
|
||||
msg: '🎉 Task completed!',
|
||||
type: 'SUCCESS',
|
||||
ico: 'celebration',
|
||||
});
|
||||
});
|
||||
|
||||
// Register header button
|
||||
PluginAPI.registerHeaderButton({
|
||||
label: 'My Plugin',
|
||||
icon: 'dashboard',
|
||||
onClick: function () {
|
||||
PluginAPI.showIndexHtmlAsView();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT - See the main Super Productivity repository for details.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please contribute to the main [Super Productivity repository](https://github.com/johannesjo/super-productivity).
|
||||
100
packages/plugin-api/example/my-plugin.ts
Normal file
100
packages/plugin-api/example/my-plugin.ts
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// Example TypeScript plugin using @super-productivity/plugin-api
|
||||
|
||||
import type {
|
||||
PluginAPI,
|
||||
PluginHooks,
|
||||
TaskData,
|
||||
PluginManifest,
|
||||
} from '@super-productivity/plugin-api';
|
||||
|
||||
// Example manifest (would be in manifest.json)
|
||||
const manifest: PluginManifest = {
|
||||
name: 'My Awesome Plugin',
|
||||
id: 'my-awesome-plugin',
|
||||
manifestVersion: 1,
|
||||
version: '1.0.0',
|
||||
minSupVersion: '13.0.0',
|
||||
description: 'An example plugin with full TypeScript support',
|
||||
hooks: [PluginHooks.TASK_COMPLETE, PluginHooks.TASK_UPDATE],
|
||||
permissions: ['showSnack', 'getTasks', 'addTask', 'showIndexHtmlAsView', 'openDialog'],
|
||||
iFrame: true,
|
||||
icon: 'icon.svg',
|
||||
};
|
||||
|
||||
// Plugin code with full type safety
|
||||
console.log('My Plugin initializing...', PluginAPI);
|
||||
|
||||
// Register hook with typed parameters
|
||||
PluginAPI.registerHook(PluginHooks.TASK_COMPLETE, (taskData: TaskData) => {
|
||||
console.log('Task completed!', taskData);
|
||||
|
||||
PluginAPI.showSnack({
|
||||
msg: `🎉 Completed: ${taskData.title}`,
|
||||
type: 'SUCCESS',
|
||||
ico: 'celebration',
|
||||
});
|
||||
});
|
||||
|
||||
// Register header button with type safety
|
||||
PluginAPI.registerHeaderButton({
|
||||
label: 'My Dashboard',
|
||||
icon: 'dashboard',
|
||||
onClick: () => {
|
||||
PluginAPI.showIndexHtmlAsView();
|
||||
},
|
||||
});
|
||||
|
||||
// Register keyboard shortcut
|
||||
PluginAPI.registerShortcut({
|
||||
id: 'create_example_task',
|
||||
label: 'Create Example Task',
|
||||
onExec: async () => {
|
||||
try {
|
||||
const taskId = await PluginAPI.addTask({
|
||||
title: '🔌 Task from TypeScript Plugin',
|
||||
notes: 'This task was created with full type safety!',
|
||||
tagIds: [],
|
||||
});
|
||||
|
||||
PluginAPI.showSnack({
|
||||
msg: `✅ Created task: ${taskId}`,
|
||||
type: 'SUCCESS',
|
||||
});
|
||||
} catch (error) {
|
||||
PluginAPI.showSnack({
|
||||
msg: '❌ Failed to create task',
|
||||
type: 'ERROR',
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Example of working with tasks
|
||||
async function processAllTasks() {
|
||||
try {
|
||||
const tasks = await PluginAPI.getTasks();
|
||||
const completedTasks = tasks.filter((task) => task.isDone);
|
||||
|
||||
PluginAPI.openDialog({
|
||||
htmlContent: `
|
||||
<div style="padding: 20px;">
|
||||
<h2>Task Summary</h2>
|
||||
<p>Total tasks: ${tasks.length}</p>
|
||||
<p>Completed: ${completedTasks.length}</p>
|
||||
<p>Remaining: ${tasks.length - completedTasks.length}</p>
|
||||
</div>
|
||||
`,
|
||||
buttons: [
|
||||
{
|
||||
label: 'Close',
|
||||
icon: 'close',
|
||||
onClick: () => {
|
||||
console.log('Dialog closed');
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to process tasks:', error);
|
||||
}
|
||||
}
|
||||
32
packages/plugin-api/package-lock.json
generated
Normal file
32
packages/plugin-api/package-lock.json
generated
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "@super-productivity/plugin-api",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@super-productivity/plugin-api",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.8.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
packages/plugin-api/package.json
Normal file
42
packages/plugin-api/package.json
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"name": "@super-productivity/plugin-api",
|
||||
"version": "1.0.0",
|
||||
"description": "TypeScript definitions for Super Productivity plugin development",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"build:watch": "tsc --watch",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"keywords": [
|
||||
"super-productivity",
|
||||
"plugin",
|
||||
"typescript",
|
||||
"types",
|
||||
"productivity",
|
||||
"task-management"
|
||||
],
|
||||
"author": "Johannes Millan",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/johannesjo/super-productivity.git",
|
||||
"directory": "packages/plugin-api"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/johannesjo/super-productivity/issues"
|
||||
},
|
||||
"homepage": "https://github.com/johannesjo/super-productivity#readme",
|
||||
"files": [
|
||||
"dist/**/*",
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
],
|
||||
"devDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
15
packages/plugin-api/publish.sh
Executable file
15
packages/plugin-api/publish.sh
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Script to build and publish the plugin API package
|
||||
|
||||
set -e
|
||||
|
||||
echo "Building @super-productivity/plugin-api..."
|
||||
npm run build
|
||||
|
||||
echo "Testing the package..."
|
||||
npm pack --dry-run
|
||||
|
||||
echo "Ready to publish!"
|
||||
echo "To publish to npm, run: npm publish --access public"
|
||||
echo "To publish a beta version, run: npm publish --tag beta --access public"
|
||||
35
packages/plugin-api/src/index.ts
Normal file
35
packages/plugin-api/src/index.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// Super Productivity Plugin API Types
|
||||
// Official TypeScript definitions for developing Super Productivity plugins
|
||||
|
||||
export * from './types';
|
||||
|
||||
// Re-export commonly used types with cleaner names
|
||||
export type {
|
||||
PluginAPI,
|
||||
PluginManifest,
|
||||
TaskData,
|
||||
ProjectData,
|
||||
TagData,
|
||||
PluginCreateTaskData,
|
||||
PluginBaseCfg,
|
||||
DialogCfg,
|
||||
DialogButtonCfg,
|
||||
SnackCfg,
|
||||
SnackCfgLimited,
|
||||
NotifyCfg,
|
||||
PluginMenuEntryCfg,
|
||||
PluginShortcutCfg,
|
||||
PluginHeaderBtnCfg,
|
||||
PluginHookHandler,
|
||||
PluginInstance,
|
||||
PluginHookHandlerRegistration,
|
||||
TaskCopy,
|
||||
ProjectCopy,
|
||||
TagCopy,
|
||||
} from './types';
|
||||
|
||||
// Re-export enums as values (not just types) so they can be used
|
||||
export { PluginHooks, type Hooks } from './types';
|
||||
|
||||
// Export app-specific types that extend the plugin-api versions
|
||||
export type { PluginMenuEntryCfg as PluginMenuEntryCfgApp } from './types';
|
||||
27
packages/plugin-api/src/types.js
Normal file
27
packages/plugin-api/src/types.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
'use strict';
|
||||
// Types for Super Productivity Plugin API
|
||||
// This package provides TypeScript types for developing plugins
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
exports.PluginHooks = void 0;
|
||||
var PluginHooks;
|
||||
(function (PluginHooks) {
|
||||
PluginHooks['TASK_COMPLETE'] = 'taskComplete';
|
||||
PluginHooks['TASK_UPDATE'] = 'taskUpdate';
|
||||
PluginHooks['TASK_DELETE'] = 'taskDelete';
|
||||
PluginHooks['CURRENT_TASK_CHANGE'] = 'currentTaskChange';
|
||||
PluginHooks['FINISH_DAY'] = 'finishDay';
|
||||
PluginHooks['LANGUAGE_CHANGE'] = 'languageChange';
|
||||
PluginHooks['PERSISTED_DATA_UPDATE'] = 'persistedDataUpdate';
|
||||
PluginHooks['ACTION'] = 'action';
|
||||
})(PluginHooks || (exports.PluginHooks = PluginHooks = {}));
|
||||
// Global PluginAPI interface for runtime use
|
||||
// Note: This is commented out to avoid conflicts with node_modules version
|
||||
// declare global {
|
||||
// interface Window {
|
||||
// PluginAPI: PluginAPI;
|
||||
// }
|
||||
//
|
||||
// // For plugin development without window reference
|
||||
// const PluginAPI: PluginAPI;
|
||||
// }
|
||||
//# sourceMappingURL=types.js.map
|
||||
1
packages/plugin-api/src/types.js.map
Normal file
1
packages/plugin-api/src/types.js.map
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":";AAAA,0CAA0C;AAC1C,gEAAgE;;;AAShE,IAAY,WASX;AATD,WAAY,WAAW;IACrB,6CAA8B,CAAA;IAC9B,yCAA0B,CAAA;IAC1B,yCAA0B,CAAA;IAC1B,wDAAyC,CAAA;IACzC,uCAAwB,CAAA;IACxB,iDAAkC,CAAA;IAClC,4DAA6C,CAAA;IAC7C,gCAAiB,CAAA;AACnB,CAAC,EATW,WAAW,2BAAX,WAAW,QAStB;AA0PD,6CAA6C;AAC7C,2EAA2E;AAC3E,mBAAmB;AACnB,uBAAuB;AACvB,4BAA4B;AAC5B,MAAM;AACN,EAAE;AACF,uDAAuD;AACvD,gCAAgC;AAChC,IAAI"}
|
||||
328
packages/plugin-api/src/types.ts
Normal file
328
packages/plugin-api/src/types.ts
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
// Types for Super Productivity Plugin API
|
||||
// This package provides TypeScript types for developing plugins
|
||||
|
||||
export interface PluginMenuEntryCfg {
|
||||
pluginId: string;
|
||||
label: string;
|
||||
icon?: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export enum PluginHooks {
|
||||
TASK_COMPLETE = 'taskComplete',
|
||||
TASK_UPDATE = 'taskUpdate',
|
||||
TASK_DELETE = 'taskDelete',
|
||||
CURRENT_TASK_CHANGE = 'currentTaskChange',
|
||||
FINISH_DAY = 'finishDay',
|
||||
LANGUAGE_CHANGE = 'languageChange',
|
||||
PERSISTED_DATA_UPDATE = 'persistedDataUpdate',
|
||||
ACTION = 'action',
|
||||
}
|
||||
|
||||
export type Hooks = PluginHooks;
|
||||
|
||||
export interface PluginBaseCfg {
|
||||
theme: 'light' | 'dark';
|
||||
appVersion: string;
|
||||
platform: 'web' | 'desktop' | 'android' | 'ios';
|
||||
isDev: boolean;
|
||||
lang?: {
|
||||
code: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DialogButtonCfg {
|
||||
label: string;
|
||||
icon?: string;
|
||||
onClick: () => void | Promise<void>;
|
||||
color?: 'primary' | 'warn';
|
||||
}
|
||||
|
||||
export interface DialogCfg {
|
||||
htmlContent?: string;
|
||||
buttons?: DialogButtonCfg[];
|
||||
}
|
||||
|
||||
export interface SnackCfg {
|
||||
msg: string;
|
||||
type?: 'SUCCESS' | 'ERROR' | 'WARNING' | 'INFO';
|
||||
ico?: string;
|
||||
}
|
||||
|
||||
export type SnackCfgLimited = SnackCfg;
|
||||
|
||||
export interface NotifyCfg {
|
||||
title: string;
|
||||
body: string;
|
||||
}
|
||||
|
||||
export interface PluginNodeScriptConfig {
|
||||
allowedPaths?: string[]; // Specific paths the script can access
|
||||
timeout?: number; // Default timeout in milliseconds for scripts
|
||||
memoryLimit?: string; // Default memory limit (e.g., '128MB', '256MB')
|
||||
}
|
||||
|
||||
export interface PluginNodeScriptRequest {
|
||||
script: string;
|
||||
timeout?: number;
|
||||
args?: unknown[];
|
||||
}
|
||||
|
||||
export interface PluginNodeScriptError {
|
||||
code:
|
||||
| 'TIMEOUT'
|
||||
| 'MEMORY_LIMIT'
|
||||
| 'SCRIPT_ERROR'
|
||||
| 'PERMISSION_DENIED'
|
||||
| 'INVALID_SCRIPT'
|
||||
| 'NO_CONSENT';
|
||||
message: string;
|
||||
details?: {
|
||||
line?: number;
|
||||
column?: number;
|
||||
scriptSnippet?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PluginNodeScriptResult {
|
||||
success: boolean;
|
||||
result?: unknown;
|
||||
error?: string | PluginNodeScriptError;
|
||||
executionTime?: number;
|
||||
resourceUsage?: {
|
||||
peakMemoryMB?: number;
|
||||
cpuTime?: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PluginManifest {
|
||||
name: string;
|
||||
id: string;
|
||||
manifestVersion: number;
|
||||
version: string;
|
||||
minSupVersion: string;
|
||||
description?: string;
|
||||
hooks: Hooks[];
|
||||
permissions: string[];
|
||||
iFrame?: boolean;
|
||||
isSkipMenuEntry?: boolean;
|
||||
type?: 'standard';
|
||||
assets?: string[];
|
||||
icon?: string; // Path to SVG icon file relative to plugin root
|
||||
nodeScriptConfig?: PluginNodeScriptConfig;
|
||||
sidePanel?: boolean; // If true, plugin loads in right panel instead of route
|
||||
}
|
||||
|
||||
export type PluginHookHandler = (...args: unknown[]) => void | Promise<void>;
|
||||
|
||||
// Core data types - Single source of truth for both plugins and app
|
||||
export interface Task {
|
||||
id: string;
|
||||
title: string;
|
||||
notes?: string;
|
||||
timeEstimate: number;
|
||||
timeSpent: number;
|
||||
isDone: boolean;
|
||||
projectId: string | null;
|
||||
tagIds: string[];
|
||||
parentId?: string | null;
|
||||
created: number;
|
||||
updated?: number;
|
||||
subTaskIds: string[];
|
||||
|
||||
// Additional fields for internal use (plugins can read but shouldn't modify)
|
||||
timeSpentOnDay?: { [key: string]: number };
|
||||
doneOn?: number | null;
|
||||
attachments?: any[];
|
||||
reminderId?: string | null;
|
||||
repeatCfgId?: string | null;
|
||||
|
||||
// Issue tracking fields (optional)
|
||||
issueId?: string | null;
|
||||
issueProviderId?: string | null;
|
||||
issueType?: any | null; // IssueProviderKey in app
|
||||
issueWasUpdated?: boolean;
|
||||
issueLastUpdated?: number | null;
|
||||
issueAttachmentNr?: number;
|
||||
issuePoints?: number | null;
|
||||
|
||||
// UI state (internal)
|
||||
_hideSubTasksMode?: number;
|
||||
}
|
||||
|
||||
export interface Project {
|
||||
id: string;
|
||||
title: string;
|
||||
theme: {
|
||||
primary?: string;
|
||||
isAutoContrast?: boolean;
|
||||
[key: string]: any;
|
||||
};
|
||||
isArchived?: boolean;
|
||||
created?: number;
|
||||
updated?: number;
|
||||
taskIds: string[];
|
||||
backlogTaskIds: string[];
|
||||
noteIds: string[];
|
||||
isEnableBacklog?: boolean;
|
||||
isHiddenFromMenu?: boolean;
|
||||
|
||||
// Advanced config (internal) - must be any to match WorkContextCommon
|
||||
advancedCfg: any;
|
||||
icon?: string | null;
|
||||
}
|
||||
|
||||
export interface Tag {
|
||||
id: string;
|
||||
title: string;
|
||||
color?: string | null;
|
||||
created: number;
|
||||
updated?: number;
|
||||
taskIds: string[];
|
||||
icon?: string | null;
|
||||
|
||||
// Advanced config (internal) - must be any to match WorkContextCommon
|
||||
theme: any;
|
||||
advancedCfg: any;
|
||||
}
|
||||
|
||||
// Legacy aliases for backward compatibility
|
||||
/** @deprecated Use Task instead */
|
||||
export type TaskData = Task;
|
||||
/** @deprecated Use Task instead */
|
||||
export type TaskCopy = Task;
|
||||
|
||||
/** @deprecated Use Project instead */
|
||||
export type ProjectData = Project;
|
||||
/** @deprecated Use Project instead */
|
||||
export type ProjectCopy = Project;
|
||||
|
||||
/** @deprecated Use Tag instead */
|
||||
export type TagData = Tag;
|
||||
/** @deprecated Use Tag instead */
|
||||
export type TagCopy = Tag;
|
||||
|
||||
export interface PluginHeaderBtnCfg {
|
||||
pluginId: string;
|
||||
label: string;
|
||||
icon?: string;
|
||||
onClick: () => void;
|
||||
color?: 'primary' | 'accent' | 'warn';
|
||||
}
|
||||
|
||||
export interface PluginSidePanelBtnCfg {
|
||||
pluginId: string;
|
||||
label: string;
|
||||
icon?: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export interface PluginAPI {
|
||||
cfg: PluginBaseCfg;
|
||||
|
||||
registerHook(hook: Hooks, fn: PluginHookHandler): void;
|
||||
|
||||
registerHeaderButton(headerBtnCfg: Omit<PluginHeaderBtnCfg, 'pluginId'>): void;
|
||||
|
||||
registerMenuEntry(menuEntryCfg: Omit<PluginMenuEntryCfg, 'pluginId'>): void;
|
||||
|
||||
registerShortcut(
|
||||
shortcutCfg: Omit<PluginShortcutCfg, 'pluginId'> & { id?: string },
|
||||
): void;
|
||||
|
||||
registerSidePanelButton(sidePanelBtnCfg: Omit<PluginSidePanelBtnCfg, 'pluginId'>): void;
|
||||
|
||||
// ui bridge
|
||||
showSnack(snackCfg: SnackCfg): void;
|
||||
|
||||
notify(notifyCfg: NotifyCfg): Promise<void>;
|
||||
|
||||
showIndexHtmlAsView(): void;
|
||||
|
||||
openDialog(dialogCfg: DialogCfg): Promise<void>;
|
||||
|
||||
// tasks
|
||||
getTasks(): Promise<Task[]>;
|
||||
|
||||
getArchivedTasks(): Promise<Task[]>;
|
||||
|
||||
getCurrentContextTasks(): Promise<Task[]>;
|
||||
|
||||
updateTask(taskId: string, updates: Partial<Task>): Promise<void>;
|
||||
|
||||
addTask(taskData: PluginCreateTaskData): Promise<string>;
|
||||
|
||||
// projects
|
||||
getAllProjects(): Promise<Project[]>;
|
||||
|
||||
addProject(projectData: Partial<Project>): Promise<string>;
|
||||
|
||||
updateProject(projectId: string, updates: Partial<Project>): Promise<void>;
|
||||
|
||||
// tags
|
||||
getAllTags(): Promise<Tag[]>;
|
||||
|
||||
addTag(tagData: Partial<Tag>): Promise<string>;
|
||||
|
||||
updateTag(tagId: string, updates: Partial<Tag>): Promise<void>;
|
||||
|
||||
// task ordering
|
||||
reorderTasks(
|
||||
taskIds: string[],
|
||||
contextId: string,
|
||||
contextType: 'project' | 'task',
|
||||
): Promise<void>;
|
||||
|
||||
// persistence
|
||||
persistDataSynced(dataStr: string): Promise<void>;
|
||||
|
||||
loadSyncedData(): Promise<string | null>;
|
||||
|
||||
// node execution (only available in Electron with nodeExecution permission)
|
||||
executeNodeScript?(request: PluginNodeScriptRequest): Promise<PluginNodeScriptResult>;
|
||||
|
||||
// action execution - dispatch NgRx actions (limited to allowed subset)
|
||||
dispatchAction(action: any): void;
|
||||
}
|
||||
|
||||
export interface PluginInstance {
|
||||
manifest: PluginManifest;
|
||||
loaded: boolean;
|
||||
isEnabled: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface PluginHookHandlerRegistration {
|
||||
pluginId: string;
|
||||
hook: Hooks;
|
||||
handler: PluginHookHandler;
|
||||
}
|
||||
|
||||
export interface PluginCreateTaskData {
|
||||
title: string;
|
||||
projectId?: string | null;
|
||||
tagIds?: string[];
|
||||
notes?: string;
|
||||
timeEstimate?: number;
|
||||
parentId?: string | null;
|
||||
isDone?: boolean;
|
||||
}
|
||||
|
||||
export interface PluginShortcutCfg {
|
||||
pluginId: string;
|
||||
id: string;
|
||||
label: string;
|
||||
onExec: () => void;
|
||||
}
|
||||
|
||||
// Global PluginAPI interface for runtime use
|
||||
// Note: This is commented out to avoid conflicts with node_modules version
|
||||
// declare global {
|
||||
// interface Window {
|
||||
// PluginAPI: PluginAPI;
|
||||
// }
|
||||
//
|
||||
// // For plugin development without window reference
|
||||
// const PluginAPI: PluginAPI;
|
||||
// }
|
||||
20
packages/plugin-api/tsconfig.json
Normal file
20
packages/plugin-api/tsconfig.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"lib": ["ES2020", "DOM"],
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"noEmitOnError": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue