@wealthfolio/addon-sdk 3.6.2 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/README.md +312 -206
- package/dist/{chunk-BFZMXPHG.js → chunk-2IM7BFJX.js} +3 -3
- package/dist/{chunk-BFZMXPHG.js.map → chunk-2IM7BFJX.js.map} +1 -1
- package/dist/{chunk-KCG6RCFW.js → chunk-3YZER4XO.js} +16 -2
- package/dist/chunk-3YZER4XO.js.map +1 -0
- package/dist/{chunk-K7KLLX42.js → chunk-5727GMVD.js} +1 -1
- package/dist/chunk-5727GMVD.js.map +1 -0
- package/dist/{chunk-AAIYUZY5.js → chunk-DQNFXUZ7.js} +3 -3
- package/dist/{chunk-AAIYUZY5.js.map → chunk-DQNFXUZ7.js.map} +1 -1
- package/dist/host-dependencies.js +1 -1
- package/dist/index.js +28 -5
- package/dist/index.js.map +1 -1
- package/dist/manifest.js +1 -1
- package/dist/permissions.js +1 -1
- package/dist/src/data-types.d.ts +90 -1
- package/dist/src/host-api.d.ts +67 -3
- package/dist/src/host-dependencies.d.ts +2 -2
- package/dist/src/i18n.d.ts +55 -0
- package/dist/src/index.d.ts +5 -3
- package/dist/src/manifest.d.ts +16 -1
- package/dist/src/types.d.ts +18 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-K7KLLX42.js.map +0 -1
- package/dist/chunk-KCG6RCFW.js.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HOST_DEPENDENCIES
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-DQNFXUZ7.js";
|
|
4
4
|
|
|
5
5
|
// package.json
|
|
6
6
|
var package_default = {
|
|
7
7
|
name: "@wealthfolio/addon-sdk",
|
|
8
|
-
version: "3.
|
|
8
|
+
version: "3.8.0",
|
|
9
9
|
type: "module",
|
|
10
10
|
description: "TypeScript SDK for building Wealthfolio addons with enhanced functionality and type safety",
|
|
11
11
|
main: "dist/index.js",
|
|
@@ -190,4 +190,4 @@ export {
|
|
|
190
190
|
generateAddonId,
|
|
191
191
|
isAddonManifest
|
|
192
192
|
};
|
|
193
|
-
//# sourceMappingURL=chunk-
|
|
193
|
+
//# sourceMappingURL=chunk-2IM7BFJX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/version.ts","../src/utils.ts"],"sourcesContent":["{\n \"name\": \"@wealthfolio/addon-sdk\",\n \"version\": \"3.6.2\",\n \"type\": \"module\",\n \"description\": \"TypeScript SDK for building Wealthfolio addons with enhanced functionality and type safety\",\n \"main\": \"dist/index.js\",\n \"types\": \"dist/src/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/src/index.d.ts\"\n },\n \"./types\": {\n \"import\": \"./dist/types.js\",\n \"types\": \"./dist/src/types.d.ts\"\n },\n \"./host-api\": {\n \"import\": \"./dist/host-api.js\",\n \"types\": \"./dist/src/host-api.d.ts\"\n },\n \"./host-dependencies\": {\n \"import\": \"./dist/host-dependencies.js\",\n \"types\": \"./dist/src/host-dependencies.d.ts\"\n },\n \"./manifest\": {\n \"import\": \"./dist/manifest.js\",\n \"types\": \"./dist/src/manifest.d.ts\"\n },\n \"./permissions\": {\n \"import\": \"./dist/permissions.js\",\n \"types\": \"./dist/src/permissions.d.ts\"\n },\n \"./query-keys\": {\n \"import\": \"./dist/query-keys.js\",\n \"types\": \"./dist/src/query-keys.d.ts\"\n },\n \"./utils\": {\n \"import\": \"./dist/utils.js\",\n \"types\": \"./dist/src/utils.d.ts\"\n },\n \"./goal-progress\": {\n \"import\": \"./dist/goal-progress.js\",\n \"types\": \"./dist/src/goal-progress.d.ts\"\n }\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"CHANGELOG.md\"\n ],\n \"keywords\": [\n \"wealthfolio\",\n \"addon\",\n \"plugin\",\n \"sdk\",\n \"typescript\",\n \"financial\",\n \"portfolio\"\n ],\n \"author\": \"Wealthfolio Team\",\n \"license\": \"MIT\",\n \"homepage\": \"https://wealthfolio.app/addons\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/wealthfolio/wealthfolio.git\",\n \"directory\": \"packages/addon-sdk\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/wealthfolio/wealthfolio/issues\"\n },\n \"scripts\": {\n \"build\": \"tsup && pnpm run build:types\",\n \"dev\": \"tsup --watch\",\n \"clean\": \"rm -rf dist\",\n \"lint\": \"eslint .\",\n \"lint:fix\": \"eslint . --fix\",\n \"lint:quiet\": \"eslint . --quiet\",\n \"format\": \"prettier --write .\",\n \"format:check\": \"prettier --check .\",\n \"type-check\": \"tsc --noEmit\",\n \"build:types\": \"tsc -p tsconfig.json\",\n \"prepack\": \"npm run build\"\n },\n \"peerDependencies\": {\n \"react\": \"^19.2.4\",\n \"react-dom\": \"^19.2.4\"\n },\n \"devDependencies\": {\n \"@tanstack/react-query\": \"^5.90.20\",\n \"@types/react\": \"^19.2.13\",\n \"@types/react-dom\": \"^19.2.3\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\"\n },\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n}\n","import packageJson from '../package.json';\n\n/**\n * Current SDK version from package.json\n */\nexport const SDK_VERSION = packageJson.version;\n","/**\n * Utility functions for addon development\n */\n\nimport type { AddonManifest, AddonValidationResult } from './manifest';\nimport { HOST_DEPENDENCIES } from './host-dependencies';\nimport { SDK_VERSION } from './version';\n\n/**\n * Validates an addon manifest\n */\nexport function validateManifest(manifest: AddonManifest): AddonValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Required fields\n if (!manifest.id) {\n errors.push('Addon ID is required');\n } else if (!/^[a-z0-9-]+$/.test(manifest.id)) {\n errors.push('Addon ID must contain only lowercase letters, numbers, and hyphens');\n }\n\n if (!manifest.name) {\n errors.push('Addon name is required');\n }\n\n if (!manifest.version) {\n errors.push('Addon version is required');\n } else if (!/^\\d+\\.\\d+\\.\\d+/.test(manifest.version)) {\n warnings.push('Version should follow semantic versioning (e.g., 1.0.0)');\n }\n\n // Optional but recommended fields\n if (!manifest.description) {\n warnings.push('Description is recommended for better discoverability');\n }\n\n if (!manifest.author) {\n warnings.push('Author information is recommended');\n }\n\n if (!manifest.main) {\n warnings.push('Main entry point not specified, defaulting to \"addon.js\"');\n }\n\n if (manifest.hostDependencies) {\n Object.entries(manifest.hostDependencies).forEach(([name, version]) => {\n if (!version) {\n errors.push(`Host dependency ${name}: version range is required`);\n }\n if (!Object.prototype.hasOwnProperty.call(HOST_DEPENDENCIES, name)) {\n warnings.push(\n `Host dependency ${name} is not provided by Wealthfolio and should be bundled`,\n );\n }\n });\n }\n\n // Validate permissions if present\n if (manifest.permissions) {\n manifest.permissions.forEach((permission, index) => {\n if (!permission.category) {\n errors.push(`Permission ${index}: category is required`);\n }\n if (!permission.functions || permission.functions.length === 0) {\n errors.push(`Permission ${index}: at least one function must be specified`);\n }\n if (!permission.purpose) {\n warnings.push(`Permission ${index}: purpose explanation is recommended`);\n }\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Checks if an addon version is compatible with the current SDK\n */\nexport function isCompatibleVersion(\n addonSdkVersion?: string,\n currentSdkVersion = SDK_VERSION,\n): boolean {\n if (!addonSdkVersion) return true; // Assume compatible if not specified\n\n const [addonMajor, addonMinor] = addonSdkVersion.split('.').map(Number);\n const [currentMajor, currentMinor] = currentSdkVersion.split('.').map(Number);\n\n // Same major version, and addon minor version <= current minor version\n return addonMajor === currentMajor && addonMinor <= currentMinor;\n}\n\n/**\n * Formats addon size in human-readable format\n */\nexport function formatAddonSize(bytes: number): string {\n const sizes = ['B', 'KB', 'MB', 'GB'];\n if (bytes === 0) return '0 B';\n\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const size = bytes / Math.pow(1024, i);\n\n return `${size.toFixed(i === 0 ? 0 : 1)} ${sizes[i]}`;\n}\n\n/**\n * Generates a unique addon ID from a name\n */\nexport function generateAddonId(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '') // Remove special characters\n .replace(/\\s+/g, '-') // Replace spaces with hyphens\n .replace(/-+/g, '-') // Replace multiple hyphens with single\n .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens\n}\n\n/**\n * Type guard to check if an object is a valid addon manifest\n */\nexport function isAddonManifest(obj: unknown): obj is AddonManifest {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n typeof (obj as Record<string, unknown>).id === 'string' &&\n typeof (obj as Record<string, unknown>).name === 'string' &&\n typeof (obj as Record<string, unknown>).version === 'string'\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/version.ts","../src/utils.ts"],"sourcesContent":["{\n \"name\": \"@wealthfolio/addon-sdk\",\n \"version\": \"3.8.0\",\n \"type\": \"module\",\n \"description\": \"TypeScript SDK for building Wealthfolio addons with enhanced functionality and type safety\",\n \"main\": \"dist/index.js\",\n \"types\": \"dist/src/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/src/index.d.ts\"\n },\n \"./types\": {\n \"import\": \"./dist/types.js\",\n \"types\": \"./dist/src/types.d.ts\"\n },\n \"./host-api\": {\n \"import\": \"./dist/host-api.js\",\n \"types\": \"./dist/src/host-api.d.ts\"\n },\n \"./host-dependencies\": {\n \"import\": \"./dist/host-dependencies.js\",\n \"types\": \"./dist/src/host-dependencies.d.ts\"\n },\n \"./manifest\": {\n \"import\": \"./dist/manifest.js\",\n \"types\": \"./dist/src/manifest.d.ts\"\n },\n \"./permissions\": {\n \"import\": \"./dist/permissions.js\",\n \"types\": \"./dist/src/permissions.d.ts\"\n },\n \"./query-keys\": {\n \"import\": \"./dist/query-keys.js\",\n \"types\": \"./dist/src/query-keys.d.ts\"\n },\n \"./utils\": {\n \"import\": \"./dist/utils.js\",\n \"types\": \"./dist/src/utils.d.ts\"\n },\n \"./goal-progress\": {\n \"import\": \"./dist/goal-progress.js\",\n \"types\": \"./dist/src/goal-progress.d.ts\"\n }\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"CHANGELOG.md\"\n ],\n \"keywords\": [\n \"wealthfolio\",\n \"addon\",\n \"plugin\",\n \"sdk\",\n \"typescript\",\n \"financial\",\n \"portfolio\"\n ],\n \"author\": \"Wealthfolio Team\",\n \"license\": \"MIT\",\n \"homepage\": \"https://wealthfolio.app/addons\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/wealthfolio/wealthfolio.git\",\n \"directory\": \"packages/addon-sdk\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/wealthfolio/wealthfolio/issues\"\n },\n \"scripts\": {\n \"build\": \"tsup && pnpm run build:types\",\n \"dev\": \"tsup --watch\",\n \"clean\": \"rm -rf dist\",\n \"lint\": \"eslint .\",\n \"lint:fix\": \"eslint . --fix\",\n \"lint:quiet\": \"eslint . --quiet\",\n \"format\": \"prettier --write .\",\n \"format:check\": \"prettier --check .\",\n \"type-check\": \"tsc --noEmit\",\n \"build:types\": \"tsc -p tsconfig.json\",\n \"prepack\": \"npm run build\"\n },\n \"peerDependencies\": {\n \"react\": \"^19.2.4\",\n \"react-dom\": \"^19.2.4\"\n },\n \"devDependencies\": {\n \"@tanstack/react-query\": \"^5.90.20\",\n \"@types/react\": \"^19.2.13\",\n \"@types/react-dom\": \"^19.2.3\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\"\n },\n \"engines\": {\n \"node\": \">=20.0.0\"\n }\n}\n","import packageJson from '../package.json';\n\n/**\n * Current SDK version from package.json\n */\nexport const SDK_VERSION = packageJson.version;\n","/**\n * Utility functions for addon development\n */\n\nimport type { AddonManifest, AddonValidationResult } from './manifest';\nimport { HOST_DEPENDENCIES } from './host-dependencies';\nimport { SDK_VERSION } from './version';\n\n/**\n * Validates an addon manifest\n */\nexport function validateManifest(manifest: AddonManifest): AddonValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Required fields\n if (!manifest.id) {\n errors.push('Addon ID is required');\n } else if (!/^[a-z0-9-]+$/.test(manifest.id)) {\n errors.push('Addon ID must contain only lowercase letters, numbers, and hyphens');\n }\n\n if (!manifest.name) {\n errors.push('Addon name is required');\n }\n\n if (!manifest.version) {\n errors.push('Addon version is required');\n } else if (!/^\\d+\\.\\d+\\.\\d+/.test(manifest.version)) {\n warnings.push('Version should follow semantic versioning (e.g., 1.0.0)');\n }\n\n // Optional but recommended fields\n if (!manifest.description) {\n warnings.push('Description is recommended for better discoverability');\n }\n\n if (!manifest.author) {\n warnings.push('Author information is recommended');\n }\n\n if (!manifest.main) {\n warnings.push('Main entry point not specified, defaulting to \"addon.js\"');\n }\n\n if (manifest.hostDependencies) {\n Object.entries(manifest.hostDependencies).forEach(([name, version]) => {\n if (!version) {\n errors.push(`Host dependency ${name}: version range is required`);\n }\n if (!Object.prototype.hasOwnProperty.call(HOST_DEPENDENCIES, name)) {\n warnings.push(\n `Host dependency ${name} is not provided by Wealthfolio and should be bundled`,\n );\n }\n });\n }\n\n // Validate permissions if present\n if (manifest.permissions) {\n manifest.permissions.forEach((permission, index) => {\n if (!permission.category) {\n errors.push(`Permission ${index}: category is required`);\n }\n if (!permission.functions || permission.functions.length === 0) {\n errors.push(`Permission ${index}: at least one function must be specified`);\n }\n if (!permission.purpose) {\n warnings.push(`Permission ${index}: purpose explanation is recommended`);\n }\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Checks if an addon version is compatible with the current SDK\n */\nexport function isCompatibleVersion(\n addonSdkVersion?: string,\n currentSdkVersion = SDK_VERSION,\n): boolean {\n if (!addonSdkVersion) return true; // Assume compatible if not specified\n\n const [addonMajor, addonMinor] = addonSdkVersion.split('.').map(Number);\n const [currentMajor, currentMinor] = currentSdkVersion.split('.').map(Number);\n\n // Same major version, and addon minor version <= current minor version\n return addonMajor === currentMajor && addonMinor <= currentMinor;\n}\n\n/**\n * Formats addon size in human-readable format\n */\nexport function formatAddonSize(bytes: number): string {\n const sizes = ['B', 'KB', 'MB', 'GB'];\n if (bytes === 0) return '0 B';\n\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const size = bytes / Math.pow(1024, i);\n\n return `${size.toFixed(i === 0 ? 0 : 1)} ${sizes[i]}`;\n}\n\n/**\n * Generates a unique addon ID from a name\n */\nexport function generateAddonId(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '') // Remove special characters\n .replace(/\\s+/g, '-') // Replace spaces with hyphens\n .replace(/-+/g, '-') // Replace multiple hyphens with single\n .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens\n}\n\n/**\n * Type guard to check if an object is a valid addon manifest\n */\nexport function isAddonManifest(obj: unknown): obj is AddonManifest {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n typeof (obj as Record<string, unknown>).id === 'string' &&\n typeof (obj as Record<string, unknown>).name === 'string' &&\n typeof (obj as Record<string, unknown>).version === 'string'\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -71,9 +71,23 @@ var PERMISSION_CATEGORIES = [
|
|
|
71
71
|
id: "currency",
|
|
72
72
|
name: "Exchange Rates",
|
|
73
73
|
description: "Access to currency exchange rates and conversion data",
|
|
74
|
-
functions: ["getAll", "update", "add"],
|
|
74
|
+
functions: ["getAll", "update", "add", "getRatesForDates"],
|
|
75
75
|
riskLevel: "low"
|
|
76
76
|
},
|
|
77
|
+
{
|
|
78
|
+
id: "spending",
|
|
79
|
+
name: "Spend Categorization",
|
|
80
|
+
description: "View spend categories and manage categorization rules that auto-tag transactions",
|
|
81
|
+
functions: [
|
|
82
|
+
"isEnabled",
|
|
83
|
+
"getCategories",
|
|
84
|
+
"getRules",
|
|
85
|
+
"saveRule",
|
|
86
|
+
"deleteRule",
|
|
87
|
+
"rerunRules"
|
|
88
|
+
],
|
|
89
|
+
riskLevel: "medium"
|
|
90
|
+
},
|
|
77
91
|
{
|
|
78
92
|
id: "financial-planning",
|
|
79
93
|
name: "Financial Planning",
|
|
@@ -239,4 +253,4 @@ export {
|
|
|
239
253
|
addDetectedFunction,
|
|
240
254
|
markFunctionAsDeclared
|
|
241
255
|
};
|
|
242
|
-
//# sourceMappingURL=chunk-
|
|
256
|
+
//# sourceMappingURL=chunk-3YZER4XO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/permissions.ts"],"sourcesContent":["/**\n * Permission system types and constants for Wealthfolio addons\n */\n\n/**\n * Security risk levels for addon operations\n */\nexport type RiskLevel = 'low' | 'medium' | 'high';\n\n/**\n * Function permission details with declaration and detection tracking\n */\nexport interface FunctionPermission {\n /** Function name */\n name: string;\n /** Whether this function was declared by the developer in manifest */\n isDeclared: boolean;\n /** Whether this function was detected by static analysis during installation */\n isDetected: boolean;\n /** ISO timestamp when this function was detected (if isDetected is true) */\n detectedAt?: string;\n}\n\n/**\n * Permission requirement for specific addon functionality\n */\nexport interface Permission {\n /** Permission category identifier */\n category: string;\n /** List of API functions this permission grants access to with their declaration/detection status */\n functions: FunctionPermission[];\n /** Human-readable explanation of why this permission is needed */\n purpose: string;\n}\n\n/**\n * Permission category definition\n */\nexport interface PermissionCategory {\n /** Unique category identifier */\n id: string;\n /** Display name for the category */\n name: string;\n /** Detailed description of what this category covers */\n description: string;\n /** List of API functions in this category */\n functions: string[];\n /** Security risk level for this category */\n riskLevel: RiskLevel;\n}\n\n/**\n * Predefined permission categories with their associated functions and risk levels\n */\nexport const PERMISSION_CATEGORIES: PermissionCategory[] = [\n {\n id: 'accounts',\n name: 'Account Management',\n description: 'Access to account information and settings',\n functions: ['getAll', 'create'],\n riskLevel: 'high',\n },\n {\n id: 'portfolio',\n name: 'Portfolio Data',\n description: 'Access to holdings, portfolio performance, and account valuations',\n functions: [\n 'getHoldings',\n 'getHolding',\n 'update',\n 'recalculate',\n 'getIncomeSummary',\n 'getHistoricalValuations',\n 'getLatestValuations',\n ],\n riskLevel: 'high',\n },\n {\n id: 'activities',\n name: 'Transaction History',\n description: 'Access to transaction records and activity management',\n functions: [\n 'getAll',\n 'search',\n 'create',\n 'update',\n 'saveMany',\n 'import',\n 'checkImport',\n 'getImportMapping',\n 'saveImportMapping',\n ],\n riskLevel: 'high',\n },\n {\n id: 'market-data',\n name: 'Market Data',\n description: 'Access to market prices, quotes, and financial data',\n functions: ['searchTicker', 'syncHistory', 'sync', 'getProviders', 'fetchDividends'],\n riskLevel: 'low',\n },\n {\n id: 'assets',\n name: 'Asset Management',\n description: 'Access to asset profiles and data sources',\n functions: ['getProfile', 'updateProfile', 'updateQuoteMode'],\n riskLevel: 'medium',\n },\n {\n id: 'quotes',\n name: 'Quote Management',\n description: 'Access to price quotes and historical data',\n functions: ['update', 'getHistory'],\n riskLevel: 'low',\n },\n {\n id: 'performance',\n name: 'Performance Analytics',\n description: 'Access to performance calculations and metrics',\n functions: ['calculateHistory', 'calculateSummary', 'calculateAccountsSimple'],\n riskLevel: 'medium',\n },\n {\n id: 'currency',\n name: 'Exchange Rates',\n description: 'Access to currency exchange rates and conversion data',\n functions: ['getAll', 'update', 'add', 'getRatesForDates'],\n riskLevel: 'low',\n },\n {\n id: 'spending',\n name: 'Spend Categorization',\n description:\n 'View spend categories and manage categorization rules that auto-tag transactions',\n functions: [\n 'isEnabled',\n 'getCategories',\n 'getRules',\n 'saveRule',\n 'deleteRule',\n 'rerunRules',\n ],\n riskLevel: 'medium',\n },\n {\n id: 'financial-planning',\n name: 'Financial Planning',\n description: 'Access to financial goals and allocations',\n functions: [\n 'getAll',\n 'create',\n 'update',\n 'getFunding',\n 'saveFunding',\n 'updateAllocations',\n 'getAllocations',\n ],\n riskLevel: 'medium',\n },\n {\n id: 'contribution-limits',\n name: 'Contribution Limits',\n description: 'Access to contribution limits and deposit calculations',\n functions: ['getAll', 'create', 'update', 'calculateDeposits'],\n riskLevel: 'medium',\n },\n {\n id: 'settings',\n name: 'Application Settings',\n description: 'Access to application settings and configuration',\n functions: ['get', 'update', 'backupDatabase'],\n riskLevel: 'medium',\n },\n {\n id: 'files',\n name: 'File Operations',\n description: 'Access to file dialogs and file system operations',\n functions: ['openCsvDialog', 'openSaveDialog'],\n riskLevel: 'medium',\n },\n {\n id: 'secrets',\n name: 'Secrets Management',\n description: 'Access to secure storage for addon secrets',\n functions: ['set', 'get', 'use', 'delete'],\n riskLevel: 'high',\n },\n {\n id: 'snapshots',\n name: 'Snapshot Management',\n description: 'Access to holdings snapshots for accounts with holdings tracking mode',\n functions: [\n 'getAll',\n 'getByDate',\n 'save',\n 'checkImport',\n 'importSnapshots',\n 'delete',\n ],\n riskLevel: 'high',\n },\n {\n id: 'events',\n name: 'Event Listeners',\n description: 'Access to application events and notifications',\n functions: [\n 'onDropHover',\n 'onDrop',\n 'onDropCancelled',\n 'onUpdateStart',\n 'onUpdateComplete',\n 'onUpdateError',\n 'onSyncStart',\n 'onSyncComplete',\n ],\n riskLevel: 'low',\n },\n {\n id: 'network',\n name: 'Network Access',\n description:\n 'Access to declared external HTTPS hosts through the host network broker',\n functions: ['request'],\n riskLevel: 'high',\n },\n];\n\n/**\n * Baseline capabilities that every addon may use without declaring a permission\n * or obtaining user consent. These are treated as an ignore-filter: legacy manifests\n * that still declare them keep parsing, but they are never surfaced in consent UI,\n * never guarded at runtime, and never count as a permission escalation on update.\n */\nexport const BASELINE_PERMISSION_CATEGORIES = [\n 'ui',\n 'query',\n 'toast',\n 'logger',\n 'storage',\n] as const;\n\n/**\n * Check whether a permission category is an implicit baseline capability.\n */\nexport function isBaselineCategory(id: string): boolean {\n return (BASELINE_PERMISSION_CATEGORIES as readonly string[]).includes(id);\n}\n\n/**\n * Helper functions for permission management\n */\n\n/**\n * Create a FunctionPermission object\n */\nexport function createFunctionPermission(\n name: string,\n isDeclared = false,\n isDetected = false,\n detectedAt?: string,\n): FunctionPermission {\n return {\n name,\n isDeclared,\n isDetected,\n detectedAt: isDetected ? detectedAt || new Date().toISOString() : undefined,\n };\n}\n\n/**\n * Get permission category by ID\n */\nexport function getPermissionCategory(id: string): PermissionCategory | undefined {\n return PERMISSION_CATEGORIES.find((category) => category.id === id);\n}\n\n/**\n * Get permission categories by risk level\n */\nexport function getPermissionCategoriesByRisk(\n riskLevel: RiskLevel,\n): PermissionCategory[] {\n return PERMISSION_CATEGORIES.filter((category) => category.riskLevel === riskLevel);\n}\n\n/**\n * Get the risk level for a specific function\n */\nexport function getFunctionRiskLevel(functionName: string): RiskLevel | undefined {\n const category = PERMISSION_CATEGORIES.find((cat) =>\n cat.functions.includes(functionName),\n );\n return category?.riskLevel;\n}\n\n/**\n * Check if a function requires a specific permission category\n */\nexport function isPermissionRequired(functionName: string, categoryId: string): boolean {\n const category = getPermissionCategory(categoryId);\n return category ? category.functions.includes(functionName) : false;\n}\n\n/**\n * Get all declared functions from a permission\n */\nexport function getDeclaredFunctions(permission: Permission): string[] {\n return permission.functions.filter((func) => func.isDeclared).map((func) => func.name);\n}\n\n/**\n * Get all detected functions from a permission\n */\nexport function getDetectedFunctions(permission: Permission): string[] {\n return permission.functions.filter((func) => func.isDetected).map((func) => func.name);\n}\n\n/**\n * Get functions that were detected but not declared (potential security concern)\n */\nexport function getUndeclaredDetectedFunctions(permission: Permission): string[] {\n return permission.functions\n .filter((func) => func.isDetected && !func.isDeclared)\n .map((func) => func.name);\n}\n\n/**\n * Check if a permission has any undeclared detected functions\n */\nexport function hasUndeclaredDetectedFunctions(permission: Permission): boolean {\n return permission.functions.some((func) => func.isDetected && !func.isDeclared);\n}\n\n/**\n * Add a detected function to a permission\n */\nexport function addDetectedFunction(\n permission: Permission,\n functionName: string,\n detectedAt?: string,\n): Permission {\n const existingFunc = permission.functions.find((f) => f.name === functionName);\n\n if (existingFunc) {\n // Update existing function to mark as detected\n existingFunc.isDetected = true;\n existingFunc.detectedAt = detectedAt || new Date().toISOString();\n } else {\n // Add new detected function\n permission.functions.push(\n createFunctionPermission(functionName, false, true, detectedAt),\n );\n }\n\n return permission;\n}\n\n/**\n * Mark a function as declared in a permission\n */\nexport function markFunctionAsDeclared(\n permission: Permission,\n functionName: string,\n): Permission {\n const existingFunc = permission.functions.find((f) => f.name === functionName);\n\n if (existingFunc) {\n existingFunc.isDeclared = true;\n } else {\n // Add new declared function\n permission.functions.push(createFunctionPermission(functionName, true, false));\n }\n\n return permission;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/manifest.ts"],"sourcesContent":["/**\n * Addon manifest and metadata types\n */\n\nimport type { AddonIconName } from './icons';\nimport type { Permission } from './permissions';\n\nexport interface AddonNetworkAccess {\n allowedHosts: string[];\n approvedHosts?: string[];\n}\n\nexport type AddonHostDependencies = Record<string, string>;\n\n/**\n * A durable addon page declared via `contributes.routes`. The host ingests\n * these at boot without executing addon code, so the route exists before (and\n * independently of) the addon's runtime activation — it is the lazy-activation\n * surface.\n */\nexport interface AddonContributedRoute {\n /** Stable route id. MUST equal the route id the addon registers at runtime. */\n id: string;\n /**\n * Optional path relative to the host-owned `/addons/<addon-id>` mount.\n * Omit for the addon root; use a suffix such as `reports/:year` for a\n * nested page. Absolute paths, traversal, query strings, and fragments are\n * rejected by the host.\n */\n path?: string;\n}\n\n/**\n * A placement in a host slot (e.g. `\"sidebar\"`) declared via\n * `contributes.links`, pointing at a route declared in `contributes.routes`\n * of the same addon.\n */\nexport interface AddonContributedLink {\n /** Optional stable link id; defaults to the referenced route id */\n id?: string;\n /** Id of a route declared in this addon's `contributes.routes` */\n route: string;\n /** Human-readable label shown in the host slot */\n label: string;\n /** Optional host-supported icon name (see {@link AddonIconName}) */\n icon?: AddonIconName;\n /** Optional sort order within the slot */\n order?: number;\n}\n\n/**\n * Declarative contributions an addon makes to the host: durable routes plus\n * links placed in host slots, keyed by slot id. Only the `\"sidebar\"` slot is\n * consumed today; unknown slot keys are preserved for future host surfaces.\n */\nexport interface AddonContributes {\n /** Durable addon pages, host-renderable before the addon boots */\n routes?: AddonContributedRoute[];\n /** Slot placements pointing at declared routes, keyed by slot id */\n links?: Record<string, AddonContributedLink[]>;\n}\n\n/**\n * Unified addon manifest structure that handles both development and runtime scenarios\n * This represents both what developers write in their manifest.json and installed addon metadata\n */\nexport interface AddonManifest {\n // Core manifest fields (always present)\n /** Unique addon identifier (lowercase, no spaces, hyphens allowed) */\n id: string;\n /** Human-readable addon name */\n name: string;\n /** Semantic version (e.g., \"1.0.0\") */\n version: string;\n /** Brief description of the addon's functionality */\n description?: string;\n /** Author name or organization */\n author?: string;\n /** Compatible SDK version */\n sdkVersion?: string;\n /** Main entry point file (relative to addon root) */\n main?: string;\n /** Whether the addon is enabled by default */\n enabled?: boolean;\n /** Permission declarations for security review */\n permissions?: Permission[];\n /** Addon homepage or documentation URL */\n homepage?: string;\n /** Support or issues URL */\n repository?: string;\n /** License identifier (e.g., \"MIT\", \"Apache-2.0\") */\n license?: string;\n /** Minimum Wealthfolio version required */\n minWealthfolioVersion?: string;\n /** Keywords for discoverability */\n keywords?: string[];\n /** Addon icon value supported by the consuming host surface */\n icon?: string;\n /** Network hosts this addon may reach through the host broker */\n network?: AddonNetworkAccess;\n /** Host-provided packages this addon imports instead of bundling */\n hostDependencies?: AddonHostDependencies;\n /** Declarative contributions to the host (routes + slot links) */\n contributes?: AddonContributes;\n\n // Runtime fields (only present after installation)\n /** Installation timestamp in ISO format */\n installedAt?: string;\n /** Last update timestamp */\n updatedAt?: string;\n /** Installation source */\n source?: 'local' | 'store' | 'sideload';\n /** File size in bytes */\n size?: number;\n}\n\n/**\n * Type guard to check if a manifest has been installed (has runtime fields)\n */\nexport function isInstalledManifest(\n manifest: AddonManifest,\n): manifest is Required<Pick<AddonManifest, 'main' | 'enabled' | 'installedAt'>> &\n AddonManifest {\n return !!(\n manifest.installedAt &&\n manifest.main !== undefined &&\n manifest.enabled !== undefined\n );\n}\n\n/**\n * Helper type for development manifests (without runtime fields)\n */\nexport type DevelopmentManifest = Omit<\n AddonManifest,\n 'installedAt' | 'updatedAt' | 'source' | 'size'\n>;\n\n/**\n * Helper type for installed manifests (with runtime fields)\n */\nexport type InstalledManifest = Required<\n Pick<AddonManifest, 'main' | 'enabled' | 'installedAt'>\n> &\n AddonManifest;\n\n/**\n * Addon file information\n */\nexport interface AddonFile {\n /** File name */\n name: string;\n /** File content */\n content: string;\n /** Whether this is the main entry point */\n is_main: boolean;\n /** File size in bytes */\n size?: number;\n}\n\n/** A packaged file available through {@link AddonContext.assets}. */\nexport interface AddonAsset {\n /** Logical package path, such as `assets/logo.png`. */\n path: string;\n /** Browser-compatible MIME type inferred by the host. */\n mimeType: string;\n /** File size in bytes. */\n size: number;\n}\n\n/**\n * Extracted addon package\n */\nexport interface ExtractedAddon {\n /** Addon metadata from manifest */\n metadata: AddonManifest;\n /** List of files in the addon package */\n files: AddonFile[];\n /**\n * Packaged static files under `assets/**` and `dist/assets/**` (metadata only).\n * Wealthfolio 3.7 hosts always return an array; optionality preserves source\n * compatibility with values constructed against earlier SDK versions.\n */\n assets?: AddonAsset[];\n}\n\n/**\n * Installed addon information\n */\nexport interface InstalledAddon {\n /** Addon metadata */\n metadata: AddonManifest;\n /** Installation path */\n path?: string;\n /** Whether the addon is currently active */\n active?: boolean;\n}\n\n/**\n * Addon installation result\n */\nexport interface AddonInstallResult {\n /** Whether installation was successful */\n success: boolean;\n /** Error message if installation failed */\n error?: string;\n /** Installed addon metadata */\n addon?: AddonManifest;\n}\n\n/**\n * Addon validation result\n */\nexport interface AddonValidationResult {\n /** Whether the addon is valid */\n valid: boolean;\n /** List of validation errors */\n errors: string[];\n /** List of validation warnings */\n warnings: string[];\n}\n\n/**\n * Addon update information\n */\nexport interface AddonUpdateInfo {\n /** Current installed version */\n currentVersion: string;\n /** Latest available version */\n latestVersion: string;\n /** Whether an update is available */\n updateAvailable: boolean;\n /** Download URL for the update */\n downloadUrl?: string;\n /** Optional SHA-256 digest for the update package bytes */\n sha256?: string;\n /** Release notes for the latest version */\n releaseNotes?: string;\n /** Release date of the latest version */\n releaseDate?: string;\n /** Changelog URL */\n changelogUrl?: string;\n /** Whether this is a critical security update */\n isCritical?: boolean;\n /** Breaking changes in this update */\n hasBreakingChanges?: boolean;\n /** Minimum Wealthfolio version required for this update */\n minWealthfolioVersion?: string;\n}\n\n/**\n * Addon update check result\n */\nexport interface AddonUpdateCheckResult {\n /** Addon ID */\n addonId: string;\n /** Update information */\n updateInfo: AddonUpdateInfo;\n /** Any errors during update check */\n error?: string;\n}\n\n/**\n * Addon store listing\n */\nexport interface AddonStoreListing {\n /** Addon metadata */\n metadata: AddonManifest;\n /** Download URL */\n downloadUrl: string;\n /** Optional SHA-256 digest for the package bytes */\n sha256?: string;\n /** Number of downloads */\n downloads?: number;\n /** Average rating */\n rating?: number;\n /** Number of reviews */\n reviewCount?: number;\n /** Whether it's verified by Wealthfolio team */\n verified?: boolean;\n /** Last update date */\n lastUpdated?: string;\n /** Screenshots or images */\n images?: string[];\n /** Release notes for the latest version */\n releaseNotes?: string;\n /** Changelog URL */\n changelogUrl?: string;\n}\n"],"mappings":";AAuHO,SAAS,oBACd,UAEc;AACd,SAAO,CAAC,EACN,SAAS,eACT,SAAS,SAAS,UAClB,SAAS,YAAY;AAEzB;","names":[]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/host-dependencies.ts
|
|
2
2
|
var HOST_DEPENDENCIES = {
|
|
3
3
|
"@tanstack/react-query": "^5.90.0",
|
|
4
|
-
"@wealthfolio/addon-sdk": "^3.
|
|
5
|
-
"@wealthfolio/ui": "^3.
|
|
4
|
+
"@wealthfolio/addon-sdk": "^3.8.0",
|
|
5
|
+
"@wealthfolio/ui": "^3.8.0",
|
|
6
6
|
"date-fns": "^4.1.0",
|
|
7
7
|
"lucide-react": "^0.561.0",
|
|
8
8
|
react: "^19.2.0",
|
|
@@ -13,4 +13,4 @@ var HOST_DEPENDENCIES = {
|
|
|
13
13
|
export {
|
|
14
14
|
HOST_DEPENDENCIES
|
|
15
15
|
};
|
|
16
|
-
//# sourceMappingURL=chunk-
|
|
16
|
+
//# sourceMappingURL=chunk-DQNFXUZ7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/host-dependencies.ts"],"sourcesContent":["export const HOST_DEPENDENCIES = {\n '@tanstack/react-query': '^5.90.0',\n '@wealthfolio/addon-sdk': '^3.
|
|
1
|
+
{"version":3,"sources":["../src/host-dependencies.ts"],"sourcesContent":["export const HOST_DEPENDENCIES = {\n '@tanstack/react-query': '^5.90.0',\n '@wealthfolio/addon-sdk': '^3.8.0',\n '@wealthfolio/ui': '^3.8.0',\n 'date-fns': '^4.1.0',\n 'lucide-react': '^0.561.0',\n react: '^19.2.0',\n 'react-dom': '^19.2.0',\n recharts: '^3.7.0',\n} as const;\n"],"mappings":";AAAO,IAAM,oBAAoB;AAAA,EAC/B,yBAAyB;AAAA,EACzB,0BAA0B;AAAA,EAC1B,mBAAmB;AAAA,EACnB,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,OAAO;AAAA,EACP,aAAa;AAAA,EACb,UAAU;AACZ;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -5,16 +5,16 @@ import {
|
|
|
5
5
|
isAddonManifest,
|
|
6
6
|
isCompatibleVersion,
|
|
7
7
|
validateManifest
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2IM7BFJX.js";
|
|
9
9
|
import {
|
|
10
10
|
calculateGoalProgress
|
|
11
11
|
} from "./chunk-465MB7HT.js";
|
|
12
12
|
import {
|
|
13
13
|
HOST_DEPENDENCIES
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-DQNFXUZ7.js";
|
|
15
15
|
import {
|
|
16
16
|
isInstalledManifest
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-5727GMVD.js";
|
|
18
18
|
import {
|
|
19
19
|
BASELINE_PERMISSION_CATEGORIES,
|
|
20
20
|
PERMISSION_CATEGORIES,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
getPermissionCategory,
|
|
24
24
|
isBaselineCategory,
|
|
25
25
|
isPermissionRequired
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-3YZER4XO.js";
|
|
27
27
|
import {
|
|
28
28
|
QueryKeys
|
|
29
29
|
} from "./chunk-PYPEFQCY.js";
|
|
@@ -119,6 +119,27 @@ var ADDON_ICON_NAMES = [
|
|
|
119
119
|
"kanban"
|
|
120
120
|
];
|
|
121
121
|
|
|
122
|
+
// src/i18n.ts
|
|
123
|
+
function registerTranslations(resources) {
|
|
124
|
+
const runtime = globalThis.__wealthfolioAddonI18n;
|
|
125
|
+
if (!runtime) {
|
|
126
|
+
console.warn(
|
|
127
|
+
"[wealthfolio-sdk] registerTranslations is only available inside the Wealthfolio addon sandbox; ignoring call."
|
|
128
|
+
);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
runtime.registerTranslations(resources);
|
|
132
|
+
}
|
|
133
|
+
function useAddonTranslation() {
|
|
134
|
+
const runtime = globalThis.__wealthfolioAddonI18n;
|
|
135
|
+
if (!runtime) {
|
|
136
|
+
throw new Error(
|
|
137
|
+
"useAddonTranslation is only available inside the Wealthfolio addon sandbox"
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
return runtime.useAddonTranslation();
|
|
141
|
+
}
|
|
142
|
+
|
|
122
143
|
// src/index.ts
|
|
123
144
|
var ReactVersion = "19.2.4";
|
|
124
145
|
export {
|
|
@@ -140,6 +161,8 @@ export {
|
|
|
140
161
|
isCompatibleVersion,
|
|
141
162
|
isInstalledManifest,
|
|
142
163
|
isPermissionRequired,
|
|
164
|
+
registerTranslations,
|
|
165
|
+
useAddonTranslation,
|
|
143
166
|
validateManifest
|
|
144
167
|
};
|
|
145
168
|
/**
|
|
@@ -148,7 +171,7 @@ export {
|
|
|
148
171
|
* TypeScript SDK for building Wealthfolio addons with enhanced functionality,
|
|
149
172
|
* type safety, and comprehensive permission management.
|
|
150
173
|
*
|
|
151
|
-
* @version
|
|
174
|
+
* @version 3.8.0
|
|
152
175
|
* @author Wealthfolio Team
|
|
153
176
|
* @license MIT
|
|
154
177
|
*/
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/icons.ts","../src/index.ts"],"sourcesContent":["/**\n * Icon names an addon may use for its sidebar item.\n *\n * The sidebar is host chrome, so the host draws the icon from this fixed set of\n * duotone Phosphor icons — an addon can't ship its own sidebar icon across the\n * sandbox boundary. (Inside your own route/page you can render any icon you\n * like.) Matching at runtime is case- and separator-insensitive (`\"ChartLine\"`,\n * `\"chart-line\"`, and `\"chartline\"` all resolve the same), but this canonical\n * kebab-case list is what the type checker accepts. Unknown names render a\n * neutral fallback icon rather than erroring.\n */\nexport const ADDON_ICON_NAMES = [\n // Money\n 'wallet',\n 'coins',\n 'dollar',\n 'dollar-circle',\n 'bank',\n 'credit-card',\n 'piggy-bank',\n 'receipt',\n 'invoice',\n 'hand-coins',\n 'hand-deposit',\n 'vault',\n 'chart-line-up',\n 'chart-line',\n 'trend-up',\n 'trend-down',\n 'percent',\n 'scales',\n 'calculator',\n // Charts & analytics\n 'chart-bar',\n 'chart-pie',\n 'chart-pie-slice',\n 'chart-donut',\n 'gauge',\n 'target',\n 'presentation',\n // Assets\n 'house',\n 'buildings',\n 'car',\n 'airplane',\n 'bicycle',\n 'diamond',\n 'bitcoin',\n 'storefront',\n 'briefcase',\n 'package',\n 'cube',\n // General\n 'star',\n 'heart',\n 'gift',\n 'trophy',\n 'medal',\n 'lightning',\n 'sparkle',\n 'bell',\n 'tag',\n 'bookmark',\n 'flag',\n 'fire',\n 'rocket',\n 'lightbulb',\n 'graduation-cap',\n 'barbell',\n 'fork-knife',\n 'coffee',\n 'wine',\n 'shopping-cart',\n 'shopping-bag',\n 'basket',\n // Time & place\n 'calendar',\n 'calendar-dots',\n 'calendar-check',\n 'clock',\n 'hourglass',\n 'globe',\n 'map-pin',\n 'compass',\n // Productivity\n 'folder',\n 'files',\n 'notebook',\n 'clipboard-text',\n 'list-checks',\n 'sliders',\n 'wrench',\n 'toolbox',\n 'puzzle-piece',\n 'plugs-connected',\n 'app-window',\n 'squares-four',\n 'stack',\n 'kanban',\n] as const;\n\n/** Union of every valid addon sidebar icon name. */\nexport type AddonIconName = (typeof ADDON_ICON_NAMES)[number];\n","/**\n * @wealthfolio/addon-sdk\n *\n * TypeScript SDK for building Wealthfolio addons with enhanced functionality,\n * type safety, and comprehensive permission management.\n *\n * @version
|
|
1
|
+
{"version":3,"sources":["../src/icons.ts","../src/i18n.ts","../src/index.ts"],"sourcesContent":["/**\n * Icon names an addon may use for its sidebar item.\n *\n * The sidebar is host chrome, so the host draws the icon from this fixed set of\n * duotone Phosphor icons — an addon can't ship its own sidebar icon across the\n * sandbox boundary. (Inside your own route/page you can render any icon you\n * like.) Matching at runtime is case- and separator-insensitive (`\"ChartLine\"`,\n * `\"chart-line\"`, and `\"chartline\"` all resolve the same), but this canonical\n * kebab-case list is what the type checker accepts. Unknown names render a\n * neutral fallback icon rather than erroring.\n */\nexport const ADDON_ICON_NAMES = [\n // Money\n 'wallet',\n 'coins',\n 'dollar',\n 'dollar-circle',\n 'bank',\n 'credit-card',\n 'piggy-bank',\n 'receipt',\n 'invoice',\n 'hand-coins',\n 'hand-deposit',\n 'vault',\n 'chart-line-up',\n 'chart-line',\n 'trend-up',\n 'trend-down',\n 'percent',\n 'scales',\n 'calculator',\n // Charts & analytics\n 'chart-bar',\n 'chart-pie',\n 'chart-pie-slice',\n 'chart-donut',\n 'gauge',\n 'target',\n 'presentation',\n // Assets\n 'house',\n 'buildings',\n 'car',\n 'airplane',\n 'bicycle',\n 'diamond',\n 'bitcoin',\n 'storefront',\n 'briefcase',\n 'package',\n 'cube',\n // General\n 'star',\n 'heart',\n 'gift',\n 'trophy',\n 'medal',\n 'lightning',\n 'sparkle',\n 'bell',\n 'tag',\n 'bookmark',\n 'flag',\n 'fire',\n 'rocket',\n 'lightbulb',\n 'graduation-cap',\n 'barbell',\n 'fork-knife',\n 'coffee',\n 'wine',\n 'shopping-cart',\n 'shopping-bag',\n 'basket',\n // Time & place\n 'calendar',\n 'calendar-dots',\n 'calendar-check',\n 'clock',\n 'hourglass',\n 'globe',\n 'map-pin',\n 'compass',\n // Productivity\n 'folder',\n 'files',\n 'notebook',\n 'clipboard-text',\n 'list-checks',\n 'sliders',\n 'wrench',\n 'toolbox',\n 'puzzle-piece',\n 'plugs-connected',\n 'app-window',\n 'squares-four',\n 'stack',\n 'kanban',\n] as const;\n\n/** Union of every valid addon sidebar icon name. */\nexport type AddonIconName = (typeof ADDON_ICON_NAMES)[number];\n","/**\n * Addon translation API.\n *\n * The implementation lives in the Wealthfolio addon sandbox, which installs a\n * runtime on `globalThis` before any addon code runs. Addon resources live on\n * a dedicated i18next instance, separate from the one serving the host's `ui`\n * catalog, so addons can never read or overwrite the host's strings, and the\n * language always follows the host setting — addons cannot change it.\n *\n * Outside the sandbox (e.g. unit tests of addon code) `registerTranslations`\n * is a warning no-op and `useAddonTranslation` throws.\n */\n\n/** A nested map of translation keys to strings, i18next resource shape. */\nexport interface AddonTranslationBundle {\n [key: string]: string | AddonTranslationBundle;\n}\n\n/**\n * Translations keyed by language code (`en`, `fr`, `de`, `zh-Hant`, ...).\n * Regional aliases are normalized to the host's canonical language: for\n * example, `fr-CA` becomes `fr` and Traditional Chinese aliases such as\n * `zh-TW` become `zh-Hant`. Invalid codes are ignored with a warning.\n * Valid languages the host does not support are stored but never resolved.\n */\nexport type AddonTranslationResources = Record<string, AddonTranslationBundle>;\n\nexport interface AddonTranslationApi {\n /**\n * Translate a key from this addon's registered resources. Supports i18next\n * interpolation and plurals. Lookups are locked to this addon's own\n * namespace and the host language: `ns`, `nsSeparator`, `lng`, `lngs`, and\n * `fallbackLng` options are ignored, `:`-prefixed keys are treated\n * literally, and `$t()` nesting inside translation values is disabled.\n */\n t: (key: string, options?: Record<string, unknown>) => string;\n /** Current UI language as a canonical host code (`en`, `fr`, `zh-Hant`, ...). */\n language: string;\n}\n\n/** Implemented and installed by the host sandbox; addons never construct this. */\nexport interface AddonTranslationRuntime {\n registerTranslations: (resources: AddonTranslationResources) => void;\n useAddonTranslation: () => AddonTranslationApi;\n}\n\ndeclare global {\n // Installed by the Wealthfolio addon sandbox before any addon code runs.\n var __wealthfolioAddonI18n: AddonTranslationRuntime | undefined;\n}\n\n/**\n * Register this addon's translations. Call once, in `enable()`, before the\n * first render. Merges per language into the addon's private namespace;\n * missing languages fall back to the addon's `en` bundle.\n */\nexport function registerTranslations(resources: AddonTranslationResources): void {\n const runtime = globalThis.__wealthfolioAddonI18n;\n if (!runtime) {\n console.warn(\n '[wealthfolio-sdk] registerTranslations is only available inside the Wealthfolio addon sandbox; ignoring call.',\n );\n return;\n }\n runtime.registerTranslations(resources);\n}\n\n/**\n * React hook returning a `t` bound to this addon's registered translations.\n * Re-renders when the host language changes.\n */\nexport function useAddonTranslation(): AddonTranslationApi {\n const runtime = globalThis.__wealthfolioAddonI18n;\n if (!runtime) {\n throw new Error(\n 'useAddonTranslation is only available inside the Wealthfolio addon sandbox',\n );\n }\n return runtime.useAddonTranslation();\n}\n","/**\n * @wealthfolio/addon-sdk\n *\n * TypeScript SDK for building Wealthfolio addons with enhanced functionality,\n * type safety, and comprehensive permission management.\n *\n * @version 3.8.0\n * @author Wealthfolio Team\n * @license MIT\n */\n\n// Core types\nexport type {\n AddonContext,\n AddonAssets,\n AddonEnableFunction,\n AddonRouteLocation,\n AddonRouteRenderContext,\n AddonRouteRenderer,\n EventCallback,\n RouteConfig,\n RouterManager,\n SidebarItemConfig,\n SidebarItemHandle,\n SidebarManager,\n UnlistenFn,\n} from './types';\n\n// Host API interface\nexport type {\n ActivitySearchFilters,\n ActivitySort,\n HostAPI,\n NetworkAuth,\n NetworkAPI,\n NetworkRequest,\n NetworkResponse,\n SnapshotsAPI,\n StorageAPI,\n ToastAPI,\n DividendEvent,\n FetchDividendsOptions,\n} from './host-api';\n\n// Query Client and Keys exports\nexport type { QueryClient } from '@tanstack/react-query';\nexport { QueryKeys } from './query-keys';\n\n// Comprehensive data types\nexport type * from './data-types';\n\n// Manifest and metadata types\nexport type {\n AddonFile,\n AddonAsset,\n AddonContributedLink,\n AddonContributedRoute,\n AddonContributes,\n AddonHostDependencies,\n AddonInstallResult,\n AddonManifest,\n AddonStoreListing,\n AddonUpdateCheckResult,\n AddonUpdateInfo,\n AddonValidationResult,\n DevelopmentManifest,\n ExtractedAddon,\n InstalledAddon,\n InstalledManifest,\n} from './manifest';\n\nexport { isInstalledManifest } from './manifest';\n\n// Permission system\nexport type {\n FunctionPermission,\n Permission,\n PermissionCategory,\n RiskLevel,\n} from './permissions';\n\nexport {\n BASELINE_PERMISSION_CATEGORIES,\n getFunctionRiskLevel,\n getPermissionCategoriesByRisk,\n getPermissionCategory,\n isBaselineCategory,\n isPermissionRequired,\n PERMISSION_CATEGORIES,\n} from './permissions';\n\n// Utilities\nexport {\n formatAddonSize,\n generateAddonId,\n isAddonManifest,\n isCompatibleVersion,\n validateManifest,\n} from './utils';\n\n// Goal progress calculation\nexport { calculateGoalProgress } from './goal-progress';\n\n/**\n * React version provided by the Wealthfolio add-on sandbox for host-externalized\n * add-ons.\n */\nexport const ReactVersion = '19.2.4';\n\nexport { HOST_DEPENDENCIES } from './host-dependencies';\n\n// Sidebar icon names (see SidebarItemConfig.icon)\nexport { ADDON_ICON_NAMES } from './icons';\nexport type { AddonIconName } from './icons';\n\n// Addon translations (implemented by the host sandbox)\nexport { registerTranslations, useAddonTranslation } from './i18n';\nexport type {\n AddonTranslationApi,\n AddonTranslationBundle,\n AddonTranslationResources,\n AddonTranslationRuntime,\n} from './i18n';\n\n/**\n * Addons receive their context as a parameter to the enable() function.\n * Each addon gets its own isolated iframe context with scoped host APIs.\n *\n * Example:\n * export default function enable(ctx: AddonContext) {\n * // Use ctx.api.secrets.set/get/delete for secure storage\n * // Use ctx.sidebar.addItem() to add navigation\n * // Use ctx.router.add() with a render callback to register routes\n * }\n */\n\n// Version\nexport { SDK_VERSION } from './version';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWO,IAAM,mBAAmB;AAAA;AAAA,EAE9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC3CO,SAAS,qBAAqB,WAA4C;AAC/E,QAAM,UAAU,WAAW;AAC3B,MAAI,CAAC,SAAS;AACZ,YAAQ;AAAA,MACN;AAAA,IACF;AACA;AAAA,EACF;AACA,UAAQ,qBAAqB,SAAS;AACxC;AAMO,SAAS,sBAA2C;AACzD,QAAM,UAAU,WAAW;AAC3B,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO,QAAQ,oBAAoB;AACrC;;;AC4BO,IAAM,eAAe;","names":[]}
|
package/dist/manifest.js
CHANGED
package/dist/permissions.js
CHANGED
package/dist/src/data-types.d.ts
CHANGED
|
@@ -222,6 +222,8 @@ export interface ActivityCreate {
|
|
|
222
222
|
currency?: string;
|
|
223
223
|
fee?: string | number | null;
|
|
224
224
|
tax?: string | number | null;
|
|
225
|
+
status?: ActivityStatus;
|
|
226
|
+
needsReview?: boolean;
|
|
225
227
|
comment?: string | null;
|
|
226
228
|
fxRate?: string | number | null;
|
|
227
229
|
metadata?: string | Record<string, unknown>;
|
|
@@ -233,6 +235,7 @@ export interface ActivityUpdate {
|
|
|
233
235
|
subtype?: string | null;
|
|
234
236
|
activityDate: string | Date;
|
|
235
237
|
sourceGroupId?: string;
|
|
238
|
+
/** Omit to preserve the current asset; pass an empty object to clear it. */
|
|
236
239
|
asset?: AssetResolutionInput;
|
|
237
240
|
/** @deprecated Use asset. */
|
|
238
241
|
symbol?: AssetResolutionInput;
|
|
@@ -242,6 +245,8 @@ export interface ActivityUpdate {
|
|
|
242
245
|
currency?: string;
|
|
243
246
|
fee?: string | number | null;
|
|
244
247
|
tax?: string | number | null;
|
|
248
|
+
status?: ActivityStatus;
|
|
249
|
+
needsReview?: boolean;
|
|
245
250
|
comment?: string | null;
|
|
246
251
|
fxRate?: string | number | null;
|
|
247
252
|
metadata?: string | Record<string, unknown>;
|
|
@@ -304,6 +309,12 @@ export interface ActivityImport {
|
|
|
304
309
|
lineNumber?: number;
|
|
305
310
|
isDraft: boolean;
|
|
306
311
|
forceImport?: boolean;
|
|
312
|
+
/**
|
|
313
|
+
* Whether a transfer or credit crosses the tracked-account boundary.
|
|
314
|
+
* Controls flow classification; internal transfers may omit
|
|
315
|
+
* `metadata.flow.is_external` because false is the default.
|
|
316
|
+
*/
|
|
317
|
+
isExternal?: boolean;
|
|
307
318
|
comment?: string;
|
|
308
319
|
}
|
|
309
320
|
export interface ImportActivitiesSummary {
|
|
@@ -421,6 +432,71 @@ export interface CategoryWithWeight {
|
|
|
421
432
|
topLevelCategory: CategoryRef;
|
|
422
433
|
weight: number;
|
|
423
434
|
}
|
|
435
|
+
/**
|
|
436
|
+
* The three fixed activity-scope taxonomies a categorization rule can target,
|
|
437
|
+
* in Wealthfolio's own vocabulary (matches the app's quick-categorize picker).
|
|
438
|
+
*/
|
|
439
|
+
export type SpendCategoryKind = 'expense' | 'income' | 'saving';
|
|
440
|
+
/**
|
|
441
|
+
* A selectable spend category, flattened from one of the three activity-scope
|
|
442
|
+
* taxonomies. Used to classify activities (e.g. WITHDRAWALs) via categorization
|
|
443
|
+
* rules, as distinct from the asset-classification taxonomies above.
|
|
444
|
+
*/
|
|
445
|
+
export interface SpendCategory {
|
|
446
|
+
kind: SpendCategoryKind;
|
|
447
|
+
taxonomyId: string;
|
|
448
|
+
categoryId: string;
|
|
449
|
+
/** Machine key, e.g. "groceries" */
|
|
450
|
+
key: string;
|
|
451
|
+
/** Display name, e.g. "Groceries" */
|
|
452
|
+
name: string;
|
|
453
|
+
/** Full breadcrumb path, e.g. "Food & Dining / Groceries" */
|
|
454
|
+
path: string;
|
|
455
|
+
}
|
|
456
|
+
export type CategorizationRuleMatchType = 'contains' | 'starts_with' | 'exact' | 'regex';
|
|
457
|
+
/**
|
|
458
|
+
* A categorization rule as returned by the host. `getRules()` only ever
|
|
459
|
+
* returns rules this addon created via `saveRule`.
|
|
460
|
+
*/
|
|
461
|
+
export interface CategorizationRule {
|
|
462
|
+
id: string;
|
|
463
|
+
name: string;
|
|
464
|
+
pattern: string;
|
|
465
|
+
matchType: CategorizationRuleMatchType;
|
|
466
|
+
kind: SpendCategoryKind;
|
|
467
|
+
categoryId: string;
|
|
468
|
+
/** Restricted to one activity type, e.g. "WITHDRAWAL". Absent if it matches any type. */
|
|
469
|
+
activityType?: ActivityType;
|
|
470
|
+
/** Restricted to one account. Absent if it applies to all accounts. */
|
|
471
|
+
accountId?: string;
|
|
472
|
+
priority: number;
|
|
473
|
+
createdAt: string;
|
|
474
|
+
updatedAt: string;
|
|
475
|
+
}
|
|
476
|
+
export interface CategorizationRuleInput {
|
|
477
|
+
/**
|
|
478
|
+
* Stable key you choose and keep reusing for the same logical rule across
|
|
479
|
+
* edits/re-saves. Internally combined with your addon's id, so it can't
|
|
480
|
+
* collide with another addon's ruleKey. Calling this again with the same
|
|
481
|
+
* ruleKey updates the existing rule in place instead of creating a
|
|
482
|
+
* duplicate.
|
|
483
|
+
*/
|
|
484
|
+
ruleKey: string;
|
|
485
|
+
/** Shown in Wealthfolio's own Settings → Spending → Rules UI */
|
|
486
|
+
name: string;
|
|
487
|
+
/** Text matched against the activity's notes/description */
|
|
488
|
+
pattern: string;
|
|
489
|
+
/** @default "contains" */
|
|
490
|
+
matchType?: CategorizationRuleMatchType;
|
|
491
|
+
kind: SpendCategoryKind;
|
|
492
|
+
categoryId: string;
|
|
493
|
+
/** Restrict to one activity type, e.g. "WITHDRAWAL". Omit to match any type. */
|
|
494
|
+
activityType?: ActivityType;
|
|
495
|
+
/** Restrict the rule to one account. Omit for a rule that applies everywhere. */
|
|
496
|
+
accountId?: string;
|
|
497
|
+
/** @default 0 */
|
|
498
|
+
priority?: number;
|
|
499
|
+
}
|
|
424
500
|
export interface MonetaryValue {
|
|
425
501
|
local: number;
|
|
426
502
|
base: number;
|
|
@@ -628,7 +704,7 @@ export interface AccountValuation {
|
|
|
628
704
|
netContributionBase: number;
|
|
629
705
|
externalInflowBase: number;
|
|
630
706
|
externalOutflowBase: number;
|
|
631
|
-
externalFlowSource: 'NO_FLOW' | 'UNKNOWN' | 'CASH_AMOUNT' | 'QUOTE_DERIVED_MARKET_VALUE' | 'COST_BASIS_FALLBACK' | 'REMOVED_LOT_BASIS_FALLBACK' | 'LEGACY_ACTIVITY_AMOUNT_FALLBACK' | 'UNKNOWN_BOUNDARY_TRANSFER' | 'ACTIVITY_DERIVED' | 'STORED_GROSS' | 'NET_CONTRIBUTION_FALLBACK' | 'MIXED';
|
|
707
|
+
externalFlowSource: 'NO_FLOW' | 'UNKNOWN' | 'CASH_AMOUNT' | 'QUOTE_DERIVED_MARKET_VALUE' | 'COST_BASIS_FALLBACK' | 'REMOVED_LOT_BASIS_FALLBACK' | 'LEGACY_ACTIVITY_AMOUNT_FALLBACK' | 'UNKNOWN_BOUNDARY_TRANSFER' | 'UNPRICED_HOLDINGS_TRANSITION' | 'ACTIVITY_DERIVED' | 'STORED_GROSS' | 'NET_CONTRIBUTION_FALLBACK' | 'MIXED' | 'MIXED_EXACT';
|
|
632
708
|
performanceEligibleValueBase: number;
|
|
633
709
|
valueStatus: ValuationStatus;
|
|
634
710
|
basisStatus: BasisStatus;
|
|
@@ -676,6 +752,19 @@ export interface ExchangeRate {
|
|
|
676
752
|
isLoading?: boolean;
|
|
677
753
|
timestamp: string;
|
|
678
754
|
}
|
|
755
|
+
export interface ExchangeRateDateQuery {
|
|
756
|
+
fromCurrency: string;
|
|
757
|
+
toCurrency: string;
|
|
758
|
+
/** Requested date in YYYY-MM-DD format. */
|
|
759
|
+
date: string;
|
|
760
|
+
}
|
|
761
|
+
export interface ExchangeRateDateResult {
|
|
762
|
+
fromCurrency: string;
|
|
763
|
+
toCurrency: string;
|
|
764
|
+
date: string;
|
|
765
|
+
rate: number | null;
|
|
766
|
+
error: string | null;
|
|
767
|
+
}
|
|
679
768
|
export interface ContributionLimit {
|
|
680
769
|
id: string;
|
|
681
770
|
groupName: string;
|
package/dist/src/host-api.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Provides comprehensive access to Wealthfolio functionality organized by domain
|
|
4
4
|
*/
|
|
5
5
|
import type { EventCallback, UnlistenFn } from './types';
|
|
6
|
-
import type { Account, Activity, ActivityBulkMutationRequest, ActivityBulkMutationResult, ActivityCreate, ActivityDetails, ActivityImport, ActivitySearchResponse, ActivityUpdate, AccountValuation, CheckSnapshotImportResult, ImportActivitiesResult, Asset, ContributionLimit, DepositsCalculation, ExchangeRate, Goal, GoalAllocation, Holding, ImportMappingData, IncomeSummary, MarketDataProviderInfo, NewContributionLimit, PerformanceResult, Quote, Settings, SimplePerformanceResult, SnapshotHoldingInput, SnapshotImportResult, SnapshotInfo, SnapshotInput, SymbolSearchResult, UpdateAssetProfile } from './data-types';
|
|
6
|
+
import type { Account, Activity, ActivityBulkMutationRequest, ActivityBulkMutationResult, ActivityCreate, ActivityDetails, ActivityImport, ActivitySearchResponse, ActivityUpdate, AccountValuation, CheckSnapshotImportResult, ImportActivitiesResult, Asset, ContributionLimit, DepositsCalculation, ExchangeRate, ExchangeRateDateQuery, ExchangeRateDateResult, Goal, GoalAllocation, Holding, ImportMappingData, IncomeSummary, MarketDataProviderInfo, NewContributionLimit, PerformanceResult, Quote, Settings, SimplePerformanceResult, SnapshotHoldingInput, SnapshotImportResult, SnapshotInfo, SnapshotInput, CategorizationRule, CategorizationRuleInput, SpendCategory, SpendCategoryKind, SymbolSearchResult, UpdateAssetProfile } from './data-types';
|
|
7
7
|
export interface ActivitySearchFilters {
|
|
8
8
|
accountIds?: string | string[];
|
|
9
9
|
activityTypes?: string | string[];
|
|
@@ -284,6 +284,66 @@ export interface ExchangeRatesAPI {
|
|
|
284
284
|
* @returns Promise resolving to created exchange rate
|
|
285
285
|
*/
|
|
286
286
|
add(newRate: Omit<ExchangeRate, 'id'>): Promise<ExchangeRate>;
|
|
287
|
+
/**
|
|
288
|
+
* Look up historical exchange rates for a batch of (currency pair, date) requests.
|
|
289
|
+
* Dates must use YYYY-MM-DD. Resolution follows Wealthfolio's core FX rules,
|
|
290
|
+
* including currency normalization, inverse or triangulated paths, nearest
|
|
291
|
+
* available quotes, and the existing latest-rate fallback.
|
|
292
|
+
* Never rejects for an individual unresolvable pair — each result carries
|
|
293
|
+
* either a rate or an error, so one bad pair doesn't fail the whole batch.
|
|
294
|
+
* @param pairs Currency pairs and dates to resolve
|
|
295
|
+
* @returns Promise resolving to one result per requested pair, in the same order
|
|
296
|
+
*/
|
|
297
|
+
getRatesForDates(pairs: ExchangeRateDateQuery[]): Promise<ExchangeRateDateResult[]>;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Spend categorization APIs
|
|
301
|
+
* Lets addons classify activities (e.g. WITHDRAWALs) into the user's
|
|
302
|
+
* existing spend-category taxonomy via Wealthfolio's categorization-rules
|
|
303
|
+
* engine, rather than a one-off per-activity tag.
|
|
304
|
+
*/
|
|
305
|
+
export interface SpendingAPI {
|
|
306
|
+
/**
|
|
307
|
+
* Whether the user has Spending enabled. Rules and categories still work
|
|
308
|
+
* when it's off, but re-running rules is a no-op until the user opts an
|
|
309
|
+
* account in — check this to explain a `rerunRules()` result of 0.
|
|
310
|
+
* @returns Promise resolving to whether Spending is enabled
|
|
311
|
+
*/
|
|
312
|
+
isEnabled(): Promise<boolean>;
|
|
313
|
+
/**
|
|
314
|
+
* List selectable spend categories, flattened with a display path.
|
|
315
|
+
* @param kind Restrict to one taxonomy. Omit to get all three (expense, income, saving).
|
|
316
|
+
* @returns Promise resolving to array of spend categories
|
|
317
|
+
*/
|
|
318
|
+
getCategories(kind?: SpendCategoryKind): Promise<SpendCategory[]>;
|
|
319
|
+
/**
|
|
320
|
+
* List this addon's own categorization rules (those created via `saveRule`).
|
|
321
|
+
* @returns Promise resolving to array of categorization rules
|
|
322
|
+
*/
|
|
323
|
+
getRules(): Promise<CategorizationRule[]>;
|
|
324
|
+
/**
|
|
325
|
+
* Create or update a categorization rule identified by `rule.ruleKey`.
|
|
326
|
+
* Calling this again with the same ruleKey updates the existing rule
|
|
327
|
+
* in place instead of creating a duplicate.
|
|
328
|
+
* @param rule Rule definition
|
|
329
|
+
* @returns Promise resolving to the created or updated rule
|
|
330
|
+
*/
|
|
331
|
+
saveRule(rule: CategorizationRuleInput): Promise<CategorizationRule>;
|
|
332
|
+
/**
|
|
333
|
+
* Delete the rule previously created with this ruleKey. No-op if absent.
|
|
334
|
+
* @param ruleKey The stable key passed to a prior saveRule call
|
|
335
|
+
* @returns Promise that resolves once the rule is deleted (or confirmed absent)
|
|
336
|
+
*/
|
|
337
|
+
deleteRule(ruleKey: string): Promise<void>;
|
|
338
|
+
/**
|
|
339
|
+
* Re-run all categorization rules. Pass false to overwrite existing
|
|
340
|
+
* rule/AI/history/import-assigned categories too — the default only fills in
|
|
341
|
+
* currently uncategorized activities. Manual assignments are always
|
|
342
|
+
* preserved.
|
|
343
|
+
* @param onlyUncategorized Defaults to true
|
|
344
|
+
* @returns Promise resolving to the number of activities matched by a rule
|
|
345
|
+
*/
|
|
346
|
+
rerunRules(onlyUncategorized?: boolean): Promise<number>;
|
|
287
347
|
}
|
|
288
348
|
/**
|
|
289
349
|
* Contribution limits APIs
|
|
@@ -605,8 +665,10 @@ export interface ToastAPI {
|
|
|
605
665
|
*/
|
|
606
666
|
export interface QueryAPI {
|
|
607
667
|
/**
|
|
608
|
-
* Get the
|
|
609
|
-
*
|
|
668
|
+
* Get the QueryClient scoped to this addon sandbox. Its invalidate/refetch
|
|
669
|
+
* operations are mirrored to the host, but its cache is not shared with the
|
|
670
|
+
* main application or other addons.
|
|
671
|
+
* @returns The addon-scoped QueryClient instance
|
|
610
672
|
*/
|
|
611
673
|
getClient(): unknown;
|
|
612
674
|
/**
|
|
@@ -679,6 +741,8 @@ export interface HostAPI {
|
|
|
679
741
|
performance: PerformanceAPI;
|
|
680
742
|
/** Exchange rates operations */
|
|
681
743
|
exchangeRates: ExchangeRatesAPI;
|
|
744
|
+
/** Spend categorization operations */
|
|
745
|
+
spending: SpendingAPI;
|
|
682
746
|
/** Contribution limits operations */
|
|
683
747
|
contributionLimits: ContributionLimitsAPI;
|
|
684
748
|
/** Goals management operations */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const HOST_DEPENDENCIES: {
|
|
2
2
|
readonly '@tanstack/react-query': "^5.90.0";
|
|
3
|
-
readonly '@wealthfolio/addon-sdk': "^3.
|
|
4
|
-
readonly '@wealthfolio/ui': "^3.
|
|
3
|
+
readonly '@wealthfolio/addon-sdk': "^3.8.0";
|
|
4
|
+
readonly '@wealthfolio/ui': "^3.8.0";
|
|
5
5
|
readonly 'date-fns': "^4.1.0";
|
|
6
6
|
readonly 'lucide-react': "^0.561.0";
|
|
7
7
|
readonly react: "^19.2.0";
|