@phoundry/phials-plugin-sdk 1.0.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/LICENSE +21 -0
- package/README.md +3 -0
- package/command-types.generated.d.ts +288 -0
- package/events-types.generated.d.ts +195 -0
- package/file-types.generated.d.ts +239 -0
- package/manifest-schema.js +307 -0
- package/manifest-schema.ts +403 -0
- package/module-types.generated.d.ts +41 -0
- package/package.json +25 -0
- package/pane-context.generated.d.ts +71 -0
- package/phials-plugin-sdk.d.ts +11 -0
- package/plugin-types.generated.d.ts +1165 -0
- package/public-contract.generated.d.ts +329 -0
- package/shortcuts-types.generated.d.ts +113 -0
|
@@ -0,0 +1,1165 @@
|
|
|
1
|
+
// @generated from phials - do not edit
|
|
2
|
+
// Source graph: phials/scripts/lib/public-sdk-manifest.mjs
|
|
3
|
+
|
|
4
|
+
/// <reference path="./pane-context.generated.d.ts" />
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Plugin System Type Definitions
|
|
8
|
+
*
|
|
9
|
+
* Defines interfaces for the plugin architecture including:
|
|
10
|
+
* - Plugin container and registration
|
|
11
|
+
* - All provider types (Preview, Metadata, View, Module, Command)
|
|
12
|
+
* - Scoped API interfaces
|
|
13
|
+
* - Settings schema types
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// ─── Plugin Container ────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Props passed to a plugin's custom settings component in Settings → Plugins.
|
|
20
|
+
*/
|
|
21
|
+
interface PluginSettingsComponentProps {
|
|
22
|
+
plugin: PhialsPlugin;
|
|
23
|
+
/** The same reactive settings object supplied through `PluginAPI.settings`. */
|
|
24
|
+
settings: PluginSettings;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A plugin is a container that can provide one or more providers.
|
|
29
|
+
* Each provider type has its own interface and registration mechanism.
|
|
30
|
+
*/
|
|
31
|
+
interface PhialsPlugin {
|
|
32
|
+
/** Unique plugin identifier (e.g., 'phials.terminal', 'vendor.preview-pdf') */
|
|
33
|
+
id: string;
|
|
34
|
+
|
|
35
|
+
/** Human-readable name */
|
|
36
|
+
name: string;
|
|
37
|
+
|
|
38
|
+
/** Plugin version (semver) */
|
|
39
|
+
version: string;
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
/** Settings schema contributed by this plugin */
|
|
43
|
+
settings?: PluginSettingsSchema;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Custom settings UI for Settings → Plugins.
|
|
47
|
+
* When set, replaces the generic field loop; `settings` still supplies defaults and reset.
|
|
48
|
+
*/
|
|
49
|
+
settingsComponent?: import("svelte").Component<PluginSettingsComponentProps>;
|
|
50
|
+
|
|
51
|
+
/** Database schema for plugin-owned SQL tables */
|
|
52
|
+
database?: PluginDatabaseSchema;
|
|
53
|
+
|
|
54
|
+
/** Called when the plugin is activated */
|
|
55
|
+
onActivate?: (api: PluginAPI) => void | Promise<void>;
|
|
56
|
+
|
|
57
|
+
/** Called when the plugin is deactivated */
|
|
58
|
+
onDeactivate?: () => void | Promise<void>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Called before the plugin is reloaded.
|
|
62
|
+
* Return any state that should be preserved across the reload.
|
|
63
|
+
*/
|
|
64
|
+
onBeforeReload?: () => unknown | Promise<unknown>;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Called after the plugin is reloaded.
|
|
68
|
+
* Receives the state that was returned from onBeforeReload.
|
|
69
|
+
*/
|
|
70
|
+
onAfterReload?: (state: unknown) => void | Promise<void>;
|
|
71
|
+
|
|
72
|
+
/** Providers contributed by this plugin */
|
|
73
|
+
providers: PluginProvider[];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Svelte runtime re-exported from a community plugin bundle (`main.js`).
|
|
79
|
+
* Required so host code mounts plugin components with the same runtime that compiled them.
|
|
80
|
+
*/
|
|
81
|
+
interface PluginSvelteRuntime {
|
|
82
|
+
mount: (
|
|
83
|
+
component: import("svelte").Component<Record<string, unknown>>,
|
|
84
|
+
options: {
|
|
85
|
+
target: Element | Document | ShadowRoot;
|
|
86
|
+
props?: Record<string, unknown>;
|
|
87
|
+
},
|
|
88
|
+
) => unknown;
|
|
89
|
+
unmount: (instance: unknown) => void;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ─── Provider Types ──────────────────────────────────────────────────────────
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Union type for all provider types
|
|
96
|
+
*/
|
|
97
|
+
type PluginProvider =
|
|
98
|
+
| PreviewProvider
|
|
99
|
+
| MetadataProvider
|
|
100
|
+
| FileBrowserViewProvider
|
|
101
|
+
| ModuleProvider
|
|
102
|
+
| CommandProvider;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Provider type discriminator
|
|
106
|
+
*/
|
|
107
|
+
type ProviderType = "preview" | "metadata" | "view" | "module" | "command";
|
|
108
|
+
|
|
109
|
+
// ─── Preview Provider ────────────────────────────────────────────────────────
|
|
110
|
+
|
|
111
|
+
type PreviewDestination = "module" | "gallery" | "page" | "embed";
|
|
112
|
+
|
|
113
|
+
/** Provider-owned state shared by every presentation of one file preview. */
|
|
114
|
+
interface PreviewSession {
|
|
115
|
+
/** Clean unreferenced sessions are disposed; unresolved work can retain itself. */
|
|
116
|
+
retainOnRelease?: () => boolean;
|
|
117
|
+
dispose?: () => void | Promise<void>;
|
|
118
|
+
/** Optional in-app path relocation hook. */
|
|
119
|
+
relocate?: (oldPath: string, newPath: string) => void | Promise<void>;
|
|
120
|
+
/** Standard editor state rendered by host preview toolbars. */
|
|
121
|
+
editor?: PreviewToolbarEditorState;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface PreviewSessionFactoryProps {
|
|
125
|
+
file: FileEntry;
|
|
126
|
+
api: PreviewAPI;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
interface PreviewSurfaceProps {
|
|
130
|
+
file: FileEntry;
|
|
131
|
+
api: PreviewAPI;
|
|
132
|
+
session?: PreviewSession;
|
|
133
|
+
/** Host destination; `embed` requires inspection-only behavior. */
|
|
134
|
+
destination?: PreviewDestination;
|
|
135
|
+
/** One-shot focus request; does not describe the host destination. */
|
|
136
|
+
focusEditor?: boolean;
|
|
137
|
+
onConsumeFocusEditor?: () => void;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
interface PreviewToolbarContributionProps {
|
|
141
|
+
file: FileEntry;
|
|
142
|
+
api: PreviewAPI;
|
|
143
|
+
session?: PreviewSession;
|
|
144
|
+
destination: PreviewDestination;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
interface PreviewDestinationCapabilities {
|
|
148
|
+
/** Surface may populate File mode in the universal Page tab. */
|
|
149
|
+
pageTab?: boolean;
|
|
150
|
+
/** Surface is safe to mount inspection-only inside Markdown. */
|
|
151
|
+
embed?: boolean;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Props passed to thumbnail components
|
|
156
|
+
*/
|
|
157
|
+
interface ThumbnailProviderProps {
|
|
158
|
+
file: FileEntry;
|
|
159
|
+
api: PreviewAPI;
|
|
160
|
+
size: number;
|
|
161
|
+
generatedSize?: number;
|
|
162
|
+
quality?: number;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Preview toolbar surface - sidebar embed vs PageTab / gallery fullscreen stage.
|
|
167
|
+
*/
|
|
168
|
+
type PreviewToolbarSurface = "sidebar" | "fullscreen";
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* In-session undo/redo surface for preview editor toolbars and code/markdown editors.
|
|
172
|
+
*/
|
|
173
|
+
interface EditorHistoryHandle {
|
|
174
|
+
undo: () => boolean;
|
|
175
|
+
redo: () => boolean;
|
|
176
|
+
canUndo: boolean;
|
|
177
|
+
canRedo: boolean;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
interface PhormatEditorEmbedderHandle {
|
|
181
|
+
prepareForSave(): string;
|
|
182
|
+
hasActiveDraft(): boolean;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** Editor state exposed by a file viewing and editing capability. */
|
|
186
|
+
interface PreviewToolbarEditorState {
|
|
187
|
+
isDirty: boolean;
|
|
188
|
+
/** Hide explicit persistence chrome while retaining history controls. */
|
|
189
|
+
autosave?: boolean;
|
|
190
|
+
saving?: boolean;
|
|
191
|
+
onSave: () => void | Promise<void>;
|
|
192
|
+
/** Await autosave finalization before replacing the current document. */
|
|
193
|
+
onFinalize?: () => Promise<boolean>;
|
|
194
|
+
onRevert?: () => void;
|
|
195
|
+
history?: EditorHistoryHandle;
|
|
196
|
+
saveLabel?: string;
|
|
197
|
+
saveSavingLabel?: string;
|
|
198
|
+
revertLabel?: string;
|
|
199
|
+
revertTitle?: string;
|
|
200
|
+
revertIcon?: string | null;
|
|
201
|
+
/** When false, Revert/Cancel stays enabled while clean (e.g. exit edit mode). Default true. */
|
|
202
|
+
revertRequiresDirty?: boolean;
|
|
203
|
+
dirtyLabel?: string;
|
|
204
|
+
showDirtyIndicator?: boolean;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Preview provider - renders file previews, thumbnails, and fullscreen views
|
|
209
|
+
*/
|
|
210
|
+
interface PreviewProvider {
|
|
211
|
+
type: "preview";
|
|
212
|
+
id: string;
|
|
213
|
+
name: string;
|
|
214
|
+
priority?: number;
|
|
215
|
+
|
|
216
|
+
/** File matching criteria */
|
|
217
|
+
extensions?: string[];
|
|
218
|
+
mimeTypes?: string[];
|
|
219
|
+
categories?: FileCategory[];
|
|
220
|
+
canHandle?: (file: FileEntry, api: FileMatchAPI) => boolean;
|
|
221
|
+
|
|
222
|
+
/** Components */
|
|
223
|
+
thumbnail?: import("svelte").Component<ThumbnailProviderProps>;
|
|
224
|
+
/** Responsive file-specific viewer/editor used by every host destination. */
|
|
225
|
+
surface?: import("svelte").Component<PreviewSurfaceProps>;
|
|
226
|
+
createSession?: (
|
|
227
|
+
props: PreviewSessionFactoryProps,
|
|
228
|
+
) => PreviewSession | Promise<PreviewSession>;
|
|
229
|
+
/** Single reactive provider control group mounted at the host toolbar's trailing edge. */
|
|
230
|
+
toolbar?: import("svelte").Component<PreviewToolbarContributionProps>;
|
|
231
|
+
destinations?: PreviewDestinationCapabilities;
|
|
232
|
+
|
|
233
|
+
/** Behavior */
|
|
234
|
+
overridesDoubleClick?: boolean;
|
|
235
|
+
/** Preview can modify file contents; the host exposes editor chrome only when this returns true. */
|
|
236
|
+
isEditable?: (file: FileEntry, metadata?: FileMetadata) => boolean;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// ─── Item Shortcuts ──────────────────────────────────────────────────────────
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Shortcut configuration for module providers and other item-level shortcuts.
|
|
243
|
+
* When defined on a module, the shortcut is auto-registered with ShortcutManager.
|
|
244
|
+
*/
|
|
245
|
+
interface ItemShortcutConfig {
|
|
246
|
+
/** Default shortcuts (up to 3). Use ShortcutDefinition format. */
|
|
247
|
+
defaults?: ShortcutDefinition[];
|
|
248
|
+
/** Description shown in shortcuts settings */
|
|
249
|
+
description?: string;
|
|
250
|
+
/** If true, don't call preventDefault() after handling */
|
|
251
|
+
allowDefault?: boolean;
|
|
252
|
+
/** Priority for conflict resolution (higher = checked first) */
|
|
253
|
+
priority?: number;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// ─── Metadata Provider ───────────────────────────────────────────────────────
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Raw metadata from filesystem/backend
|
|
260
|
+
*/
|
|
261
|
+
interface RawMetadata {
|
|
262
|
+
[key: string]: string;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Extracted/processed metadata from a provider
|
|
267
|
+
*/
|
|
268
|
+
interface ExtractedMetadata {
|
|
269
|
+
[key: string]: unknown;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* File metadata combining raw and extracted data
|
|
274
|
+
*/
|
|
275
|
+
interface FileMetadata {
|
|
276
|
+
raw: RawMetadata;
|
|
277
|
+
extracted: ExtractedMetadata;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Schema field for metadata display
|
|
282
|
+
*/
|
|
283
|
+
interface MetadataSchemaField {
|
|
284
|
+
key: string;
|
|
285
|
+
label: string;
|
|
286
|
+
type: "string" | "number" | "date" | "boolean" | "array" | "dynamic-enum";
|
|
287
|
+
/**
|
|
288
|
+
* Optional hint for how extracted values should be presented in schema-driven UI
|
|
289
|
+
* (Details columns, preview Metadata, thumbnail captions), paired with `type`.
|
|
290
|
+
* v1 implements `"html"` only (sanitized render from `key`); requires `rawKey`.
|
|
291
|
+
* On formatted fields, `type` describes the raw value semantics for sort/filter.
|
|
292
|
+
*/
|
|
293
|
+
format?: "html";
|
|
294
|
+
/**
|
|
295
|
+
* Extracted key for sort, filter, and logic (not a separate schema row).
|
|
296
|
+
* Required when `format: "html"`.
|
|
297
|
+
*/
|
|
298
|
+
rawKey?: string;
|
|
299
|
+
/** Optional Iconify id for column header / property list chrome */
|
|
300
|
+
icon?: string;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Schema for metadata UI rendering
|
|
305
|
+
*/
|
|
306
|
+
interface MetadataSchema {
|
|
307
|
+
fields: MetadataSchemaField[];
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Policy for how a metadata provider contributes Details view columns.
|
|
312
|
+
*/
|
|
313
|
+
interface MetadataColumnPolicy {
|
|
314
|
+
/** Whether this provider contributes fields to the Details column menu. Default true when schema exists. */
|
|
315
|
+
showInColumnMenu?: boolean;
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* If set, only these schema keys appear in the Details column menu (and auto-visible
|
|
319
|
+
* picks from this set). Omit for all schema fields. An empty array excludes the provider
|
|
320
|
+
* from column contributions. Does not override `showInColumnMenu` when that is false.
|
|
321
|
+
*/
|
|
322
|
+
columnWhitelist?: string[];
|
|
323
|
+
|
|
324
|
+
/** Whether columns can be auto-shown from file matching alone. Default "when-dominant". */
|
|
325
|
+
autoVisible?: "never" | "when-any" | "when-dominant";
|
|
326
|
+
|
|
327
|
+
/** Fields to show automatically when the provider qualifies. Defaults to the first few schema fields. */
|
|
328
|
+
defaultVisibleFields?: string[];
|
|
329
|
+
|
|
330
|
+
/** Exclude this provider from dominance ratios. Useful for global/base providers. */
|
|
331
|
+
excludeFromDominance?: boolean;
|
|
332
|
+
|
|
333
|
+
/** Matching by extension/category is not enough; values may require sampling. */
|
|
334
|
+
requiresValueSampling?: boolean;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Metadata provider - extracts structured metadata from files
|
|
339
|
+
*/
|
|
340
|
+
interface MetadataProvider {
|
|
341
|
+
type: "metadata";
|
|
342
|
+
id: string;
|
|
343
|
+
name: string;
|
|
344
|
+
/**
|
|
345
|
+
* Precedence when multiple providers match the same file (default 0).
|
|
346
|
+
* Higher values sort first in registry lookups and extraction order; also
|
|
347
|
+
* breaks ties for directory metadata profiles and auto-visible Details columns.
|
|
348
|
+
*/
|
|
349
|
+
priority?: number;
|
|
350
|
+
|
|
351
|
+
/** File matching criteria */
|
|
352
|
+
extensions?: string[];
|
|
353
|
+
mimeTypes?: string[];
|
|
354
|
+
categories?: FileCategory[];
|
|
355
|
+
canHandle?: (file: FileEntry) => boolean;
|
|
356
|
+
|
|
357
|
+
/** Extract metadata from file */
|
|
358
|
+
extract: (
|
|
359
|
+
file: FileEntry,
|
|
360
|
+
rawMeta: RawMetadata,
|
|
361
|
+
api: MetadataAPI,
|
|
362
|
+
) => Promise<ExtractedMetadata> | ExtractedMetadata;
|
|
363
|
+
|
|
364
|
+
/** Schema for extracted metadata (for UI rendering) */
|
|
365
|
+
schema?: MetadataSchema;
|
|
366
|
+
|
|
367
|
+
/** How this provider appears in Details column picker and auto-visible heuristics */
|
|
368
|
+
columnPolicy?: MetadataColumnPolicy;
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Optional override for filter dropdown options on `dynamic-enum` schema fields.
|
|
372
|
+
* When absent or empty, Phials falls back to distinct-value scan over the listing.
|
|
373
|
+
*/
|
|
374
|
+
getFilterValueOptions?: (
|
|
375
|
+
fieldKey: string,
|
|
376
|
+
api: MetadataAPI,
|
|
377
|
+
) => FilterValueOption[] | Promise<FilterValueOption[]>;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/** Runtime filter dropdown entry from a metadata provider hook */
|
|
381
|
+
interface FilterValueOption {
|
|
382
|
+
value: string;
|
|
383
|
+
label?: string;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Options for computing a directory metadata profile (cheap matching only).
|
|
388
|
+
*/
|
|
389
|
+
interface DirectoryMetadataProfileOptions {
|
|
390
|
+
/** Directory path this profile describes (for diagnostics / persistence). */
|
|
391
|
+
path?: string;
|
|
392
|
+
/** Cap files scanned; default 1000. Uses the first N files after filtering. */
|
|
393
|
+
maxSample?: number;
|
|
394
|
+
/** Minimum share of sampled files that must match a provider for `dominant`; default 0.9. */
|
|
395
|
+
dominanceThreshold?: number;
|
|
396
|
+
/** Minimum total file count in the directory before any provider can be `dominant`; default 5. */
|
|
397
|
+
minFilesForDominance?: number;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Per-provider stats from scanning directory file entries (no metadata extraction).
|
|
402
|
+
*/
|
|
403
|
+
interface MetadataProviderDirectoryStats {
|
|
404
|
+
providerId: string;
|
|
405
|
+
matchedFiles: number;
|
|
406
|
+
ratio: number;
|
|
407
|
+
fields: MetadataSchemaField[];
|
|
408
|
+
dominant: boolean;
|
|
409
|
+
/** Number of matched files inspected for sparse extracted values. */
|
|
410
|
+
valueSampledFiles?: number;
|
|
411
|
+
/** Number of inspected files containing at least one eligible value. */
|
|
412
|
+
valueMatchedFiles?: number;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Aggregated column-relevant metadata coverage for a directory listing.
|
|
417
|
+
*/
|
|
418
|
+
interface DirectoryMetadataProfile {
|
|
419
|
+
path: string;
|
|
420
|
+
fileCount: number;
|
|
421
|
+
sampledCount: number;
|
|
422
|
+
providers: MetadataProviderDirectoryStats[];
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// ─── Toolbar Context (Command Path Bar) ─────────────────────────────────────
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Props passed to toolbar sub-toolbar components
|
|
429
|
+
*/
|
|
430
|
+
interface ToolbarSubToolbarProps {
|
|
431
|
+
ctx: ToolbarContext;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Context passed to toolbar button callbacks and sub-toolbar components
|
|
436
|
+
*/
|
|
437
|
+
interface ToolbarContext {
|
|
438
|
+
pane: PluginPaneContext;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// ─── File Browser View Provider ──────────────────────────────────────────────
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Props passed to file browser view components
|
|
445
|
+
*/
|
|
446
|
+
interface FileBrowserViewProps {
|
|
447
|
+
pane: PluginPaneContext;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Row / cell size tier for view default item size (maps to slider ticks per view family).
|
|
452
|
+
*/
|
|
453
|
+
type ViewItemSizePreset = "xs" | "sm" | "md" | "lg";
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Column definition for views that support columns
|
|
457
|
+
*/
|
|
458
|
+
interface ViewColumnDefinition {
|
|
459
|
+
id: string;
|
|
460
|
+
label: string;
|
|
461
|
+
width: number;
|
|
462
|
+
minWidth?: number;
|
|
463
|
+
sortable?: boolean;
|
|
464
|
+
getValue: (file: FileEntry) => string | number | null;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* File browser view provider - provides custom view modes
|
|
469
|
+
*/
|
|
470
|
+
interface FileBrowserViewProvider {
|
|
471
|
+
type: "view";
|
|
472
|
+
id: string;
|
|
473
|
+
name: string;
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Sort order when listing views (lower appears first).
|
|
477
|
+
* Built-in views use 1–6; extension views should use higher numbers.
|
|
478
|
+
*/
|
|
479
|
+
priority: number;
|
|
480
|
+
|
|
481
|
+
/** Icon for view switcher */
|
|
482
|
+
icon: string;
|
|
483
|
+
|
|
484
|
+
/** View component */
|
|
485
|
+
component: import("svelte").Component<FileBrowserViewProps>;
|
|
486
|
+
|
|
487
|
+
/** Optional: custom column configuration for this view */
|
|
488
|
+
columns?: ViewColumnDefinition[];
|
|
489
|
+
|
|
490
|
+
/** If true, this view is only available in collections (vials) */
|
|
491
|
+
collectionOnly?: boolean;
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Default item size when a folder has no per-folder override (`itemSize` null).
|
|
495
|
+
* Details family uses row-height ticks; thumbnails / gallery use grid ticks;
|
|
496
|
+
* Boards uses its column-width ticks.
|
|
497
|
+
*/
|
|
498
|
+
defaultItemSizePreset?: ViewItemSizePreset;
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Optional inline view configuration items (phoundry-ui menu row contract).
|
|
502
|
+
* `api` is scoped to the plugin that registered this view.
|
|
503
|
+
*/
|
|
504
|
+
getConfigurationItems?: (
|
|
505
|
+
pane: PluginPaneContext,
|
|
506
|
+
api: ViewAPI,
|
|
507
|
+
) => import("phoundry-ui").MenuItem[];
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// ─── Module Provider ──────────────────────────────────────────────────────────
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Props passed to module components
|
|
514
|
+
*/
|
|
515
|
+
interface ModuleProviderProps {
|
|
516
|
+
/** The pane context (for pane-scoped modules) */
|
|
517
|
+
pane?: PluginPaneContext;
|
|
518
|
+
|
|
519
|
+
/** The module instance configuration */
|
|
520
|
+
moduleInstance: ModuleInstance;
|
|
521
|
+
|
|
522
|
+
/** Replace this instance's opaque state and schedule center-session persistence. */
|
|
523
|
+
updateState(state: unknown): void;
|
|
524
|
+
|
|
525
|
+
/** Request that the host close this module instance. */
|
|
526
|
+
close(): Promise<void>;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Module provider - provides a UI module for panels and center tab groups
|
|
531
|
+
*
|
|
532
|
+
* Modules are self-contained UI components like Navigator, File Preview,
|
|
533
|
+
* or Terminal that can be arranged in panel tabs or modular center groups.
|
|
534
|
+
*/
|
|
535
|
+
interface ModuleProvider {
|
|
536
|
+
type: "module";
|
|
537
|
+
|
|
538
|
+
/** Unique module identifier (e.g., 'phials.module.navigator') */
|
|
539
|
+
id: string;
|
|
540
|
+
|
|
541
|
+
/** Human-readable name for display */
|
|
542
|
+
name: string;
|
|
543
|
+
|
|
544
|
+
/** Icon for tabs and headers */
|
|
545
|
+
icon: string;
|
|
546
|
+
|
|
547
|
+
/** Positions where this module can be placed (default: all panels, not center) */
|
|
548
|
+
allowedPositions?: ModulePosition[];
|
|
549
|
+
|
|
550
|
+
/** Default position for new instances */
|
|
551
|
+
defaultPosition?: ModulePosition;
|
|
552
|
+
|
|
553
|
+
/** The module component */
|
|
554
|
+
component: import("svelte").Component<ModuleProviderProps>;
|
|
555
|
+
|
|
556
|
+
/** Whether multiple instances of this module are allowed (default: false) */
|
|
557
|
+
allowMultiple?: boolean;
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* If true, the center host fully remounts the component when the remount key
|
|
561
|
+
* changes: `getCenterTabIdentity(state)` when defined, otherwise the module
|
|
562
|
+
* instance id. Needed for lifecycle-heavy modules (Terminal, Page, Preview)
|
|
563
|
+
* so **center tab replacement** reloads content when only state changes.
|
|
564
|
+
* Default: false.
|
|
565
|
+
*/
|
|
566
|
+
requiresRemount?: boolean;
|
|
567
|
+
|
|
568
|
+
/** Default state for new module instances */
|
|
569
|
+
getDefaultState?: () => unknown;
|
|
570
|
+
|
|
571
|
+
/** Keyboard shortcut to toggle/focus this module */
|
|
572
|
+
shortcut?: ItemShortcutConfig;
|
|
573
|
+
|
|
574
|
+
/** Dynamic tab title when rendered in center (falls back to `name`) */
|
|
575
|
+
getTabTitle?: (state?: unknown) => string;
|
|
576
|
+
|
|
577
|
+
/** Dynamic tab icon when rendered in center (falls back to `icon`) */
|
|
578
|
+
getTabIcon?: (state?: unknown) => string;
|
|
579
|
+
|
|
580
|
+
/** Stable content identity used to focus an equivalent center tab before creating one. */
|
|
581
|
+
getCenterTabIdentity?: (state?: unknown) => string | undefined;
|
|
582
|
+
|
|
583
|
+
/** Opt in to same-type replacement of an active, unpinned center tab. */
|
|
584
|
+
canReplaceCenterTab?: (
|
|
585
|
+
currentState: unknown,
|
|
586
|
+
requestedState: unknown,
|
|
587
|
+
) => boolean;
|
|
588
|
+
|
|
589
|
+
/** Finalize or refuse unresolved state before close or center-tab replacement. */
|
|
590
|
+
finalizeCenterTab?: (moduleInstance: ModuleInstance) => Promise<boolean>;
|
|
591
|
+
|
|
592
|
+
/** Optional panel module tab bar menu items (phoundry-ui context menu rows). */
|
|
593
|
+
getTabBarMenuItems?: (
|
|
594
|
+
moduleInstance: ModuleInstance,
|
|
595
|
+
api: ModuleAPI,
|
|
596
|
+
) => import("phoundry-ui").MenuItem[];
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// ─── Plugin Settings ─────────────────────────────────────────────────────────
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Settings field types
|
|
603
|
+
*/
|
|
604
|
+
type SettingsFieldType = "boolean" | "string" | "number" | "select" | "path";
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Base settings field
|
|
608
|
+
*/
|
|
609
|
+
interface SettingsFieldBase {
|
|
610
|
+
key: string;
|
|
611
|
+
label: string;
|
|
612
|
+
description?: string;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Boolean settings field
|
|
617
|
+
*/
|
|
618
|
+
interface BooleanSettingsField extends SettingsFieldBase {
|
|
619
|
+
type: "boolean";
|
|
620
|
+
default: boolean;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* String settings field
|
|
625
|
+
*/
|
|
626
|
+
interface StringSettingsField extends SettingsFieldBase {
|
|
627
|
+
type: "string";
|
|
628
|
+
default: string;
|
|
629
|
+
placeholder?: string;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Number settings field
|
|
634
|
+
*/
|
|
635
|
+
interface NumberSettingsField extends SettingsFieldBase {
|
|
636
|
+
type: "number";
|
|
637
|
+
default: number;
|
|
638
|
+
min?: number;
|
|
639
|
+
max?: number;
|
|
640
|
+
step?: number;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Select settings field
|
|
645
|
+
*/
|
|
646
|
+
interface SelectSettingsField extends SettingsFieldBase {
|
|
647
|
+
type: "select";
|
|
648
|
+
options: { value: string; label: string }[];
|
|
649
|
+
default: string;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Path settings field
|
|
654
|
+
*/
|
|
655
|
+
interface PathSettingsField extends SettingsFieldBase {
|
|
656
|
+
type: "path";
|
|
657
|
+
default: string;
|
|
658
|
+
directory?: boolean;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Union of all settings field types
|
|
663
|
+
*/
|
|
664
|
+
type SettingsField =
|
|
665
|
+
| BooleanSettingsField
|
|
666
|
+
| StringSettingsField
|
|
667
|
+
| NumberSettingsField
|
|
668
|
+
| SelectSettingsField
|
|
669
|
+
| PathSettingsField;
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Plugin settings schema
|
|
673
|
+
*/
|
|
674
|
+
interface PluginSettingsSchema {
|
|
675
|
+
/** Settings section title */
|
|
676
|
+
title: string;
|
|
677
|
+
|
|
678
|
+
/** Settings fields */
|
|
679
|
+
fields: SettingsField[];
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// ─── Plugin Database Schema ──────────────────────────────────────────────────
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* SQLite column types supported for plugin tables
|
|
686
|
+
*/
|
|
687
|
+
type PluginColumnType = "TEXT" | "INTEGER" | "REAL" | "BLOB";
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* Column definition for a plugin database table
|
|
691
|
+
*/
|
|
692
|
+
interface PluginColumnDefinition {
|
|
693
|
+
/** Column name */
|
|
694
|
+
name: string;
|
|
695
|
+
|
|
696
|
+
/** SQLite data type */
|
|
697
|
+
type: PluginColumnType;
|
|
698
|
+
|
|
699
|
+
/** Whether this column is the primary key */
|
|
700
|
+
primaryKey?: boolean;
|
|
701
|
+
|
|
702
|
+
/** Whether this column auto-increments (only for INTEGER PRIMARY KEY) */
|
|
703
|
+
autoIncrement?: boolean;
|
|
704
|
+
|
|
705
|
+
/** Whether NULL values are disallowed */
|
|
706
|
+
notNull?: boolean;
|
|
707
|
+
|
|
708
|
+
/** Whether values must be unique */
|
|
709
|
+
unique?: boolean;
|
|
710
|
+
|
|
711
|
+
/** Default value for the column */
|
|
712
|
+
default?: unknown;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* Index definition for a plugin database table
|
|
717
|
+
*/
|
|
718
|
+
interface PluginIndexDefinition {
|
|
719
|
+
/** Index name (will be prefixed with table name) */
|
|
720
|
+
name: string;
|
|
721
|
+
|
|
722
|
+
/** Columns to index */
|
|
723
|
+
columns: string[];
|
|
724
|
+
|
|
725
|
+
/** Whether this is a unique index */
|
|
726
|
+
unique?: boolean;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Table definition for a plugin database
|
|
731
|
+
*/
|
|
732
|
+
interface PluginTableDefinition {
|
|
733
|
+
/** Table name (will be prefixed with plugin ID) */
|
|
734
|
+
name: string;
|
|
735
|
+
|
|
736
|
+
/** Column definitions */
|
|
737
|
+
columns: PluginColumnDefinition[];
|
|
738
|
+
|
|
739
|
+
/** Optional index definitions */
|
|
740
|
+
indexes?: PluginIndexDefinition[];
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* Database schema for a plugin
|
|
745
|
+
*/
|
|
746
|
+
interface PluginDatabaseSchema {
|
|
747
|
+
/** Monotonic schema version. */
|
|
748
|
+
version: number;
|
|
749
|
+
|
|
750
|
+
/** Contiguous `N → N+1` migrations. */
|
|
751
|
+
migrations?: readonly PluginDatabaseMigration[];
|
|
752
|
+
|
|
753
|
+
/** Tables owned by this plugin */
|
|
754
|
+
tables: PluginTableDefinition[];
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// ─── Plugin Storage API ──────────────────────────────────────────────────────
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Key/value storage API for plugin data (separate from settings)
|
|
761
|
+
*/
|
|
762
|
+
interface PluginStorageAPI {
|
|
763
|
+
/** Get a value by key */
|
|
764
|
+
get<T>(key: string): Promise<T | null>;
|
|
765
|
+
|
|
766
|
+
/** Set a value by key */
|
|
767
|
+
set(key: string, value: unknown): Promise<void>;
|
|
768
|
+
|
|
769
|
+
/** Delete a value by key */
|
|
770
|
+
delete(key: string): Promise<void>;
|
|
771
|
+
|
|
772
|
+
/** Get all keys for this plugin */
|
|
773
|
+
keys(): Promise<string[]>;
|
|
774
|
+
|
|
775
|
+
/** Clear all data for this plugin */
|
|
776
|
+
clear(): Promise<void>;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// ─── Plugin Database API ─────────────────────────────────────────────────────
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* Result from an execute operation
|
|
783
|
+
*/
|
|
784
|
+
interface DatabaseExecuteResult {
|
|
785
|
+
/** Number of rows affected */
|
|
786
|
+
rowsAffected: number;
|
|
787
|
+
|
|
788
|
+
/** Last inserted row ID (if applicable) */
|
|
789
|
+
lastInsertId?: number;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* SQL database API for plugin-owned tables
|
|
794
|
+
*/
|
|
795
|
+
interface PluginDatabaseAPI {
|
|
796
|
+
/**
|
|
797
|
+
* Execute a raw SQL query and return results.
|
|
798
|
+
* Table names in the query should use the short name (without prefix).
|
|
799
|
+
* @param sql SQL query string with ? placeholders
|
|
800
|
+
* @param params Array of parameter values
|
|
801
|
+
*/
|
|
802
|
+
query<T = Record<string, unknown>>(
|
|
803
|
+
sql: string,
|
|
804
|
+
params?: unknown[],
|
|
805
|
+
): Promise<T[]>;
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Execute a SQL statement (INSERT, UPDATE, DELETE, etc.)
|
|
809
|
+
* @param sql SQL statement with ? placeholders
|
|
810
|
+
* @param params Array of parameter values
|
|
811
|
+
*/
|
|
812
|
+
execute(sql: string, params?: unknown[]): Promise<DatabaseExecuteResult>;
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Insert a row into a table
|
|
816
|
+
* @param table Table name (without prefix)
|
|
817
|
+
* @param data Object with column names as keys
|
|
818
|
+
* @returns The last inserted row ID
|
|
819
|
+
*/
|
|
820
|
+
insert(table: string, data: Record<string, unknown>): Promise<number>;
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Update rows in a table
|
|
824
|
+
* @param table Table name (without prefix)
|
|
825
|
+
* @param data Object with column names as keys
|
|
826
|
+
* @param where WHERE clause (without 'WHERE')
|
|
827
|
+
* @param params Parameters for the WHERE clause
|
|
828
|
+
* @returns Number of rows affected
|
|
829
|
+
*/
|
|
830
|
+
update(
|
|
831
|
+
table: string,
|
|
832
|
+
data: Record<string, unknown>,
|
|
833
|
+
where: string,
|
|
834
|
+
params?: unknown[],
|
|
835
|
+
): Promise<number>;
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Delete rows from a table
|
|
839
|
+
* @param table Table name (without prefix)
|
|
840
|
+
* @param where WHERE clause (without 'WHERE')
|
|
841
|
+
* @param params Parameters for the WHERE clause
|
|
842
|
+
* @returns Number of rows affected
|
|
843
|
+
*/
|
|
844
|
+
deleteFrom(
|
|
845
|
+
table: string,
|
|
846
|
+
where: string,
|
|
847
|
+
params?: unknown[],
|
|
848
|
+
): Promise<number>;
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* Select all rows from a table
|
|
852
|
+
* @param table Table name (without prefix)
|
|
853
|
+
* @param where Optional WHERE clause (without 'WHERE')
|
|
854
|
+
* @param params Parameters for the WHERE clause
|
|
855
|
+
*/
|
|
856
|
+
selectAll<T = Record<string, unknown>>(
|
|
857
|
+
table: string,
|
|
858
|
+
where?: string,
|
|
859
|
+
params?: unknown[],
|
|
860
|
+
): Promise<T[]>;
|
|
861
|
+
|
|
862
|
+
/** Run dependent operations in one plugin-scoped transaction. */
|
|
863
|
+
transaction<T>(
|
|
864
|
+
callback: (transaction: PluginDatabaseTransaction) => Promise<T>,
|
|
865
|
+
): Promise<T>;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// ─── Plugin APIs ─────────────────────────────────────────────────────────────
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* Read-only app settings proxy
|
|
872
|
+
*/
|
|
873
|
+
interface ReadonlyAppSettings {
|
|
874
|
+
readonly thumbnailsEnabled: boolean;
|
|
875
|
+
readonly thumbnailSize: number;
|
|
876
|
+
readonly thumbnailQuality: number;
|
|
877
|
+
readonly showHiddenFiles: boolean;
|
|
878
|
+
readonly showParentDirectory: boolean;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/**
|
|
882
|
+
* Plugin settings proxy for a specific plugin
|
|
883
|
+
*/
|
|
884
|
+
interface PluginSettings {
|
|
885
|
+
get<T>(key: string): T | undefined;
|
|
886
|
+
set(key: string, value: unknown): Promise<void>;
|
|
887
|
+
getAll(): Readonly<Record<string, unknown>>;
|
|
888
|
+
/** Read the unvalidated durable value for migration or recovery. */
|
|
889
|
+
getStored(key: string): unknown;
|
|
890
|
+
/** Remove one durable value and reveal the schema default. */
|
|
891
|
+
unset(key: string): Promise<void>;
|
|
892
|
+
/** Remove every durable value and reveal all schema defaults. */
|
|
893
|
+
reset(): Promise<void>;
|
|
894
|
+
onChange(
|
|
895
|
+
handler: (change: PluginSettingsChange) => void,
|
|
896
|
+
): PluginSettingsSubscription;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* Modal dialog API
|
|
901
|
+
*/
|
|
902
|
+
interface ModalAPI {
|
|
903
|
+
confirm(opts: {
|
|
904
|
+
title: string;
|
|
905
|
+
message: string;
|
|
906
|
+
confirmLabel?: string;
|
|
907
|
+
cancelLabel?: string;
|
|
908
|
+
danger?: boolean;
|
|
909
|
+
}): Promise<boolean>;
|
|
910
|
+
|
|
911
|
+
prompt(opts: {
|
|
912
|
+
title: string;
|
|
913
|
+
message: string;
|
|
914
|
+
defaultValue?: string;
|
|
915
|
+
placeholder?: string;
|
|
916
|
+
confirmLabel?: string;
|
|
917
|
+
cancelLabel?: string;
|
|
918
|
+
validate?: (
|
|
919
|
+
value: string,
|
|
920
|
+
) => string | null | undefined | Promise<string | null | undefined>;
|
|
921
|
+
}): Promise<string | null>;
|
|
922
|
+
|
|
923
|
+
alert(opts: { title: string; message: string }): Promise<void>;
|
|
924
|
+
|
|
925
|
+
choose<T extends string>(opts: {
|
|
926
|
+
title: string;
|
|
927
|
+
message: string;
|
|
928
|
+
choices: Array<{
|
|
929
|
+
id: T;
|
|
930
|
+
label: string;
|
|
931
|
+
description?: string;
|
|
932
|
+
variant?: "primary" | "secondary" | "danger";
|
|
933
|
+
}>;
|
|
934
|
+
cancelLabel?: string;
|
|
935
|
+
}): Promise<T | null>;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/**
|
|
939
|
+
* Notification/toast API
|
|
940
|
+
*/
|
|
941
|
+
interface NotificationOptions {
|
|
942
|
+
id?: string;
|
|
943
|
+
description?: string;
|
|
944
|
+
duration?: number;
|
|
945
|
+
dismissible?: boolean;
|
|
946
|
+
action?: {
|
|
947
|
+
label: string;
|
|
948
|
+
onAction: () => void | Promise<void>;
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
interface NotificationHandle {
|
|
953
|
+
readonly id: string;
|
|
954
|
+
dismiss(): void;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
interface NotifyAPI {
|
|
958
|
+
info(message: string, options?: NotificationOptions): NotificationHandle;
|
|
959
|
+
success(message: string, options?: NotificationOptions): NotificationHandle;
|
|
960
|
+
warning(message: string, options?: NotificationOptions): NotificationHandle;
|
|
961
|
+
error(message: string, options?: NotificationOptions): NotificationHandle;
|
|
962
|
+
dismiss(id: string): void;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* File utilities API
|
|
967
|
+
*/
|
|
968
|
+
interface FileUtilsAPI {
|
|
969
|
+
getExtension(filename: string): string;
|
|
970
|
+
getBasename(path: string): string;
|
|
971
|
+
getDirname(path: string): string;
|
|
972
|
+
joinPath(...parts: string[]): string;
|
|
973
|
+
pickDirectory(options?: {
|
|
974
|
+
title?: string;
|
|
975
|
+
initialPath?: string;
|
|
976
|
+
}): Promise<string | null>;
|
|
977
|
+
readDirectory(path: string): Promise<PluginDirectoryReadResult>;
|
|
978
|
+
readText(path: string): Promise<PluginTextFileSnapshot>;
|
|
979
|
+
writeText(
|
|
980
|
+
path: string,
|
|
981
|
+
content: string,
|
|
982
|
+
options: {
|
|
983
|
+
expectedRevision: string | null;
|
|
984
|
+
overwrite?: boolean;
|
|
985
|
+
},
|
|
986
|
+
): Promise<PluginTextWriteResult>;
|
|
987
|
+
createDirectory(path: string): Promise<void>;
|
|
988
|
+
renamePath(source: string, destination: string): Promise<void>;
|
|
989
|
+
trash(paths: readonly string[]): Promise<readonly PluginPathOutcome[]>;
|
|
990
|
+
revealPath(path: string): Promise<void>;
|
|
991
|
+
toAssetUrl(path: string): Promise<string>;
|
|
992
|
+
readBinary(path: string): Promise<PluginBinaryFileSnapshot>;
|
|
993
|
+
writeBinary(
|
|
994
|
+
path: string,
|
|
995
|
+
content: Uint8Array,
|
|
996
|
+
options: { expectedRevision: string | null; overwrite?: boolean },
|
|
997
|
+
): Promise<PluginBinaryWriteResult>;
|
|
998
|
+
getFolderSummary(
|
|
999
|
+
path: string,
|
|
1000
|
+
options?: { signal?: AbortSignal },
|
|
1001
|
+
): Promise<FolderSummary>;
|
|
1002
|
+
watchDirectory(
|
|
1003
|
+
path: string,
|
|
1004
|
+
handler: () => void,
|
|
1005
|
+
): Promise<PluginDirectoryWatch>;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
interface PluginTextFileSnapshot {
|
|
1009
|
+
content: string;
|
|
1010
|
+
revision: string;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
type PluginTextWriteResult =
|
|
1014
|
+
| { status: "saved"; revision: string }
|
|
1015
|
+
| { status: "conflict"; actualRevision: string | null };
|
|
1016
|
+
|
|
1017
|
+
interface PluginDirectoryWatch {
|
|
1018
|
+
unsubscribe(): void;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
interface ModulesAPI {
|
|
1023
|
+
openCenter(
|
|
1024
|
+
moduleProviderId: string,
|
|
1025
|
+
state: unknown,
|
|
1026
|
+
options?: { sourcePaneId?: string },
|
|
1027
|
+
): Promise<ModuleOpenResult>;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* File matching API for canHandle callbacks
|
|
1032
|
+
*/
|
|
1033
|
+
interface FileMatchAPI {
|
|
1034
|
+
matchesExtension(file: FileEntry, extensions: string[]): boolean;
|
|
1035
|
+
matchesMime(file: FileEntry, mimeTypes: string[]): boolean;
|
|
1036
|
+
matchesCategory(file: FileEntry, categories: FileCategory[]): boolean;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* Events API for pub/sub cross-plugin communication
|
|
1041
|
+
*/
|
|
1042
|
+
interface EventsAPI {
|
|
1043
|
+
/**
|
|
1044
|
+
* Subscribe to an event.
|
|
1045
|
+
* @param eventId - The event ID to subscribe to
|
|
1046
|
+
* @param handler - Callback invoked when event is emitted
|
|
1047
|
+
* @returns Subscription handle with unsubscribe() method
|
|
1048
|
+
*/
|
|
1049
|
+
on<K extends keyof EventMap>(
|
|
1050
|
+
eventId: K,
|
|
1051
|
+
handler: EventHandler<EventMap[K]>,
|
|
1052
|
+
): EventSubscription;
|
|
1053
|
+
|
|
1054
|
+
/**
|
|
1055
|
+
* Subscribe to an event once (auto-unsubscribes after first trigger).
|
|
1056
|
+
* @param eventId - The event ID to subscribe to
|
|
1057
|
+
* @param handler - Callback invoked when event is emitted
|
|
1058
|
+
* @returns Subscription handle with unsubscribe() method
|
|
1059
|
+
*/
|
|
1060
|
+
once<K extends keyof EventMap>(
|
|
1061
|
+
eventId: K,
|
|
1062
|
+
handler: EventHandler<EventMap[K]>,
|
|
1063
|
+
): EventSubscription;
|
|
1064
|
+
|
|
1065
|
+
/**
|
|
1066
|
+
* Emit an event to all subscribers.
|
|
1067
|
+
* @param eventId - The event ID to emit
|
|
1068
|
+
* @param payload - The event payload
|
|
1069
|
+
*/
|
|
1070
|
+
emit<K extends keyof EventMap>(eventId: K, payload: EventMap[K]): void;
|
|
1071
|
+
|
|
1072
|
+
/**
|
|
1073
|
+
* Register a new event type (namespaced to plugin).
|
|
1074
|
+
* The full event ID will be `{pluginId}.{localId}`.
|
|
1075
|
+
* @param localId - Local event name (without plugin prefix)
|
|
1076
|
+
* @param description - Optional description for docs/debugging
|
|
1077
|
+
*/
|
|
1078
|
+
register(localId: string, description?: string): void;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* Base Plugin API - available to all providers
|
|
1083
|
+
*/
|
|
1084
|
+
interface PluginAPI {
|
|
1085
|
+
/** Plugin's own settings */
|
|
1086
|
+
settings: PluginSettings;
|
|
1087
|
+
|
|
1088
|
+
/** Key/value data storage (separate from settings) */
|
|
1089
|
+
storage: PluginStorageAPI;
|
|
1090
|
+
|
|
1091
|
+
/** SQL database for plugin-owned tables */
|
|
1092
|
+
database: PluginDatabaseAPI;
|
|
1093
|
+
|
|
1094
|
+
/** Read-only access to app settings */
|
|
1095
|
+
appSettings: ReadonlyAppSettings;
|
|
1096
|
+
|
|
1097
|
+
/** Invoke Tauri commands (permission-gated allowlist for community plugins) */
|
|
1098
|
+
invoke<T>(command: string, args?: Record<string, unknown>): Promise<T>;
|
|
1099
|
+
|
|
1100
|
+
/** Modal dialogs */
|
|
1101
|
+
modal: ModalAPI;
|
|
1102
|
+
|
|
1103
|
+
/** Notifications/toasts */
|
|
1104
|
+
notify: NotifyAPI;
|
|
1105
|
+
|
|
1106
|
+
/** File path utilities */
|
|
1107
|
+
files: FileUtilsAPI;
|
|
1108
|
+
|
|
1109
|
+
/** Explicit acquisition of stable Explorer pane facades. */
|
|
1110
|
+
explorer: ExplorerAPI;
|
|
1111
|
+
|
|
1112
|
+
/** Fixed read-only repository inspection under filesystem.read. */
|
|
1113
|
+
git: GitAPI;
|
|
1114
|
+
|
|
1115
|
+
/** Permission-gated Workspace Folder data and Page operations. */
|
|
1116
|
+
workspaceFolders: WorkspaceFoldersAPI;
|
|
1117
|
+
|
|
1118
|
+
/** Permission-gated text clipboard. */
|
|
1119
|
+
clipboard: ClipboardAPI;
|
|
1120
|
+
/** Permission-gated network fetch. */
|
|
1121
|
+
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
1122
|
+
|
|
1123
|
+
/** Center-module routing. */
|
|
1124
|
+
modules: ModulesAPI;
|
|
1125
|
+
|
|
1126
|
+
/** Event pub/sub for cross-plugin communication */
|
|
1127
|
+
events: EventsAPI;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* API passed to view configuration item factories (scoped to the view's owning plugin).
|
|
1132
|
+
* Same runtime object as {@link PluginAPI} for that plugin; reserved for future view helpers.
|
|
1133
|
+
*/
|
|
1134
|
+
interface ViewAPI extends PluginAPI {}
|
|
1135
|
+
|
|
1136
|
+
/**
|
|
1137
|
+
* API passed to module tab bar menu item factories (scoped to the module's owning plugin).
|
|
1138
|
+
* Same runtime object as {@link PluginAPI} for that plugin; reserved for future module helpers.
|
|
1139
|
+
*/
|
|
1140
|
+
interface ModuleAPI extends PluginAPI {}
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* Preview API - extended API for preview providers
|
|
1144
|
+
*/
|
|
1145
|
+
interface PreviewAPI extends PluginAPI {
|
|
1146
|
+
/** Get metadata for a file */
|
|
1147
|
+
getMetadata(file: FileEntry): Promise<FileMetadata>;
|
|
1148
|
+
|
|
1149
|
+
/** Open fullscreen preview for a file */
|
|
1150
|
+
openFullscreen(file: FileEntry): void;
|
|
1151
|
+
|
|
1152
|
+
/** Navigate to a path */
|
|
1153
|
+
navigateTo(path: string): void;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
/**
|
|
1157
|
+
* Metadata API - extended API for metadata providers
|
|
1158
|
+
*/
|
|
1159
|
+
interface MetadataAPI extends PluginAPI {
|
|
1160
|
+
/** Read the exact host-selected extraction target as bytes. */
|
|
1161
|
+
readFile(): Promise<Uint8Array>;
|
|
1162
|
+
|
|
1163
|
+
/** Read the exact host-selected extraction target as text. */
|
|
1164
|
+
readTextFile(): Promise<string>;
|
|
1165
|
+
}
|