@wealthfolio/addon-sdk 3.5.1 → 3.6.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/README.md +4 -3
- package/dist/chunk-465MB7HT.js +61 -0
- package/dist/chunk-465MB7HT.js.map +1 -0
- package/dist/chunk-5XUF4TB3.js +193 -0
- package/dist/chunk-5XUF4TB3.js.map +1 -0
- package/dist/chunk-AAIYUZY5.js +16 -0
- package/dist/chunk-AAIYUZY5.js.map +1 -0
- package/dist/chunk-O566EAIL.js +9 -0
- package/dist/chunk-O566EAIL.js.map +1 -0
- package/dist/chunk-PYPEFQCY.js +61 -0
- package/dist/chunk-PYPEFQCY.js.map +1 -0
- package/dist/{chunk-ISD4MMHY.js → chunk-SEHD46ND.js} +17 -3
- package/dist/chunk-SEHD46ND.js.map +1 -0
- package/dist/goal-progress.js +7 -0
- package/dist/goal-progress.js.map +1 -0
- package/dist/host-api.js +1 -0
- package/dist/host-api.js.map +1 -0
- package/dist/host-dependencies.js +7 -0
- package/dist/host-dependencies.js.map +1 -0
- package/dist/index.js +23 -270
- package/dist/index.js.map +1 -1
- package/dist/manifest.js +7 -0
- package/dist/manifest.js.map +1 -0
- package/dist/permissions.js +1 -1
- package/dist/query-keys.js +7 -0
- package/dist/query-keys.js.map +1 -0
- package/dist/src/data-types.d.ts +25 -1
- package/dist/src/host-api.d.ts +24 -0
- package/dist/src/host-dependencies.d.ts +10 -0
- package/dist/src/index.d.ts +18 -8
- package/dist/src/manifest.d.ts +13 -0
- package/dist/src/types.d.ts +33 -7
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils.js +16 -0
- package/dist/utils.js.map +1 -0
- package/package.json +25 -1
- package/dist/chunk-ISD4MMHY.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,284 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SDK_VERSION,
|
|
3
|
+
formatAddonSize,
|
|
4
|
+
generateAddonId,
|
|
5
|
+
isAddonManifest,
|
|
6
|
+
isCompatibleVersion,
|
|
7
|
+
validateManifest
|
|
8
|
+
} from "./chunk-5XUF4TB3.js";
|
|
9
|
+
import {
|
|
10
|
+
calculateGoalProgress
|
|
11
|
+
} from "./chunk-465MB7HT.js";
|
|
12
|
+
import {
|
|
13
|
+
HOST_DEPENDENCIES
|
|
14
|
+
} from "./chunk-AAIYUZY5.js";
|
|
15
|
+
import {
|
|
16
|
+
isInstalledManifest
|
|
17
|
+
} from "./chunk-O566EAIL.js";
|
|
1
18
|
import {
|
|
2
19
|
PERMISSION_CATEGORIES,
|
|
3
20
|
getFunctionRiskLevel,
|
|
4
21
|
getPermissionCategoriesByRisk,
|
|
5
22
|
getPermissionCategory,
|
|
6
23
|
isPermissionRequired
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// Account related keys
|
|
12
|
-
ACCOUNTS: "accounts",
|
|
13
|
-
ACCOUNTS_SUMMARY: "accounts_summary",
|
|
14
|
-
// Activity related keys
|
|
15
|
-
ACTIVITY_DATA: "activity-data",
|
|
16
|
-
ACTIVITIES: "activities",
|
|
17
|
-
// Portfolio related keys
|
|
18
|
-
HOLDINGS: "holdings",
|
|
19
|
-
HOLDING: "holding",
|
|
20
|
-
INCOME_SUMMARY: "incomeSummary",
|
|
21
|
-
PORTFOLIO_SUMMARY: "portfolioSummary",
|
|
22
|
-
QUOTE_HISTORY: "quoteHistory",
|
|
23
|
-
// Goals related keys
|
|
24
|
-
GOALS: "goals",
|
|
25
|
-
GOALS_ALLOCATIONS: "goals_allocations",
|
|
26
|
-
// Settings related keys
|
|
27
|
-
SETTINGS: "settings",
|
|
28
|
-
EXCHANGE_RATES: "exchangeRates",
|
|
29
|
-
// New keys for exchange rates
|
|
30
|
-
EXCHANGE_RATE_SYMBOLS: "exchange_rate_symbols",
|
|
31
|
-
QUOTE: "quote",
|
|
32
|
-
CONTRIBUTION_LIMITS: "contributionLimits",
|
|
33
|
-
CONTRIBUTION_LIMIT_PROGRESS: "contributionLimitProgress",
|
|
34
|
-
ASSET_DATA: "asset_data",
|
|
35
|
-
IMPORT_MAPPING: "import_mapping",
|
|
36
|
-
PERFORMANCE_SUMMARY: "performanceSummary",
|
|
37
|
-
PERFORMANCE_HISTORY: "performanceHistory",
|
|
38
|
-
HISTORY_VALUATION: "historyValuation",
|
|
39
|
-
// Helper function to create account-specific keys
|
|
40
|
-
valuationHistory: (id) => [QueryKeys.HISTORY_VALUATION, id],
|
|
41
|
-
// Account simple performance
|
|
42
|
-
ACCOUNTS_SIMPLE_PERFORMANCE: "accountsSimplePerformance",
|
|
43
|
-
accountsSimplePerformance: (accountIds) => [
|
|
44
|
-
QueryKeys.ACCOUNTS_SIMPLE_PERFORMANCE,
|
|
45
|
-
[...accountIds].sort().join(",") || "none"
|
|
46
|
-
],
|
|
47
|
-
// Market Data Providers
|
|
48
|
-
MARKET_DATA_PROVIDERS: "marketDataProviders",
|
|
49
|
-
MARKET_DATA_PROVIDER_SETTINGS: "marketDataProviderSettings",
|
|
50
|
-
transactions: "transactions",
|
|
51
|
-
latestValuations: "latest-valuations",
|
|
52
|
-
// Market Data
|
|
53
|
-
symbolSearch: "symbol-search",
|
|
54
|
-
ASSET_HISTORY: "asset-history",
|
|
55
|
-
// Addons
|
|
56
|
-
INSTALLED_ADDONS: "installedAddons",
|
|
57
|
-
ADDON_STORE_LISTINGS: "addonStoreListings",
|
|
58
|
-
ADDON_AUTO_UPDATE_CHECK: "addonAutoUpdateCheck",
|
|
59
|
-
SNAPSHOTS: "snapshots",
|
|
60
|
-
snapshots: (accountId) => [QueryKeys.SNAPSHOTS, accountId],
|
|
61
|
-
secrets: {
|
|
62
|
-
apiKey: (providerId) => ["secrets", "apiKey", providerId]
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// src/manifest.ts
|
|
67
|
-
function isInstalledManifest(manifest) {
|
|
68
|
-
return !!(manifest.installedAt && manifest.main !== void 0 && manifest.enabled !== void 0);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// package.json
|
|
72
|
-
var package_default = {
|
|
73
|
-
name: "@wealthfolio/addon-sdk",
|
|
74
|
-
version: "3.5.1",
|
|
75
|
-
type: "module",
|
|
76
|
-
description: "TypeScript SDK for building Wealthfolio addons with enhanced functionality and type safety",
|
|
77
|
-
main: "dist/index.js",
|
|
78
|
-
types: "dist/src/index.d.ts",
|
|
79
|
-
exports: {
|
|
80
|
-
".": {
|
|
81
|
-
import: "./dist/index.js",
|
|
82
|
-
types: "./dist/src/index.d.ts"
|
|
83
|
-
},
|
|
84
|
-
"./types": {
|
|
85
|
-
import: "./dist/types.js",
|
|
86
|
-
types: "./dist/src/types.d.ts"
|
|
87
|
-
},
|
|
88
|
-
"./permissions": {
|
|
89
|
-
import: "./dist/permissions.js",
|
|
90
|
-
types: "./dist/src/permissions.d.ts"
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
files: [
|
|
94
|
-
"dist",
|
|
95
|
-
"README.md",
|
|
96
|
-
"CHANGELOG.md"
|
|
97
|
-
],
|
|
98
|
-
keywords: [
|
|
99
|
-
"wealthfolio",
|
|
100
|
-
"addon",
|
|
101
|
-
"plugin",
|
|
102
|
-
"sdk",
|
|
103
|
-
"typescript",
|
|
104
|
-
"financial",
|
|
105
|
-
"portfolio"
|
|
106
|
-
],
|
|
107
|
-
author: "Wealthfolio Team",
|
|
108
|
-
license: "MIT",
|
|
109
|
-
homepage: "https://wealthfolio.app/addons",
|
|
110
|
-
repository: {
|
|
111
|
-
type: "git",
|
|
112
|
-
url: "https://github.com/wealthfolio/wealthfolio.git",
|
|
113
|
-
directory: "packages/addon-sdk"
|
|
114
|
-
},
|
|
115
|
-
bugs: {
|
|
116
|
-
url: "https://github.com/wealthfolio/wealthfolio/issues"
|
|
117
|
-
},
|
|
118
|
-
scripts: {
|
|
119
|
-
build: "tsup && pnpm run build:types",
|
|
120
|
-
dev: "tsup --watch",
|
|
121
|
-
clean: "rm -rf dist",
|
|
122
|
-
lint: "eslint .",
|
|
123
|
-
"lint:fix": "eslint . --fix",
|
|
124
|
-
"lint:quiet": "eslint . --quiet",
|
|
125
|
-
format: "prettier --write .",
|
|
126
|
-
"format:check": "prettier --check .",
|
|
127
|
-
"type-check": "tsc --noEmit",
|
|
128
|
-
"build:types": "tsc -p tsconfig.json",
|
|
129
|
-
prepack: "npm run build"
|
|
130
|
-
},
|
|
131
|
-
peerDependencies: {
|
|
132
|
-
react: "^19.2.4",
|
|
133
|
-
"react-dom": "^19.2.4"
|
|
134
|
-
},
|
|
135
|
-
devDependencies: {
|
|
136
|
-
"@tanstack/react-query": "^5.90.20",
|
|
137
|
-
"@types/react": "^19.2.13",
|
|
138
|
-
"@types/react-dom": "^19.2.3",
|
|
139
|
-
tsup: "^8.5.1",
|
|
140
|
-
typescript: "^5.9.3"
|
|
141
|
-
},
|
|
142
|
-
engines: {
|
|
143
|
-
node: ">=20.0.0"
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
// src/version.ts
|
|
148
|
-
var SDK_VERSION = package_default.version;
|
|
149
|
-
|
|
150
|
-
// src/utils.ts
|
|
151
|
-
function validateManifest(manifest) {
|
|
152
|
-
const errors = [];
|
|
153
|
-
const warnings = [];
|
|
154
|
-
if (!manifest.id) {
|
|
155
|
-
errors.push("Addon ID is required");
|
|
156
|
-
} else if (!/^[a-z0-9-]+$/.test(manifest.id)) {
|
|
157
|
-
errors.push("Addon ID must contain only lowercase letters, numbers, and hyphens");
|
|
158
|
-
}
|
|
159
|
-
if (!manifest.name) {
|
|
160
|
-
errors.push("Addon name is required");
|
|
161
|
-
}
|
|
162
|
-
if (!manifest.version) {
|
|
163
|
-
errors.push("Addon version is required");
|
|
164
|
-
} else if (!/^\d+\.\d+\.\d+/.test(manifest.version)) {
|
|
165
|
-
warnings.push("Version should follow semantic versioning (e.g., 1.0.0)");
|
|
166
|
-
}
|
|
167
|
-
if (!manifest.description) {
|
|
168
|
-
warnings.push("Description is recommended for better discoverability");
|
|
169
|
-
}
|
|
170
|
-
if (!manifest.author) {
|
|
171
|
-
warnings.push("Author information is recommended");
|
|
172
|
-
}
|
|
173
|
-
if (!manifest.main) {
|
|
174
|
-
warnings.push('Main entry point not specified, defaulting to "addon.js"');
|
|
175
|
-
}
|
|
176
|
-
if (manifest.permissions) {
|
|
177
|
-
manifest.permissions.forEach((permission, index) => {
|
|
178
|
-
if (!permission.category) {
|
|
179
|
-
errors.push(`Permission ${index}: category is required`);
|
|
180
|
-
}
|
|
181
|
-
if (!permission.functions || permission.functions.length === 0) {
|
|
182
|
-
errors.push(`Permission ${index}: at least one function must be specified`);
|
|
183
|
-
}
|
|
184
|
-
if (!permission.purpose) {
|
|
185
|
-
warnings.push(`Permission ${index}: purpose explanation is recommended`);
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
return {
|
|
190
|
-
valid: errors.length === 0,
|
|
191
|
-
errors,
|
|
192
|
-
warnings
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
function isCompatibleVersion(addonSdkVersion, currentSdkVersion = SDK_VERSION) {
|
|
196
|
-
if (!addonSdkVersion) return true;
|
|
197
|
-
const [addonMajor, addonMinor] = addonSdkVersion.split(".").map(Number);
|
|
198
|
-
const [currentMajor, currentMinor] = currentSdkVersion.split(".").map(Number);
|
|
199
|
-
return addonMajor === currentMajor && addonMinor <= currentMinor;
|
|
200
|
-
}
|
|
201
|
-
function formatAddonSize(bytes) {
|
|
202
|
-
const sizes = ["B", "KB", "MB", "GB"];
|
|
203
|
-
if (bytes === 0) return "0 B";
|
|
204
|
-
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
205
|
-
const size = bytes / Math.pow(1024, i);
|
|
206
|
-
return `${size.toFixed(i === 0 ? 0 : 1)} ${sizes[i]}`;
|
|
207
|
-
}
|
|
208
|
-
function generateAddonId(name) {
|
|
209
|
-
return name.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
210
|
-
}
|
|
211
|
-
function isAddonManifest(obj) {
|
|
212
|
-
return typeof obj === "object" && obj !== null && typeof obj.id === "string" && typeof obj.name === "string" && typeof obj.version === "string";
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// src/goal-progress.ts
|
|
216
|
-
function isParticipatingGoal(goal) {
|
|
217
|
-
if (goal.statusLifecycle) {
|
|
218
|
-
return goal.statusLifecycle === "active";
|
|
219
|
-
}
|
|
220
|
-
return true;
|
|
221
|
-
}
|
|
222
|
-
function getFiniteAmount(value) {
|
|
223
|
-
if (value === null || value === void 0 || value === "") {
|
|
224
|
-
return void 0;
|
|
225
|
-
}
|
|
226
|
-
const amount = typeof value === "number" ? value : Number(value);
|
|
227
|
-
return Number.isFinite(amount) ? amount : void 0;
|
|
228
|
-
}
|
|
229
|
-
function toFiniteAmount(value) {
|
|
230
|
-
return getFiniteAmount(value) ?? 0;
|
|
231
|
-
}
|
|
232
|
-
function calculateGoalProgress(accountsValuations, goals, allocations) {
|
|
233
|
-
if (!goals) {
|
|
234
|
-
return [];
|
|
235
|
-
}
|
|
236
|
-
const baseCurrency = accountsValuations?.[0]?.baseCurrency ?? "USD";
|
|
237
|
-
const accountValueMap = /* @__PURE__ */ new Map();
|
|
238
|
-
accountsValuations?.forEach((account) => {
|
|
239
|
-
const valueInBaseCurrency = account.totalValueBase ?? 0;
|
|
240
|
-
accountValueMap.set(account.accountId, valueInBaseCurrency);
|
|
241
|
-
});
|
|
242
|
-
const allocationsByGoal = /* @__PURE__ */ new Map();
|
|
243
|
-
allocations?.forEach((alloc) => {
|
|
244
|
-
const existing = allocationsByGoal.get(alloc.goalId) ?? [];
|
|
245
|
-
allocationsByGoal.set(alloc.goalId, [...existing, alloc]);
|
|
246
|
-
});
|
|
247
|
-
const sortedGoals = [...goals].filter(isParticipatingGoal).sort(
|
|
248
|
-
(a, b) => toFiniteAmount(a.summaryTargetAmount ?? a.targetAmount) - toFiniteAmount(b.summaryTargetAmount ?? b.targetAmount)
|
|
249
|
-
);
|
|
250
|
-
return sortedGoals.map((goal) => {
|
|
251
|
-
const goalAllocations = allocationsByGoal.get(goal.id) ?? [];
|
|
252
|
-
const targetAmount = toFiniteAmount(goal.summaryTargetAmount ?? goal.targetAmount);
|
|
253
|
-
const totalAllocatedValue = goalAllocations.reduce((total, allocation) => {
|
|
254
|
-
const accountValueInBase = accountValueMap.get(allocation.accountId) ?? 0;
|
|
255
|
-
return total + accountValueInBase * allocation.sharePercent / 100;
|
|
256
|
-
}, 0);
|
|
257
|
-
const currentValue = getFiniteAmount(goal.summaryCurrentValue) ?? totalAllocatedValue;
|
|
258
|
-
const progress = getFiniteAmount(goal.summaryProgress) ?? (targetAmount > 0 ? currentValue / targetAmount : 0);
|
|
259
|
-
return {
|
|
260
|
-
goalId: goal.id,
|
|
261
|
-
name: goal.title,
|
|
262
|
-
targetValue: targetAmount,
|
|
263
|
-
currentValue,
|
|
264
|
-
progress,
|
|
265
|
-
currency: goal.currency ?? baseCurrency,
|
|
266
|
-
statusHealth: goal.statusHealth,
|
|
267
|
-
targetDate: goal.targetDate
|
|
268
|
-
};
|
|
269
|
-
});
|
|
270
|
-
}
|
|
24
|
+
} from "./chunk-SEHD46ND.js";
|
|
25
|
+
import {
|
|
26
|
+
QueryKeys
|
|
27
|
+
} from "./chunk-PYPEFQCY.js";
|
|
271
28
|
|
|
272
29
|
// src/index.ts
|
|
273
|
-
var ReactVersion = "19.
|
|
274
|
-
var hostGlobals = window;
|
|
275
|
-
var React = hostGlobals.React;
|
|
276
|
-
var ReactDOM = hostGlobals.ReactDOM;
|
|
30
|
+
var ReactVersion = "19.2.4";
|
|
277
31
|
export {
|
|
32
|
+
HOST_DEPENDENCIES,
|
|
278
33
|
PERMISSION_CATEGORIES,
|
|
279
34
|
QueryKeys,
|
|
280
|
-
React,
|
|
281
|
-
ReactDOM,
|
|
282
35
|
ReactVersion,
|
|
283
36
|
SDK_VERSION,
|
|
284
37
|
calculateGoalProgress,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/query-keys.ts","../src/manifest.ts","../package.json","../src/version.ts","../src/utils.ts","../src/goal-progress.ts","../src/index.ts"],"sourcesContent":["/**\n * Shared Query Keys for React Query\n * These keys should match the main application's query keys to ensure cache consistency\n */\nexport const QueryKeys = {\n // Account related keys\n ACCOUNTS: 'accounts',\n ACCOUNTS_SUMMARY: 'accounts_summary',\n\n // Activity related keys\n ACTIVITY_DATA: 'activity-data',\n ACTIVITIES: 'activities',\n\n // Portfolio related keys\n HOLDINGS: 'holdings',\n HOLDING: 'holding',\n INCOME_SUMMARY: 'incomeSummary',\n PORTFOLIO_SUMMARY: 'portfolioSummary',\n QUOTE_HISTORY: 'quoteHistory',\n\n // Goals related keys\n GOALS: 'goals',\n GOALS_ALLOCATIONS: 'goals_allocations',\n\n // Settings related keys\n SETTINGS: 'settings',\n EXCHANGE_RATES: 'exchangeRates',\n\n // New keys for exchange rates\n EXCHANGE_RATE_SYMBOLS: 'exchange_rate_symbols',\n QUOTE: 'quote',\n\n CONTRIBUTION_LIMITS: 'contributionLimits',\n CONTRIBUTION_LIMIT_PROGRESS: 'contributionLimitProgress',\n\n ASSET_DATA: 'asset_data',\n IMPORT_MAPPING: 'import_mapping',\n\n PERFORMANCE_SUMMARY: 'performanceSummary',\n PERFORMANCE_HISTORY: 'performanceHistory',\n\n HISTORY_VALUATION: 'historyValuation',\n // Helper function to create account-specific keys\n valuationHistory: (id: string) => [QueryKeys.HISTORY_VALUATION, id],\n\n // Account simple performance\n ACCOUNTS_SIMPLE_PERFORMANCE: 'accountsSimplePerformance',\n accountsSimplePerformance: (accountIds: string[]) => [\n QueryKeys.ACCOUNTS_SIMPLE_PERFORMANCE,\n [...accountIds].sort().join(',') || 'none',\n ],\n\n // Market Data Providers\n MARKET_DATA_PROVIDERS: 'marketDataProviders',\n MARKET_DATA_PROVIDER_SETTINGS: 'marketDataProviderSettings',\n\n transactions: 'transactions',\n latestValuations: 'latest-valuations',\n\n // Market Data\n symbolSearch: 'symbol-search',\n\n ASSET_HISTORY: 'asset-history',\n\n // Addons\n INSTALLED_ADDONS: 'installedAddons',\n ADDON_STORE_LISTINGS: 'addonStoreListings',\n ADDON_AUTO_UPDATE_CHECK: 'addonAutoUpdateCheck',\n\n SNAPSHOTS: 'snapshots',\n snapshots: (accountId: string) => [QueryKeys.SNAPSHOTS, accountId],\n\n secrets: {\n apiKey: (providerId: string) => ['secrets', 'apiKey', providerId],\n },\n} as const;\n\nexport type QueryKeys = typeof QueryKeys;\n","/**\n * Addon manifest and metadata types\n */\n\nimport type { Permission } from './permissions';\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 (base64 or relative path) */\n icon?: string;\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/**\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\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 /** 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 /** 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","{\n \"name\": \"@wealthfolio/addon-sdk\",\n \"version\": \"3.5.1\",\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 \"./permissions\": {\n \"import\": \"./dist/permissions.js\",\n \"types\": \"./dist/src/permissions.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 { 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 // 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","import type { Goal, GoalAllocation, AccountValuation, GoalProgress } from './data-types';\n\nfunction isParticipatingGoal(goal: Goal): boolean {\n if (goal.statusLifecycle) {\n return goal.statusLifecycle === 'active';\n }\n\n return true;\n}\n\nfunction getFiniteAmount(value: unknown): number | undefined {\n if (value === null || value === undefined || value === '') {\n return undefined;\n }\n\n const amount = typeof value === 'number' ? value : Number(value);\n return Number.isFinite(amount) ? amount : undefined;\n}\n\nfunction toFiniteAmount(value: unknown): number {\n return getFiniteAmount(value) ?? 0;\n}\n\n/**\n * Calculate goal progress from goal summaries, falling back to allocations.\n */\nexport function calculateGoalProgress(\n accountsValuations: AccountValuation[],\n goals: Goal[],\n allocations: GoalAllocation[],\n): GoalProgress[] {\n if (!goals) {\n return [];\n }\n\n const baseCurrency = accountsValuations?.[0]?.baseCurrency ?? 'USD';\n\n // accountId -> totalValue in base currency\n const accountValueMap = new Map<string, number>();\n accountsValuations?.forEach((account) => {\n const valueInBaseCurrency = account.totalValueBase ?? 0;\n accountValueMap.set(account.accountId, valueInBaseCurrency);\n });\n\n // goalId -> allocations\n const allocationsByGoal = new Map<string, GoalAllocation[]>();\n allocations?.forEach((alloc) => {\n const existing = allocationsByGoal.get(alloc.goalId) ?? [];\n allocationsByGoal.set(alloc.goalId, [...existing, alloc]);\n });\n\n const sortedGoals = [...goals]\n .filter(isParticipatingGoal)\n .sort(\n (a, b) =>\n toFiniteAmount(a.summaryTargetAmount ?? a.targetAmount) -\n toFiniteAmount(b.summaryTargetAmount ?? b.targetAmount),\n );\n\n return sortedGoals.map((goal) => {\n const goalAllocations = allocationsByGoal.get(goal.id) ?? [];\n const targetAmount = toFiniteAmount(goal.summaryTargetAmount ?? goal.targetAmount);\n\n const totalAllocatedValue = goalAllocations.reduce((total, allocation) => {\n const accountValueInBase = accountValueMap.get(allocation.accountId) ?? 0;\n return total + (accountValueInBase * allocation.sharePercent) / 100;\n }, 0);\n\n const currentValue = getFiniteAmount(goal.summaryCurrentValue) ?? totalAllocatedValue;\n const progress =\n getFiniteAmount(goal.summaryProgress) ??\n (targetAmount > 0 ? currentValue / targetAmount : 0);\n\n return {\n goalId: goal.id,\n name: goal.title,\n targetValue: targetAmount,\n currentValue,\n progress,\n currency: goal.currency ?? baseCurrency,\n statusHealth: goal.statusHealth,\n targetDate: goal.targetDate,\n };\n });\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 1.0.0\n * @author Wealthfolio Team\n * @license MIT\n */\n\n// Core types\nexport type {\n AddonContext,\n AddonEnableFunction,\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 SnapshotsAPI,\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 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 getFunctionRiskLevel,\n getPermissionCategoriesByRisk,\n getPermissionCategory,\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// Framework version contract\n// -----------------------------------------------------------------------------\n\n/**\n * React version guaranteed by the host application. Addons may assert against\n * this at runtime if they rely on a particular React feature set.\n */\nexport const ReactVersion = '19.1.1';\n\n/**\n * Addons receive their context as a parameter to the enable() function.\n * Each addon gets its own isolated context with scoped secret storage.\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() to register routes\n * }\n */\n\ninterface HostGlobals {\n React: typeof import('react');\n ReactDOM: typeof import('react-dom');\n}\nconst hostGlobals = window as unknown as Partial<HostGlobals>;\nexport const React = hostGlobals.React!;\nexport const ReactDOM = hostGlobals.ReactDOM!;\n\n// Version\nexport { SDK_VERSION } from './version';\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\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.0.0\n * @author Wealthfolio Team\n * @license MIT\n */\n\n// Core types\nexport type {\n AddonContext,\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 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 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 getFunctionRiskLevel,\n getPermissionCategoriesByRisk,\n getPermissionCategory,\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/**\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmGO,IAAM,eAAe;","names":[]}
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/permissions.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/src/data-types.d.ts
CHANGED
|
@@ -130,6 +130,7 @@ export interface Activity {
|
|
|
130
130
|
unitPrice?: string | null;
|
|
131
131
|
amount?: string | null;
|
|
132
132
|
fee?: string | null;
|
|
133
|
+
tax?: string | null;
|
|
133
134
|
currency: string;
|
|
134
135
|
fxRate?: string | null;
|
|
135
136
|
notes?: string;
|
|
@@ -162,6 +163,7 @@ export interface ActivityDetails {
|
|
|
162
163
|
unitPrice: string | null;
|
|
163
164
|
amount: string | null;
|
|
164
165
|
fee: string | null;
|
|
166
|
+
tax?: string | null;
|
|
165
167
|
currency: string;
|
|
166
168
|
needsReview: boolean;
|
|
167
169
|
comment?: string;
|
|
@@ -219,6 +221,7 @@ export interface ActivityCreate {
|
|
|
219
221
|
amount?: string | number | null;
|
|
220
222
|
currency?: string;
|
|
221
223
|
fee?: string | number | null;
|
|
224
|
+
tax?: string | number | null;
|
|
222
225
|
comment?: string | null;
|
|
223
226
|
fxRate?: string | number | null;
|
|
224
227
|
metadata?: string | Record<string, unknown>;
|
|
@@ -238,6 +241,7 @@ export interface ActivityUpdate {
|
|
|
238
241
|
amount?: string | number | null;
|
|
239
242
|
currency?: string;
|
|
240
243
|
fee?: string | number | null;
|
|
244
|
+
tax?: string | number | null;
|
|
241
245
|
comment?: string | null;
|
|
242
246
|
fxRate?: string | number | null;
|
|
243
247
|
metadata?: string | Record<string, unknown>;
|
|
@@ -276,6 +280,7 @@ export interface ActivityImport {
|
|
|
276
280
|
quantity?: number | string | null;
|
|
277
281
|
unitPrice?: number | string | null;
|
|
278
282
|
fee?: number | string | null;
|
|
283
|
+
tax?: number | string | null;
|
|
279
284
|
fxRate?: number | string | null;
|
|
280
285
|
accountName?: string;
|
|
281
286
|
symbolName?: string;
|
|
@@ -603,6 +608,8 @@ export interface DateRange {
|
|
|
603
608
|
to: Date | undefined;
|
|
604
609
|
}
|
|
605
610
|
export type TimePeriod = '1D' | '1W' | '1M' | '3M' | '6M' | 'YTD' | '1Y' | '5Y' | 'ALL';
|
|
611
|
+
export type ValuationStatus = 'complete' | 'partialUnpriced' | 'unavailable';
|
|
612
|
+
export type BasisStatus = 'complete' | 'partialUnknown' | 'unknown' | 'notApplicable';
|
|
606
613
|
export interface AccountValuation {
|
|
607
614
|
id: string;
|
|
608
615
|
accountId: string;
|
|
@@ -622,8 +629,10 @@ export interface AccountValuation {
|
|
|
622
629
|
netContributionBase: number;
|
|
623
630
|
externalInflowBase: number;
|
|
624
631
|
externalOutflowBase: number;
|
|
625
|
-
externalFlowSource: 'UNKNOWN' | 'ACTIVITY_DERIVED' | 'STORED_GROSS' | 'NET_CONTRIBUTION_FALLBACK' | 'MIXED';
|
|
632
|
+
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';
|
|
626
633
|
performanceEligibleValueBase: number;
|
|
634
|
+
valueStatus: ValuationStatus;
|
|
635
|
+
basisStatus: BasisStatus;
|
|
627
636
|
calculatedAt: string;
|
|
628
637
|
}
|
|
629
638
|
export interface AccountSummaryView {
|
|
@@ -703,6 +712,8 @@ export interface PerformanceResult {
|
|
|
703
712
|
attribution: PerformanceAttribution;
|
|
704
713
|
risk: PerformanceRisk;
|
|
705
714
|
dataQuality: PerformanceDataQuality;
|
|
715
|
+
basisStatus?: BasisStatus;
|
|
716
|
+
summary?: PerformanceSummary;
|
|
706
717
|
series: ReturnData[];
|
|
707
718
|
isHoldingsMode?: boolean;
|
|
708
719
|
isMixedTrackingMode?: boolean;
|
|
@@ -718,6 +729,19 @@ export interface PerformancePeriod {
|
|
|
718
729
|
endDate?: string | null;
|
|
719
730
|
}
|
|
720
731
|
export type ReturnMethod = 'timeWeighted' | 'valueReturn' | 'symbolPriceBased' | 'notApplicable';
|
|
732
|
+
export type PerformanceSummaryBasis = 'marketValue' | 'bookBasis' | 'mixed' | 'notApplicable';
|
|
733
|
+
export type PerformanceSummaryStatus = 'complete' | 'unavailable';
|
|
734
|
+
export interface PerformanceSummary {
|
|
735
|
+
amount?: number | null;
|
|
736
|
+
percent?: number | null;
|
|
737
|
+
method: ReturnMethod;
|
|
738
|
+
basis: PerformanceSummaryBasis;
|
|
739
|
+
quality: PerformanceDataQuality['status'];
|
|
740
|
+
amountStatus: PerformanceSummaryStatus;
|
|
741
|
+
percentStatus: PerformanceSummaryStatus;
|
|
742
|
+
basisStatus: BasisStatus;
|
|
743
|
+
reasons: string[];
|
|
744
|
+
}
|
|
721
745
|
export interface PerformanceReturns {
|
|
722
746
|
twr?: number | null;
|
|
723
747
|
annualizedTwr?: number | null;
|
package/dist/src/host-api.d.ts
CHANGED
|
@@ -585,6 +585,28 @@ export interface QueryAPI {
|
|
|
585
585
|
*/
|
|
586
586
|
refetchQueries(queryKey: string | string[]): void;
|
|
587
587
|
}
|
|
588
|
+
export interface NetworkRequest {
|
|
589
|
+
url: string;
|
|
590
|
+
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD';
|
|
591
|
+
headers?: Record<string, string>;
|
|
592
|
+
body?: string;
|
|
593
|
+
auth?: NetworkAuth;
|
|
594
|
+
}
|
|
595
|
+
export interface NetworkResponse {
|
|
596
|
+
status: number;
|
|
597
|
+
headers: Record<string, string>;
|
|
598
|
+
body: string;
|
|
599
|
+
}
|
|
600
|
+
export interface NetworkAuth {
|
|
601
|
+
type: 'bearer';
|
|
602
|
+
secretKey: string;
|
|
603
|
+
}
|
|
604
|
+
export interface NetworkAPI {
|
|
605
|
+
/**
|
|
606
|
+
* Send a brokered HTTPS request to a host declared in the addon manifest.
|
|
607
|
+
*/
|
|
608
|
+
request(request: NetworkRequest): Promise<NetworkResponse>;
|
|
609
|
+
}
|
|
588
610
|
/**
|
|
589
611
|
* Snapshot management APIs
|
|
590
612
|
* For accounts using HOLDINGS tracking mode
|
|
@@ -638,6 +660,8 @@ export interface HostAPI {
|
|
|
638
660
|
navigation: NavigationAPI;
|
|
639
661
|
/** React Query operations */
|
|
640
662
|
query: QueryAPI;
|
|
663
|
+
/** Brokered external network operations */
|
|
664
|
+
network: NetworkAPI;
|
|
641
665
|
/** Toast notification operations */
|
|
642
666
|
toast: ToastAPI;
|
|
643
667
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const HOST_DEPENDENCIES: {
|
|
2
|
+
readonly '@tanstack/react-query': "^5.90.0";
|
|
3
|
+
readonly '@wealthfolio/addon-sdk': "^3.6.0";
|
|
4
|
+
readonly '@wealthfolio/ui': "^3.6.0";
|
|
5
|
+
readonly 'date-fns': "^4.1.0";
|
|
6
|
+
readonly 'lucide-react': "^0.561.0";
|
|
7
|
+
readonly react: "^19.2.0";
|
|
8
|
+
readonly 'react-dom': "^19.2.0";
|
|
9
|
+
readonly recharts: "^3.7.0";
|
|
10
|
+
};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -8,22 +8,32 @@
|
|
|
8
8
|
* @author Wealthfolio Team
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
export type { AddonContext, AddonEnableFunction, EventCallback, RouteConfig, RouterManager, SidebarItemConfig, SidebarItemHandle, SidebarManager, UnlistenFn, } from './types';
|
|
12
|
-
export type { ActivitySearchFilters, ActivitySort, HostAPI, SnapshotsAPI, ToastAPI, DividendEvent, FetchDividendsOptions, } from './host-api';
|
|
11
|
+
export type { AddonContext, AddonEnableFunction, AddonRouteLocation, AddonRouteRenderContext, AddonRouteRenderer, EventCallback, RouteConfig, RouterManager, SidebarItemConfig, SidebarItemHandle, SidebarManager, UnlistenFn, } from './types';
|
|
12
|
+
export type { ActivitySearchFilters, ActivitySort, HostAPI, NetworkAuth, NetworkAPI, NetworkRequest, NetworkResponse, SnapshotsAPI, ToastAPI, DividendEvent, FetchDividendsOptions, } from './host-api';
|
|
13
13
|
export type { QueryClient } from '@tanstack/react-query';
|
|
14
14
|
export { QueryKeys } from './query-keys';
|
|
15
15
|
export type * from './data-types';
|
|
16
|
-
export type { AddonFile, AddonInstallResult, AddonManifest, AddonStoreListing, AddonUpdateCheckResult, AddonUpdateInfo, AddonValidationResult, DevelopmentManifest, ExtractedAddon, InstalledAddon, InstalledManifest, } from './manifest';
|
|
16
|
+
export type { AddonFile, AddonHostDependencies, AddonInstallResult, AddonManifest, AddonStoreListing, AddonUpdateCheckResult, AddonUpdateInfo, AddonValidationResult, DevelopmentManifest, ExtractedAddon, InstalledAddon, InstalledManifest, } from './manifest';
|
|
17
17
|
export { isInstalledManifest } from './manifest';
|
|
18
18
|
export type { FunctionPermission, Permission, PermissionCategory, RiskLevel, } from './permissions';
|
|
19
19
|
export { getFunctionRiskLevel, getPermissionCategoriesByRisk, getPermissionCategory, isPermissionRequired, PERMISSION_CATEGORIES, } from './permissions';
|
|
20
20
|
export { formatAddonSize, generateAddonId, isAddonManifest, isCompatibleVersion, validateManifest, } from './utils';
|
|
21
21
|
export { calculateGoalProgress } from './goal-progress';
|
|
22
22
|
/**
|
|
23
|
-
* React version
|
|
24
|
-
*
|
|
23
|
+
* React version provided by the Wealthfolio add-on sandbox for host-externalized
|
|
24
|
+
* add-ons.
|
|
25
|
+
*/
|
|
26
|
+
export declare const ReactVersion = "19.2.4";
|
|
27
|
+
export { HOST_DEPENDENCIES } from './host-dependencies';
|
|
28
|
+
/**
|
|
29
|
+
* Addons receive their context as a parameter to the enable() function.
|
|
30
|
+
* Each addon gets its own isolated iframe context with scoped host APIs.
|
|
31
|
+
*
|
|
32
|
+
* Example:
|
|
33
|
+
* export default function enable(ctx: AddonContext) {
|
|
34
|
+
* // Use ctx.api.secrets.set/get/delete for secure storage
|
|
35
|
+
* // Use ctx.sidebar.addItem() to add navigation
|
|
36
|
+
* // Use ctx.router.add() with a render callback to register routes
|
|
37
|
+
* }
|
|
25
38
|
*/
|
|
26
|
-
export declare const ReactVersion = "19.1.1";
|
|
27
|
-
export declare const React: typeof import("react");
|
|
28
|
-
export declare const ReactDOM: typeof import("react-dom");
|
|
29
39
|
export { SDK_VERSION } from './version';
|
package/dist/src/manifest.d.ts
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
* Addon manifest and metadata types
|
|
3
3
|
*/
|
|
4
4
|
import type { Permission } from './permissions';
|
|
5
|
+
export interface AddonNetworkAccess {
|
|
6
|
+
allowedHosts: string[];
|
|
7
|
+
approvedHosts?: string[];
|
|
8
|
+
}
|
|
9
|
+
export type AddonHostDependencies = Record<string, string>;
|
|
5
10
|
/**
|
|
6
11
|
* Unified addon manifest structure that handles both development and runtime scenarios
|
|
7
12
|
* This represents both what developers write in their manifest.json and installed addon metadata
|
|
@@ -37,6 +42,10 @@ export interface AddonManifest {
|
|
|
37
42
|
keywords?: string[];
|
|
38
43
|
/** Addon icon (base64 or relative path) */
|
|
39
44
|
icon?: string;
|
|
45
|
+
/** Network hosts this addon may reach through the host broker */
|
|
46
|
+
network?: AddonNetworkAccess;
|
|
47
|
+
/** Host-provided packages this addon imports instead of bundling */
|
|
48
|
+
hostDependencies?: AddonHostDependencies;
|
|
40
49
|
/** Installation timestamp in ISO format */
|
|
41
50
|
installedAt?: string;
|
|
42
51
|
/** Last update timestamp */
|
|
@@ -125,6 +134,8 @@ export interface AddonUpdateInfo {
|
|
|
125
134
|
updateAvailable: boolean;
|
|
126
135
|
/** Download URL for the update */
|
|
127
136
|
downloadUrl?: string;
|
|
137
|
+
/** Optional SHA-256 digest for the update package bytes */
|
|
138
|
+
sha256?: string;
|
|
128
139
|
/** Release notes for the latest version */
|
|
129
140
|
releaseNotes?: string;
|
|
130
141
|
/** Release date of the latest version */
|
|
@@ -157,6 +168,8 @@ export interface AddonStoreListing {
|
|
|
157
168
|
metadata: AddonManifest;
|
|
158
169
|
/** Download URL */
|
|
159
170
|
downloadUrl: string;
|
|
171
|
+
/** Optional SHA-256 digest for the package bytes */
|
|
172
|
+
sha256?: string;
|
|
160
173
|
/** Number of downloads */
|
|
161
174
|
downloads?: number;
|
|
162
175
|
/** Average rating */
|