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:
Johannes Millan 2025-06-27 18:13:19 +02:00
parent 296f987698
commit d4d81bf511
248 changed files with 50093 additions and 683 deletions

1
packages/plugin-api/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
node_modules

View file

@ -0,0 +1,8 @@
src/
tsconfig.json
.git
.gitignore
*.log
node_modules/
.DS_Store
*.tgz

View 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

View 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

View 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).

View 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
View 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"
}
}
}
}

View 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
View 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"

View 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';

View 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

View 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"}

View 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;
// }

View 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"]
}