From 7363313f1e90e1cbb9aaba38fecc7c2870c76ad7 Mon Sep 17 00:00:00 2001 From: mirivlad Date: Mon, 29 Jun 2026 04:27:22 +0800 Subject: [PATCH] feat: expose plugin data storage bridge --- .../src/lib/plugin-host/VerstakPluginAPI.js | 25 +++++++++++++++++++ frontend/src/lib/test/wails-mock.js | 12 +++++++-- .../tests/plugin-api-contributions-test.mjs | 21 ++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/frontend/src/lib/plugin-host/VerstakPluginAPI.js b/frontend/src/lib/plugin-host/VerstakPluginAPI.js index 0d67691..50f709e 100644 --- a/frontend/src/lib/plugin-host/VerstakPluginAPI.js +++ b/frontend/src/lib/plugin-host/VerstakPluginAPI.js @@ -232,6 +232,31 @@ export function createPluginAPI(pluginId) { } }, + storage: { + data: { + read: function(name) { + assertActive('storage.data.read(' + name + ')'); + if (!name) { + throw new Error('storage.data.read requires a name'); + } + return callBackend(pluginId, 'storage.data.read(' + name + ')', function() { + return App.ReadPluginDataJSON(pluginId, name); + }).then(function(data) { + return data || {}; + }); + }, + write: function(name, data) { + assertActive('storage.data.write(' + name + ')'); + if (!name) { + throw new Error('storage.data.write requires a name'); + } + return callBackendErrorString(pluginId, 'storage.data.write(' + name + ')', function() { + return App.WritePluginDataJSON(pluginId, name, data || {}); + }); + } + } + }, + files: { list: function(relativeDir) { assertActive('files.list'); diff --git a/frontend/src/lib/test/wails-mock.js b/frontend/src/lib/test/wails-mock.js index bf500b1..e4b703a 100644 --- a/frontend/src/lib/test/wails-mock.js +++ b/frontend/src/lib/test/wails-mock.js @@ -216,6 +216,7 @@ var pluginSettings = { 'verstak.platform-test': { savedText: 'initial value' } }; + var pluginData = {}; var vaultFiles = makeDefaultVaultFiles(); var externalOpens = []; var trashEntries = []; @@ -1120,8 +1121,15 @@ }, ReadPluginSetting: function () { return Promise.resolve(null); }, WritePluginSetting: function () { return Promise.resolve(null); }, - ReadPluginDataJSON: function () { return Promise.resolve({}); }, - WritePluginDataJSON: function () { return Promise.resolve(null); }, + ReadPluginDataJSON: function (pluginId, name) { + var data = (pluginData[pluginId] && pluginData[pluginId][name]) || {}; + return Promise.resolve([Object.assign({}, data), '']); + }, + WritePluginDataJSON: function (pluginId, name, data) { + pluginData[pluginId] = pluginData[pluginId] || {}; + pluginData[pluginId][name] = Object.assign({}, data || {}); + return Promise.resolve(''); + }, OpenWorkbenchResource: function (pluginId, request) { return openWorkbenchResource(pluginId, request || {}, ''); }, diff --git a/frontend/tests/plugin-api-contributions-test.mjs b/frontend/tests/plugin-api-contributions-test.mjs index 9ff31c1..57e7df2 100644 --- a/frontend/tests/plugin-api-contributions-test.mjs +++ b/frontend/tests/plugin-api-contributions-test.mjs @@ -2,6 +2,8 @@ import fs from 'node:fs'; import path from 'node:path'; import { pathToFileURL } from 'node:url'; +const pluginData = {}; + globalThis.window = { __VERSTAK_PLUGIN_REGISTRY__: {}, __VERSTAK_EVENT_HANDLERS__: {}, @@ -27,6 +29,15 @@ globalThis.window = { commandId, args, }, '']), + ReadPluginDataJSON: (pluginId, name) => Promise.resolve([ + Object.assign({}, (pluginData[pluginId] && pluginData[pluginId][name]) || {}), + '', + ]), + WritePluginDataJSON: (pluginId, name, data) => { + pluginData[pluginId] = pluginData[pluginId] || {}; + pluginData[pluginId][name] = Object.assign({}, data || {}); + return Promise.resolve(''); + }, }, }, }, @@ -67,4 +78,14 @@ if (result.status !== 'handled' || result.result.handledPath !== 'Project/Docs/r throw new Error(`unexpected executeFor result: ${JSON.stringify(result)}`); } +if (!api.storage || !api.storage.data || typeof api.storage.data.read !== 'function' || typeof api.storage.data.write !== 'function') { + throw new Error('api.storage.data read/write is missing'); +} + +await api.storage.data.write('search-index', { version: 1, workspaceRootPath: 'Project' }); +const stored = await api.storage.data.read('search-index'); +if (stored.version !== 1 || stored.workspaceRootPath !== 'Project') { + throw new Error(`unexpected storage data: ${JSON.stringify(stored)}`); +} + console.log('plugin api contributions smoke passed');