feat: expose plugin data storage API
This commit is contained in:
parent
663e299d28
commit
4387c6ab19
|
|
@ -1,5 +1,6 @@
|
||||||
import type { CapabilityEntry, FileBytes, FileEntry, FileMetadata, MovePathOptions, OpenResourceRequest, OpenResourceResult, PluginSettings, RegisteredContributionPoints, RestoreTrashOptions, TrashEntry, TrashResult, WriteTextOptions } from './types';
|
import type { CapabilityEntry, FileBytes, FileEntry, FileMetadata, MovePathOptions, OpenResourceRequest, OpenResourceResult, PluginSettings, RegisteredContributionPoints, RestoreTrashOptions, TrashEntry, TrashResult, WriteTextOptions } from './types';
|
||||||
export type PluginCommandArgs = Record<string, unknown>;
|
export type PluginCommandArgs = Record<string, unknown>;
|
||||||
|
export type PluginDataJSON = Record<string, unknown>;
|
||||||
export type PluginCommandHandler = (args: PluginCommandArgs, declaration: PluginCommandDeclaration) => unknown | Promise<unknown>;
|
export type PluginCommandHandler = (args: PluginCommandArgs, declaration: PluginCommandDeclaration) => unknown | Promise<unknown>;
|
||||||
export type Unsubscribe = () => void;
|
export type Unsubscribe = () => void;
|
||||||
export interface PluginCommandDeclaration {
|
export interface PluginCommandDeclaration {
|
||||||
|
|
@ -62,6 +63,12 @@ export interface VerstakPluginAPI {
|
||||||
write(key: string, value: unknown): Promise<PluginSettings>;
|
write(key: string, value: unknown): Promise<PluginSettings>;
|
||||||
writeAll(settings: PluginSettings): Promise<void>;
|
writeAll(settings: PluginSettings): Promise<void>;
|
||||||
};
|
};
|
||||||
|
storage: {
|
||||||
|
data: {
|
||||||
|
read(name: string): Promise<PluginDataJSON>;
|
||||||
|
write(name: string, data: PluginDataJSON): Promise<void>;
|
||||||
|
};
|
||||||
|
};
|
||||||
capabilities: {
|
capabilities: {
|
||||||
has(capability: string): Promise<boolean>;
|
has(capability: string): Promise<boolean>;
|
||||||
get(capability: string): Promise<{
|
get(capability: string): Promise<{
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"plugin-api.js","sourceRoot":"","sources":["../src/plugin-api.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,8EAA8E;AAC9E,gDAAgD;AA8JhD,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;AACtF,CAAC"}
|
{"version":3,"file":"plugin-api.js","sourceRoot":"","sources":["../src/plugin-api.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,8EAA8E;AAC9E,gDAAgD;AAsKhD,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;AACtF,CAAC"}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,KAAK,EAAwB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAQ3E,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,4BAA4B,CAAC;CAC9C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAetF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CASnF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,SAAgB,EAAE,OAAO,GAAE,oBAAyB,GAAG,gBAAgB,CAySlH;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAgCxF;AAGD,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,EAAE,EAAE,CAAC"}
|
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,KAAK,EAAwB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAQ3E,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,4BAA4B,CAAC;CAC9C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAetF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CASnF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,SAAgB,EAAE,OAAO,GAAE,oBAAyB,GAAG,gBAAgB,CAkTlH;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAgCxF;AAGD,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,EAAE,EAAE,CAAC"}
|
||||||
|
|
@ -40,6 +40,7 @@ export function createTestPluginState(overrides) {
|
||||||
*/
|
*/
|
||||||
export function createMockPluginAPI(pluginId = 'test.plugin', options = {}) {
|
export function createMockPluginAPI(pluginId = 'test.plugin', options = {}) {
|
||||||
const settings = {};
|
const settings = {};
|
||||||
|
const pluginData = new Map();
|
||||||
const commands = new Map();
|
const commands = new Map();
|
||||||
const eventHandlers = new Map();
|
const eventHandlers = new Map();
|
||||||
const files = new Map();
|
const files = new Map();
|
||||||
|
|
@ -117,6 +118,14 @@ export function createMockPluginAPI(pluginId = 'test.plugin', options = {}) {
|
||||||
Object.assign(settings, nextSettings);
|
Object.assign(settings, nextSettings);
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
storage: {
|
||||||
|
data: {
|
||||||
|
read: vi.fn(async (name) => ({ ...(pluginData.get(name) || {}) })),
|
||||||
|
write: vi.fn(async (name, data) => {
|
||||||
|
pluginData.set(name, { ...(data || {}) });
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
capabilities: {
|
capabilities: {
|
||||||
has: vi.fn(async () => false),
|
has: vi.fn(async () => false),
|
||||||
get: vi.fn(async (name) => ({ available: false, name })),
|
get: vi.fn(async (name) => ({ available: false, name })),
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -12,6 +12,8 @@ describe('VerstakPluginAPI contract', () => {
|
||||||
expect(api.pluginId).toBe('verstak.platform-test');
|
expect(api.pluginId).toBe('verstak.platform-test');
|
||||||
expect(typeof api.settings.read).toBe('function');
|
expect(typeof api.settings.read).toBe('function');
|
||||||
expect(typeof api.settings.write).toBe('function');
|
expect(typeof api.settings.write).toBe('function');
|
||||||
|
expect(typeof api.storage.data.read).toBe('function');
|
||||||
|
expect(typeof api.storage.data.write).toBe('function');
|
||||||
expect(typeof api.capabilities.list).toBe('function');
|
expect(typeof api.capabilities.list).toBe('function');
|
||||||
expect(typeof api.commands.register).toBe('function');
|
expect(typeof api.commands.register).toBe('function');
|
||||||
expect(typeof api.commands.execute).toBe('function');
|
expect(typeof api.commands.execute).toBe('function');
|
||||||
|
|
@ -190,6 +192,25 @@ describe('VerstakPluginAPI contract', () => {
|
||||||
await expect(api.settings.read()).resolves.toEqual({ savedText: 'hello' });
|
await expect(api.settings.read()).resolves.toEqual({ savedText: 'hello' });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('plugin data persists separately from settings in the mock API namespace', async () => {
|
||||||
|
const api = createMockPluginAPI('storage.plugin');
|
||||||
|
|
||||||
|
await api.settings.write('search-index', { source: 'settings' });
|
||||||
|
await api.storage.data.write('search-index', {
|
||||||
|
version: 1,
|
||||||
|
workspaceRootPath: 'Project',
|
||||||
|
entries: [{ path: 'Project/Docs/case.md' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(api.storage.data.read('search-index')).resolves.toEqual({
|
||||||
|
version: 1,
|
||||||
|
workspaceRootPath: 'Project',
|
||||||
|
entries: [{ path: 'Project/Docs/case.md' }],
|
||||||
|
});
|
||||||
|
await expect(api.settings.read('search-index')).resolves.toEqual({ source: 'settings' });
|
||||||
|
await expect(api.storage.data.read('missing')).resolves.toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
test('commands register, execute, and unregister', async () => {
|
test('commands register, execute, and unregister', async () => {
|
||||||
const api = createMockPluginAPI('cmd.plugin');
|
const api = createMockPluginAPI('cmd.plugin');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import type {
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
export type PluginCommandArgs = Record<string, unknown>;
|
export type PluginCommandArgs = Record<string, unknown>;
|
||||||
|
export type PluginDataJSON = Record<string, unknown>;
|
||||||
export type PluginCommandHandler = (
|
export type PluginCommandHandler = (
|
||||||
args: PluginCommandArgs,
|
args: PluginCommandArgs,
|
||||||
declaration: PluginCommandDeclaration
|
declaration: PluginCommandDeclaration
|
||||||
|
|
@ -96,6 +97,13 @@ export interface VerstakPluginAPI {
|
||||||
writeAll(settings: PluginSettings): Promise<void>;
|
writeAll(settings: PluginSettings): Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
storage: {
|
||||||
|
data: {
|
||||||
|
read(name: string): Promise<PluginDataJSON>;
|
||||||
|
write(name: string, data: PluginDataJSON): Promise<void>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
capabilities: {
|
capabilities: {
|
||||||
has(capability: string): Promise<boolean>;
|
has(capability: string): Promise<boolean>;
|
||||||
get(capability: string): Promise<{ available: boolean; name?: string; pluginId?: string; status?: string }>;
|
get(capability: string): Promise<{ available: boolean; name?: string; pluginId?: string; status?: string }>;
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ export function createTestPluginState(overrides?: Partial<PluginState>): PluginS
|
||||||
*/
|
*/
|
||||||
export function createMockPluginAPI(pluginId = 'test.plugin', options: MockPluginAPIOptions = {}): VerstakPluginAPI {
|
export function createMockPluginAPI(pluginId = 'test.plugin', options: MockPluginAPIOptions = {}): VerstakPluginAPI {
|
||||||
const settings: Record<string, unknown> = {};
|
const settings: Record<string, unknown> = {};
|
||||||
|
const pluginData = new Map<string, Record<string, unknown>>();
|
||||||
const commands = new Map<string, PluginCommandHandler>();
|
const commands = new Map<string, PluginCommandHandler>();
|
||||||
const eventHandlers = new Map<string, Array<(event: any) => void>>();
|
const eventHandlers = new Map<string, Array<(event: any) => void>>();
|
||||||
const files = new Map<string, { type: 'file' | 'folder'; content?: string; modifiedAt: string }>();
|
const files = new Map<string, { type: 'file' | 'folder'; content?: string; modifiedAt: string }>();
|
||||||
|
|
@ -129,6 +130,14 @@ export function createMockPluginAPI(pluginId = 'test.plugin', options: MockPlugi
|
||||||
Object.assign(settings, nextSettings);
|
Object.assign(settings, nextSettings);
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
storage: {
|
||||||
|
data: {
|
||||||
|
read: vi.fn(async (name: string) => ({ ...(pluginData.get(name) || {}) })),
|
||||||
|
write: vi.fn(async (name: string, data: Record<string, unknown>) => {
|
||||||
|
pluginData.set(name, { ...(data || {}) });
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
capabilities: {
|
capabilities: {
|
||||||
has: vi.fn(async () => false),
|
has: vi.fn(async () => false),
|
||||||
get: vi.fn(async (name: string) => ({ available: false, name })),
|
get: vi.fn(async (name: string) => ({ available: false, name })),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue