@lapis-notes/api 0.1.4 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +206 -0
- package/README.md +21 -2
- package/dist/__tests__/fixtures/indexed-mutations.json +6862 -0
- package/dist/__tests__/fixtures/memory-storage.json +309 -0
- package/dist/__tests__/fixtures/native-facade-contract.json +3224 -0
- package/dist/__tests__/fixtures/projection-query.json +195 -0
- package/dist/__tests__/fixtures/projection-values.json +60 -0
- package/dist/__tests__/fixtures/search-preparation.json +1513 -0
- package/dist/__tests__/fixtures/search-retrieval.json +15409 -0
- package/dist/__tests__/fixtures/search-semantic-model.json +3691 -0
- package/dist/__tests__/fixtures/search-semantic-retrieval.json +6603 -0
- package/dist/__tests__/fixtures/search-storage.json +409 -0
- package/dist/__tests__/fixtures/task-projection.json +428 -0
- package/dist/__tests__/indexed-mutation-support.js +262 -0
- package/dist/__tests__/projection-query-support.js +40 -0
- package/dist/__tests__/search-retrieval-support.js +47 -0
- package/dist/app-database-host.d.ts +1 -0
- package/dist/app-shell-plugin-persistence.d.ts +3 -2
- package/dist/app-shell-plugin-persistence.js +37 -3
- package/dist/cache.svelte.d.ts +8 -1
- package/dist/cache.svelte.js +103 -5
- package/dist/command.svelte.js +29 -2
- package/dist/components/editor/editor.css +4 -0
- package/dist/components/editor/editor.svelte +21 -9
- package/dist/components/editor/embedded-editor-surface.js +3 -1
- package/dist/components/editor/inline-title-alignment.d.ts +3 -0
- package/dist/components/editor/inline-title-alignment.js +57 -0
- package/dist/configuration.svelte.d.ts +270 -206
- package/dist/configuration.svelte.js +161 -86
- package/dist/context.svelte.d.ts +21 -3
- package/dist/context.svelte.js +63 -20
- package/dist/diagnostics.d.ts +8 -0
- package/dist/diagnostics.js +6 -0
- package/dist/editor-save-context.d.ts +12 -1
- package/dist/editor-save-context.js +32 -1
- package/dist/editor-view-registry.d.ts +10 -0
- package/dist/editor-view-registry.js +44 -4
- package/dist/editor.svelte.js +128 -37
- package/dist/embed-registry.d.ts +10 -0
- package/dist/embed-registry.js +15 -0
- package/dist/file-editing-failures.d.ts +2 -0
- package/dist/file-editing-failures.js +29 -0
- package/dist/file-editing-native-issues.d.ts +19 -0
- package/dist/file-editing-native-issues.js +65 -0
- package/dist/file-editing-sessions.d.ts +56 -8
- package/dist/file-editing-sessions.js +185 -15
- package/dist/file-manager.d.ts +8 -1
- package/dist/file-manager.js +37 -3
- package/dist/file-state-store.d.ts +5 -0
- package/dist/file-state-store.js +34 -0
- package/dist/file-text-conflicts.d.ts +25 -0
- package/dist/file-text-conflicts.js +35 -0
- package/dist/file-text-mutation.d.ts +13 -0
- package/dist/file-text-mutation.js +100 -0
- package/dist/file-text-persistence.d.ts +36 -0
- package/dist/file-text-persistence.js +234 -0
- package/dist/file-text-state-writer.d.ts +34 -0
- package/dist/file-text-state-writer.js +183 -0
- package/dist/files-configuration.d.ts +20 -0
- package/dist/files-configuration.js +47 -0
- package/dist/generated/plugin-host-modules.schema.generated.d.ts +87 -37
- package/dist/generated/plugin-host-modules.schema.generated.js +102 -37
- package/dist/glob.d.ts +3 -0
- package/dist/glob.js +2 -1
- package/dist/icons/changes.d.ts +3 -0
- package/dist/icons/changes.js +16 -0
- package/dist/icons/index.d.ts +5 -1
- package/dist/icons/index.js +44 -3
- package/dist/icons/registry.d.ts +35 -0
- package/dist/icons/registry.js +154 -0
- package/dist/icons/safe-svg.d.ts +2 -0
- package/dist/icons/safe-svg.js +44 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -1
- package/dist/lapis-extension.d.ts +6 -2
- package/dist/lapis-extension.js +2 -0
- package/dist/metadata.svelte.js +45 -2
- package/dist/native-background-indexing.d.ts +48 -0
- package/dist/native-background-indexing.js +208 -0
- package/dist/native-database-protocol.d.ts +29 -0
- package/dist/native-database-protocol.js +1 -0
- package/dist/native-editing-intent-lease.d.ts +17 -0
- package/dist/native-editing-intent-lease.js +188 -0
- package/dist/native-editing-intents-protocol.d.ts +70 -0
- package/dist/native-editing-intents-protocol.js +1 -0
- package/dist/native-editing-intents.d.ts +8 -0
- package/dist/native-editing-intents.js +1 -0
- package/dist/native-editing-problems.d.ts +3 -0
- package/dist/native-editing-problems.js +180 -0
- package/dist/native-editing-recovery.d.ts +24 -0
- package/dist/native-editing-recovery.js +198 -0
- package/dist/native-editing-session.d.ts +51 -0
- package/dist/native-editing-session.js +251 -0
- package/dist/native-history-index-protocol.d.ts +80 -0
- package/dist/native-history-index-protocol.js +1 -0
- package/dist/native-history-index.d.ts +6 -0
- package/dist/native-history-index.js +1 -0
- package/dist/native-indexing-protocol.d.ts +63 -0
- package/dist/native-indexing-protocol.js +1 -0
- package/dist/native-participant-protocol.d.ts +67 -0
- package/dist/native-participant-protocol.js +3 -0
- package/dist/native-queue-protocol.d.ts +73 -0
- package/dist/native-queue-protocol.js +3 -0
- package/dist/native-tasks-protocol.d.ts +264 -0
- package/dist/native-tasks-protocol.js +1 -0
- package/dist/native-tasks.d.ts +35 -0
- package/dist/native-tasks.js +79 -0
- package/dist/native-turn-protocol.d.ts +81 -0
- package/dist/native-turn-protocol.js +1 -0
- package/dist/native-turns.d.ts +29 -0
- package/dist/native-turns.js +2 -0
- package/dist/plugin-asset-server.js +3 -2
- package/dist/plugin-dependency-resolver.d.ts +1 -1
- package/dist/plugin-distribution/compatibility.d.ts +1 -1
- package/dist/plugin-distribution/compatibility.js +10 -5
- package/dist/plugin-distribution/installed-plugin-state.js +2 -1
- package/dist/plugin-distribution/installer.d.ts +6 -0
- package/dist/plugin-distribution/installer.js +90 -37
- package/dist/plugin-distribution/manager.d.ts +4 -1
- package/dist/plugin-distribution/manager.js +12 -5
- package/dist/plugin-distribution/registry-cache.js +2 -1
- package/dist/plugin-distribution/registry-source-state.js +2 -1
- package/dist/plugin-distribution/schemas.d.ts +26 -8
- package/dist/plugin-distribution/schemas.js +2 -1
- package/dist/plugin-distribution/types.d.ts +4 -0
- package/dist/plugin-manager.d.ts +20 -4
- package/dist/plugin-manager.js +228 -64
- package/dist/plugin-runtime-entry.d.ts +1 -1
- package/dist/plugin-runtime-entry.js +16 -0
- package/dist/plugin.d.ts +18 -2
- package/dist/plugin.js +93 -39
- package/dist/registry-schema/catalog-v1.d.ts +60 -9
- package/dist/registry-schema/catalog-v1.js +2 -1
- package/dist/registry-schema/catalog-v2.d.ts +60 -9
- package/dist/registry-schema/catalog-v2.js +1 -1
- package/dist/search-result-provider.d.ts +95 -0
- package/dist/search-result-provider.js +42 -0
- package/dist/status-bar.svelte.d.ts +26 -20
- package/dist/status-bar.svelte.js +1 -0
- package/dist/storage/app-database.d.ts +6 -2
- package/dist/storage/app-database.js +41 -34
- package/dist/storage/desktop-native.d.ts +5 -3
- package/dist/storage/desktop-native.js +59 -6
- package/dist/storage/directory-watcher.d.ts +27 -0
- package/dist/storage/directory-watcher.js +201 -0
- package/dist/storage/fs.d.ts +14 -27
- package/dist/storage/fs.js +2 -168
- package/dist/storage/index-projection.js +33 -15
- package/dist/storage/memory-vault-adapter.d.ts +2 -0
- package/dist/storage/memory-vault-adapter.js +14 -1
- package/dist/storage/path.d.ts +6 -2
- package/dist/storage/path.js +8 -2
- package/dist/storage/projection-query-candidates.d.ts +3 -0
- package/dist/storage/projection-query-candidates.js +69 -0
- package/dist/storage/remote-app-database.d.ts +2 -2
- package/dist/storage/remote-app-database.js +1 -1
- package/dist/storage/runtime.d.ts +3 -0
- package/dist/storage/runtime.js +3 -0
- package/dist/storage/search-embedding-record.d.ts +3 -0
- package/dist/storage/search-embedding-record.js +18 -0
- package/dist/storage/turso-app-database.d.ts +2 -0
- package/dist/storage/turso-app-database.js +67 -30
- package/dist/storage/vault-listing.d.ts +3 -0
- package/dist/storage/vault-listing.js +36 -0
- package/dist/storage/vault-reconciliation.d.ts +19 -0
- package/dist/storage/vault-reconciliation.js +137 -0
- package/dist/storage/vault-session.d.ts +8 -0
- package/dist/storage/vault-session.js +10 -2
- package/dist/storage/vault.svelte.d.ts +53 -4
- package/dist/storage/vault.svelte.js +223 -87
- package/dist/sync-host.d.ts +12 -3
- package/dist/sync-host.js +5 -1
- package/dist/vault-change-views.d.ts +4 -0
- package/dist/vault-change-views.js +43 -0
- package/dist/vault-changes.d.ts +37 -0
- package/dist/vault-changes.js +228 -0
- package/dist/view.svelte.d.ts +182 -149
- package/dist/view.svelte.js +11 -2
- package/dist/workspace-close-guard.d.ts +3 -0
- package/dist/workspace-close-guard.js +35 -0
- package/dist/workspace-host-internal.js +10 -2
- package/dist/workspace-layout-normalizer.d.ts +4 -2
- package/dist/workspace-layout-normalizer.js +5 -5
- package/dist/workspace-view-document.d.ts +3 -0
- package/dist/workspace-view-document.js +12 -0
- package/dist/workspace.svelte.d.ts +13 -2
- package/dist/workspace.svelte.js +371 -82
- package/package.json +45 -8
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
export const checkCatalogEntryCompatibility = (entry, input) => checkBaseCompatibility(entry.minAppVersion, entry.platforms, false, false, false, input);
|
|
2
|
-
export const checkCatalogReleaseCompatibility = (release, input) => checkBaseCompatibility(release.minAppVersion, release.platforms, false, false, Boolean(release.revoked), input);
|
|
3
|
-
export const checkReleaseManifestCompatibility = (manifest, input) => checkBaseCompatibility(manifest.compatibility.minAppVersion, manifest.compatibility.platforms, Boolean(manifest.compatibility.desktopOnly), Boolean(manifest.compatibility.requiresWorkspaceTrust), Boolean(manifest.revoked), input);
|
|
4
|
-
const checkBaseCompatibility = (minAppVersion, platforms, desktopOnly, requiresWorkspaceTrust, revoked, input) => {
|
|
1
|
+
export const checkCatalogEntryCompatibility = (entry, input) => checkBaseCompatibility(entry.id, entry.minAppVersion, entry.platforms, false, false, false, input);
|
|
2
|
+
export const checkCatalogReleaseCompatibility = (release, input, pluginId = "") => checkBaseCompatibility(pluginId, release.minAppVersion, release.platforms, false, false, Boolean(release.revoked), input);
|
|
3
|
+
export const checkReleaseManifestCompatibility = (manifest, input) => checkBaseCompatibility(manifest.pluginId, manifest.compatibility.minAppVersion, manifest.compatibility.platforms, Boolean(manifest.compatibility.desktopOnly), Boolean(manifest.compatibility.requiresWorkspaceTrust), Boolean(manifest.revoked), input);
|
|
4
|
+
const checkBaseCompatibility = (pluginId, minAppVersion, platforms, desktopOnly, requiresWorkspaceTrust, revoked, input) => {
|
|
5
5
|
const reasons = [];
|
|
6
|
+
if (Object.hasOwn(input.unavailablePlugins ?? {}, pluginId)) {
|
|
7
|
+
reasons.push(input.unavailablePlugins[pluginId]);
|
|
8
|
+
}
|
|
6
9
|
if (compareVersions(input.appVersion, minAppVersion) < 0) {
|
|
7
10
|
reasons.push("app-version-too-old");
|
|
8
11
|
}
|
|
9
12
|
if (!platforms.includes(input.platform)) {
|
|
10
13
|
reasons.push("platform-unsupported");
|
|
11
14
|
}
|
|
12
|
-
if (desktopOnly &&
|
|
15
|
+
if (desktopOnly &&
|
|
16
|
+
input.platform === "web" &&
|
|
17
|
+
!reasons.includes("desktop-only")) {
|
|
13
18
|
reasons.push("desktop-only");
|
|
14
19
|
}
|
|
15
20
|
if (requiresWorkspaceTrust && !input.workspaceTrusted) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { appStatePath } from "../storage/path";
|
|
1
2
|
import { dirname } from "../storage/path";
|
|
2
3
|
import { installedPluginsStateSchema, parsePluginDistributionMetadata, } from "./schemas";
|
|
3
4
|
export class InstalledPluginStateStore {
|
|
@@ -57,7 +58,7 @@ export class InstalledPluginStateStore {
|
|
|
57
58
|
};
|
|
58
59
|
}
|
|
59
60
|
get path() {
|
|
60
|
-
return this.options.path ?? "
|
|
61
|
+
return this.options.path ?? appStatePath("installed-plugins.json");
|
|
61
62
|
}
|
|
62
63
|
now() {
|
|
63
64
|
return (this.options.now?.() ?? new Date()).toISOString();
|
|
@@ -19,6 +19,12 @@ export interface PluginInstallerProgressEvent {
|
|
|
19
19
|
fileCount?: number;
|
|
20
20
|
}
|
|
21
21
|
export interface PluginInstallerManager {
|
|
22
|
+
unloadPlugin?(pluginId: string): Promise<boolean>;
|
|
23
|
+
isStaticPlugin?(pluginId: string): boolean;
|
|
24
|
+
preparePluginReplacement?(pluginId: string): Promise<{
|
|
25
|
+
reloadRequired: boolean;
|
|
26
|
+
rollback(): Promise<void>;
|
|
27
|
+
} | undefined>;
|
|
22
28
|
loadPlugin?(pluginPath: string, options?: {
|
|
23
29
|
provenance?: PluginProvenance;
|
|
24
30
|
}): Promise<unknown>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { appStatePath } from "../storage/path";
|
|
1
2
|
import { basename, dirname, joinPath } from "../storage/path";
|
|
2
3
|
import { checkReleaseManifestCompatibility } from "./compatibility";
|
|
3
4
|
import { PluginDistributionError } from "./errors";
|
|
@@ -64,7 +65,15 @@ export class VerifiedPluginInstaller {
|
|
|
64
65
|
});
|
|
65
66
|
}
|
|
66
67
|
async uninstall(pluginId, options = {}) {
|
|
67
|
-
|
|
68
|
+
const manager = this.options.pluginManager;
|
|
69
|
+
if (!manager?.isStaticPlugin?.(pluginId)) {
|
|
70
|
+
if (manager?.unloadPlugin) {
|
|
71
|
+
if (!(await manager.unloadPlugin(pluginId)))
|
|
72
|
+
throw new Error(`Plugin ${pluginId} cleanup failed; uninstall was cancelled.`);
|
|
73
|
+
}
|
|
74
|
+
else
|
|
75
|
+
await manager?.disablePlugin?.(pluginId);
|
|
76
|
+
}
|
|
68
77
|
const pluginPath = joinPath(this.pluginsPath, pluginId);
|
|
69
78
|
if (options.removeData) {
|
|
70
79
|
await this.removeIfExists(pluginPath);
|
|
@@ -140,6 +149,9 @@ export class VerifiedPluginInstaller {
|
|
|
140
149
|
}
|
|
141
150
|
async installVerifiedBundlePayload(payload, options) {
|
|
142
151
|
const { releaseEnvelope, releaseManifest, releaseManifestSha256, files, nostrProof, } = payload;
|
|
152
|
+
if (this.options.pluginManager?.isStaticPlugin?.(releaseManifest.pluginId)) {
|
|
153
|
+
throw new PluginDistributionError("reserved-id", `Plugin ${releaseManifest.pluginId} is registered by the application.`);
|
|
154
|
+
}
|
|
143
155
|
if (options.compatibility) {
|
|
144
156
|
const compatibility = checkReleaseManifestCompatibility(releaseManifest, options.compatibility);
|
|
145
157
|
if (!compatibility.compatible) {
|
|
@@ -170,36 +182,12 @@ export class VerifiedPluginInstaller {
|
|
|
170
182
|
}
|
|
171
183
|
const stagingPath = joinPath(this.pluginsPath, ".installing", `${releaseManifest.pluginId}-${Date.now()}`);
|
|
172
184
|
const finalPath = joinPath(this.pluginsPath, releaseManifest.pluginId);
|
|
173
|
-
|
|
174
|
-
throwIfAborted(options.signal);
|
|
175
|
-
options.onProgress?.({
|
|
176
|
-
phase: "staging",
|
|
177
|
-
message: "Staging plugin files",
|
|
178
|
-
processedBytes: 0,
|
|
179
|
-
totalBytes: totalFileBytes(files),
|
|
180
|
-
});
|
|
181
|
-
await this.writeStagingFiles(stagingPath, files, {
|
|
182
|
-
signal: options.signal,
|
|
183
|
-
onProgress: options.onProgress,
|
|
184
|
-
});
|
|
185
|
-
options.onProgress?.({
|
|
186
|
-
phase: "installing",
|
|
187
|
-
message: "Installing plugin files",
|
|
188
|
-
});
|
|
189
|
-
await this.swapIntoPlace(stagingPath, finalPath);
|
|
190
|
-
}
|
|
191
|
-
catch (error) {
|
|
192
|
-
await this.removeIfExists(stagingPath);
|
|
193
|
-
if (!(await this.options.adapter.exists(finalPath))) {
|
|
194
|
-
await this.removeIfExists(finalPath);
|
|
195
|
-
}
|
|
196
|
-
throw error;
|
|
197
|
-
}
|
|
185
|
+
const previousRecord = await this.stateStore.get(releaseManifest.pluginId);
|
|
198
186
|
const now = this.now();
|
|
199
187
|
const record = {
|
|
200
188
|
pluginId: releaseManifest.pluginId,
|
|
201
189
|
installedVersion: releaseManifest.version,
|
|
202
|
-
installedAt: now,
|
|
190
|
+
installedAt: previousRecord?.installedAt ?? now,
|
|
203
191
|
updatedAt: now,
|
|
204
192
|
provenance,
|
|
205
193
|
registryId: options.registryId,
|
|
@@ -219,22 +207,70 @@ export class VerifiedPluginInstaller {
|
|
|
219
207
|
...(nostrProof ? { nostrProof } : {}),
|
|
220
208
|
restartRequired: Boolean(this.options.pluginManager),
|
|
221
209
|
};
|
|
222
|
-
|
|
210
|
+
let replacement;
|
|
211
|
+
try {
|
|
212
|
+
throwIfAborted(options.signal);
|
|
213
|
+
options.onProgress?.({
|
|
214
|
+
phase: "staging",
|
|
215
|
+
message: "Staging plugin files",
|
|
216
|
+
processedBytes: 0,
|
|
217
|
+
totalBytes: totalFileBytes(files),
|
|
218
|
+
});
|
|
219
|
+
await this.writeStagingFiles(stagingPath, files, {
|
|
220
|
+
signal: options.signal,
|
|
221
|
+
onProgress: options.onProgress,
|
|
222
|
+
});
|
|
223
|
+
if (await this.options.adapter.exists(finalPath)) {
|
|
224
|
+
replacement =
|
|
225
|
+
await this.options.pluginManager?.preparePluginReplacement?.(releaseManifest.pluginId);
|
|
226
|
+
// Read after teardown so its final save wins over release defaults.
|
|
227
|
+
const dataPath = joinPath(finalPath, "data.json");
|
|
228
|
+
if (await this.options.adapter.exists(dataPath)) {
|
|
229
|
+
await this.options.adapter.writeBinary(joinPath(stagingPath, "data.json"), await this.options.adapter.readBinary(dataPath));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
options.onProgress?.({
|
|
233
|
+
phase: "installing",
|
|
234
|
+
message: "Installing plugin files",
|
|
235
|
+
});
|
|
236
|
+
throwIfAborted(options.signal);
|
|
237
|
+
await this.swapIntoPlace(stagingPath, finalPath, {
|
|
238
|
+
publish: () => this.stateStore.upsert(record),
|
|
239
|
+
rollback: async () => {
|
|
240
|
+
if (previousRecord)
|
|
241
|
+
await this.stateStore.upsert(previousRecord);
|
|
242
|
+
else
|
|
243
|
+
await this.stateStore.remove(releaseManifest.pluginId);
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
try {
|
|
249
|
+
await this.removeIfExists(stagingPath);
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
await replacement?.rollback();
|
|
253
|
+
}
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
223
256
|
if (this.options.pluginManager?.loadPlugin) {
|
|
224
257
|
options.onProgress?.({
|
|
225
258
|
phase: "loading",
|
|
226
259
|
message: "Loading installed plugin",
|
|
227
260
|
});
|
|
228
261
|
}
|
|
229
|
-
const loaded =
|
|
230
|
-
|
|
231
|
-
|
|
262
|
+
const loaded = replacement?.reloadRequired
|
|
263
|
+
? null
|
|
264
|
+
: await this.options.pluginManager?.loadPlugin?.(finalPath, {
|
|
265
|
+
provenance,
|
|
266
|
+
});
|
|
232
267
|
const shouldEnable = options.enable ?? true;
|
|
233
268
|
const diagnostics = this.options.pluginManager?.getCommunityPluginDiagnostics?.(releaseManifest.pluginId) ?? null;
|
|
234
269
|
const cleanDormantExtension = diagnostics?.state === "dormant" &&
|
|
235
270
|
(diagnostics.lastFailureMessage ?? null) === null;
|
|
236
271
|
let enabled = false;
|
|
237
272
|
if (shouldEnable &&
|
|
273
|
+
!replacement?.reloadRequired &&
|
|
238
274
|
(loaded || cleanDormantExtension) &&
|
|
239
275
|
this.options.pluginManager?.enablePlugin) {
|
|
240
276
|
options.onProgress?.({
|
|
@@ -243,7 +279,8 @@ export class VerifiedPluginInstaller {
|
|
|
243
279
|
});
|
|
244
280
|
enabled = await this.options.pluginManager.enablePlugin(releaseManifest.pluginId);
|
|
245
281
|
}
|
|
246
|
-
record.restartRequired = Boolean(this.options.pluginManager &&
|
|
282
|
+
record.restartRequired = Boolean(this.options.pluginManager &&
|
|
283
|
+
(replacement?.reloadRequired || (!loaded && !enabled)));
|
|
247
284
|
await this.stateStore.upsert(record);
|
|
248
285
|
return record;
|
|
249
286
|
}
|
|
@@ -332,24 +369,40 @@ export class VerifiedPluginInstaller {
|
|
|
332
369
|
});
|
|
333
370
|
}
|
|
334
371
|
}
|
|
335
|
-
async swapIntoPlace(stagingPath, finalPath) {
|
|
372
|
+
async swapIntoPlace(stagingPath, finalPath, metadata) {
|
|
336
373
|
await ensureFolder(this.options.adapter, this.pluginsPath);
|
|
337
374
|
const backupPath = joinPath(this.pluginsPath, ".installing", `${basename(finalPath)}-backup-${Date.now()}`);
|
|
338
375
|
const hadExisting = await this.options.adapter.exists(finalPath);
|
|
339
376
|
if (hadExisting) {
|
|
340
377
|
await this.options.adapter.rename(finalPath, backupPath);
|
|
341
378
|
}
|
|
379
|
+
let moved = false;
|
|
380
|
+
let publishingMetadata = false;
|
|
342
381
|
try {
|
|
343
382
|
await this.options.adapter.rename(stagingPath, finalPath);
|
|
344
|
-
|
|
345
|
-
|
|
383
|
+
moved = true;
|
|
384
|
+
publishingMetadata = true;
|
|
385
|
+
await metadata.publish();
|
|
346
386
|
}
|
|
347
387
|
catch (error) {
|
|
388
|
+
if (moved)
|
|
389
|
+
await this.removeIfExists(finalPath);
|
|
348
390
|
if (hadExisting && !(await this.options.adapter.exists(finalPath))) {
|
|
349
391
|
await this.options.adapter.rename(backupPath, finalPath);
|
|
350
392
|
}
|
|
393
|
+
if (publishingMetadata)
|
|
394
|
+
await metadata.rollback();
|
|
351
395
|
throw error;
|
|
352
396
|
}
|
|
397
|
+
// Code and metadata are committed. Cleanup cannot reactivate the old module.
|
|
398
|
+
if (hadExisting) {
|
|
399
|
+
try {
|
|
400
|
+
await this.removeIfExists(backupPath);
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
console.warn(`Could not remove plugin backup ${backupPath}`, error);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
353
406
|
}
|
|
354
407
|
async removePluginCodeButKeepData(pluginPath) {
|
|
355
408
|
if (!(await this.options.adapter.exists(pluginPath)))
|
|
@@ -365,7 +418,7 @@ export class VerifiedPluginInstaller {
|
|
|
365
418
|
}
|
|
366
419
|
}
|
|
367
420
|
async removeCommunityPluginEnabledState(pluginId) {
|
|
368
|
-
const enabledPath = "
|
|
421
|
+
const enabledPath = appStatePath("community-plugins.json");
|
|
369
422
|
try {
|
|
370
423
|
const enabled = JSON.parse(await this.options.adapter.read(enabledPath));
|
|
371
424
|
if (!Array.isArray(enabled))
|
|
@@ -388,7 +441,7 @@ export class VerifiedPluginInstaller {
|
|
|
388
441
|
}
|
|
389
442
|
}
|
|
390
443
|
get pluginsPath() {
|
|
391
|
-
return this.options.pluginsPath ?? "
|
|
444
|
+
return this.options.pluginsPath ?? appStatePath("plugins");
|
|
392
445
|
}
|
|
393
446
|
now() {
|
|
394
447
|
return (this.options.now?.() ?? new Date()).toISOString();
|
|
@@ -4,7 +4,7 @@ import { type PluginBinaryFetch, type PluginInstallerManager } from "./installer
|
|
|
4
4
|
import type { PluginBundleVerificationMode } from "./plugin-bundle-worker";
|
|
5
5
|
import { type ParsedNostrPluginBundle } from "./plugin-bundle";
|
|
6
6
|
import type { VerifiedPluginBundlePayload } from "./plugin-bundle-verifier";
|
|
7
|
-
import type { InstalledPluginRecord, PluginCatalogDetail, PluginCatalogEntry, PluginCatalogIndex, PluginCompatibilityResult, PluginDownloadStatsSummary, PluginPlatform, PluginProvenance, PluginRegistryChannel, PluginRevocationIndex, PluginRevocationRecord, PluginRegistrySource, PluginRegistrySourceKind, PluginRegistrySourceState, TrustedSigningKey } from "./types";
|
|
7
|
+
import type { InstalledPluginRecord, PluginCatalogDetail, PluginCatalogEntry, PluginCatalogIndex, PluginCompatibilityInput, PluginCompatibilityResult, PluginDownloadStatsSummary, PluginPlatform, PluginProvenance, PluginRegistryChannel, PluginRevocationIndex, PluginRevocationRecord, PluginRegistrySource, PluginRegistrySourceKind, PluginRegistrySourceState, TrustedSigningKey } from "./types";
|
|
8
8
|
export type PluginInstallPhase = "resolving" | "fetching-catalog" | "fetching-release" | "verifying-signature" | "downloading-bundle" | "verifying-bundle" | "extracting-files" | "verifying-files" | "staging" | "installing" | "loading" | "enabling" | "complete" | "failed";
|
|
9
9
|
export interface PluginInstallProgressEvent {
|
|
10
10
|
pluginId: string;
|
|
@@ -73,6 +73,7 @@ export interface PluginDistributionManager {
|
|
|
73
73
|
setSourceEnabled(sourceId: string, enabled: boolean): Promise<void>;
|
|
74
74
|
search(query?: PluginSearchQuery): PluginCatalogEntry[];
|
|
75
75
|
getCatalogEntry(pluginId: string): PluginCatalogEntry | undefined;
|
|
76
|
+
getCompatibility?(pluginId: string): PluginCompatibilityResult | null;
|
|
76
77
|
getPluginDetail(pluginId: string, options?: {
|
|
77
78
|
registryId?: string;
|
|
78
79
|
}): Promise<PluginCatalogDetail | null>;
|
|
@@ -122,6 +123,7 @@ export interface DefaultPluginDistributionManagerOptions {
|
|
|
122
123
|
adapter: DataAdapter;
|
|
123
124
|
appVersion: string;
|
|
124
125
|
platform?: PluginPlatform;
|
|
126
|
+
unavailablePlugins?: PluginCompatibilityInput["unavailablePlugins"];
|
|
125
127
|
workspaceTrusted?: () => Promise<boolean> | boolean;
|
|
126
128
|
registries?: PluginRegistrySource[];
|
|
127
129
|
trustedKeys?: TrustedSigningKey[];
|
|
@@ -162,6 +164,7 @@ export declare class DefaultPluginDistributionManager extends EventDispatcher<{
|
|
|
162
164
|
setSourceEnabled(sourceId: string, enabled: boolean): Promise<void>;
|
|
163
165
|
search(query?: PluginSearchQuery): PluginCatalogEntry[];
|
|
164
166
|
getCatalogEntry(pluginId: string): PluginCatalogEntry | undefined;
|
|
167
|
+
getCompatibility(pluginId: string): PluginCompatibilityResult | null;
|
|
165
168
|
getPluginDetail(pluginId: string, options?: {
|
|
166
169
|
registryId?: string;
|
|
167
170
|
}): Promise<PluginCatalogDetail | null>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { appStatePath } from "../storage/path";
|
|
1
2
|
import { EventDispatcher } from "../events";
|
|
2
3
|
import { hasNativeDesktopCapability } from "../storage/desktop-native";
|
|
3
4
|
import { checkCatalogEntryCompatibility, checkCatalogReleaseCompatibility, compareVersions, } from "./compatibility";
|
|
@@ -236,8 +237,7 @@ export class DefaultPluginDistributionManager extends EventDispatcher {
|
|
|
236
237
|
return false;
|
|
237
238
|
}
|
|
238
239
|
if (query.compatibleOnly) {
|
|
239
|
-
|
|
240
|
-
if (!compatibility.compatible)
|
|
240
|
+
if (!this.getCompatibility(entry.id)?.compatible)
|
|
241
241
|
return false;
|
|
242
242
|
}
|
|
243
243
|
return true;
|
|
@@ -246,6 +246,12 @@ export class DefaultPluginDistributionManager extends EventDispatcher {
|
|
|
246
246
|
getCatalogEntry(pluginId) {
|
|
247
247
|
return this.catalog?.plugins.find((entry) => entry.id === pluginId);
|
|
248
248
|
}
|
|
249
|
+
getCompatibility(pluginId) {
|
|
250
|
+
const entry = this.getCatalogEntry(pluginId);
|
|
251
|
+
return entry
|
|
252
|
+
? checkCatalogEntryCompatibility(entry, this.compatibilityInput(false))
|
|
253
|
+
: null;
|
|
254
|
+
}
|
|
249
255
|
async getPluginDetail(pluginId, options = {}) {
|
|
250
256
|
const entry = this.entryForSource(pluginId, options.registryId);
|
|
251
257
|
if (!entry)
|
|
@@ -284,7 +290,7 @@ export class DefaultPluginDistributionManager extends EventDispatcher {
|
|
|
284
290
|
if (!release) {
|
|
285
291
|
throw new PluginDistributionError("metadata-invalid", `Plugin ${pluginId} has no requested release.`);
|
|
286
292
|
}
|
|
287
|
-
const releaseCompatibility = checkCatalogReleaseCompatibility(release, this.compatibilityInput(false));
|
|
293
|
+
const releaseCompatibility = checkCatalogReleaseCompatibility(release, this.compatibilityInput(false), pluginId);
|
|
288
294
|
if (!releaseCompatibility.compatible) {
|
|
289
295
|
throw new PluginDistributionError("compatibility-failed", `Plugin ${pluginId} release is not compatible: ${releaseCompatibility.reasons.join(", ")}`, { details: { reasons: releaseCompatibility.reasons } });
|
|
290
296
|
}
|
|
@@ -488,7 +494,7 @@ export class DefaultPluginDistributionManager extends EventDispatcher {
|
|
|
488
494
|
});
|
|
489
495
|
const targetRelease = detail?.versions[targetVersion];
|
|
490
496
|
if (targetRelease) {
|
|
491
|
-
compatibility = checkCatalogReleaseCompatibility(targetRelease, this.compatibilityInput(false));
|
|
497
|
+
compatibility = checkCatalogReleaseCompatibility(targetRelease, this.compatibilityInput(false), record.pluginId);
|
|
492
498
|
}
|
|
493
499
|
const canUpdate = hasNewerTarget && compatibility.compatible;
|
|
494
500
|
const update = {
|
|
@@ -528,7 +534,7 @@ export class DefaultPluginDistributionManager extends EventDispatcher {
|
|
|
528
534
|
fetch: this.options.fetch,
|
|
529
535
|
cache: new PluginRegistryCache({
|
|
530
536
|
adapter: this.options.adapter,
|
|
531
|
-
cachePath:
|
|
537
|
+
cachePath: appStatePath(`plugin-registry-cache/${encodeURIComponent(source.id)}/${encodeURIComponent(source.url)}.json`),
|
|
532
538
|
}),
|
|
533
539
|
});
|
|
534
540
|
this.httpClients.set(key, client);
|
|
@@ -580,6 +586,7 @@ export class DefaultPluginDistributionManager extends EventDispatcher {
|
|
|
580
586
|
appVersion: this.options.appVersion,
|
|
581
587
|
platform: this.platform,
|
|
582
588
|
workspaceTrusted,
|
|
589
|
+
unavailablePlugins: this.options.unavailablePlugins,
|
|
583
590
|
};
|
|
584
591
|
}
|
|
585
592
|
get platform() {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { appStatePath } from "../storage/path";
|
|
1
2
|
import { pluginCatalogDetailSchema, pluginCatalogIndexSchema, pluginRevocationIndexSchema, parsePluginDistributionMetadata, } from "./schemas";
|
|
2
3
|
export class PluginRegistryCache {
|
|
3
4
|
options;
|
|
@@ -68,7 +69,7 @@ export class PluginRegistryCache {
|
|
|
68
69
|
return this.write(existing.sourceUrl, existing.index, existing.details, revocations);
|
|
69
70
|
}
|
|
70
71
|
get cachePath() {
|
|
71
|
-
return this.options.cachePath ?? "
|
|
72
|
+
return this.options.cachePath ?? appStatePath("plugin-registry-cache.json");
|
|
72
73
|
}
|
|
73
74
|
get cacheFolder() {
|
|
74
75
|
const parts = this.cachePath.split("/");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { appStatePath } from "../storage/path";
|
|
1
2
|
import { dirname } from "../storage/path";
|
|
2
3
|
import { ensureFolder } from "./installed-plugin-state";
|
|
3
4
|
import { parsePluginDistributionMetadata, pluginRegistrySourcePreferencesStateSchema, } from "./schemas";
|
|
@@ -34,7 +35,7 @@ export class PluginRegistrySourcePreferenceStore {
|
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
37
|
get path() {
|
|
37
|
-
return this.options.path ?? "
|
|
38
|
+
return this.options.path ?? appStatePath("plugin-registry-sources.json");
|
|
38
39
|
}
|
|
39
40
|
now() {
|
|
40
41
|
return (this.options.now?.() ?? new Date()).toISOString();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
1
|
+
import { z } from "zod/v3";
|
|
2
2
|
export declare const registryTrustTierSchema: z.ZodEnum<["official", "community", "local"]>;
|
|
3
3
|
export declare const pluginProvenanceSchema: z.ZodEnum<["bundled", "official", "community", "manual", "development"]>;
|
|
4
4
|
export declare const pluginRegistryChannelSchema: z.ZodEnum<["official", "community"]>;
|
|
@@ -28,13 +28,13 @@ export declare const trustedSigningKeySchema: z.ZodObject<{
|
|
|
28
28
|
publicKey: string;
|
|
29
29
|
keyId: string;
|
|
30
30
|
alg: "ed25519";
|
|
31
|
-
trustTier: "
|
|
31
|
+
trustTier: "local" | "community" | "official";
|
|
32
32
|
expiresAt?: string | undefined;
|
|
33
33
|
}, {
|
|
34
34
|
publicKey: string;
|
|
35
35
|
keyId: string;
|
|
36
36
|
alg: "ed25519";
|
|
37
|
-
trustTier: "
|
|
37
|
+
trustTier: "local" | "community" | "official";
|
|
38
38
|
expiresAt?: string | undefined;
|
|
39
39
|
}>;
|
|
40
40
|
export declare const remoteFileReferenceSchema: z.ZodObject<{
|
|
@@ -524,16 +524,19 @@ export declare const pluginContributionSummarySchema: z.ZodObject<{
|
|
|
524
524
|
}, z.ZodTypeAny, "passthrough">>, "many">>;
|
|
525
525
|
editorViews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
526
526
|
id: z.ZodString;
|
|
527
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
527
528
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
528
529
|
extensions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
529
530
|
mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
530
531
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
531
532
|
id: z.ZodString;
|
|
533
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
532
534
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
533
535
|
extensions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
534
536
|
mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
535
537
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
536
538
|
id: z.ZodString;
|
|
539
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
537
540
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
538
541
|
extensions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
539
542
|
mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
@@ -581,16 +584,19 @@ export declare const pluginContributionSummarySchema: z.ZodObject<{
|
|
|
581
584
|
}, z.ZodTypeAny, "passthrough">>, "many">>;
|
|
582
585
|
editorViews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
583
586
|
id: z.ZodString;
|
|
587
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
584
588
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
585
589
|
extensions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
586
590
|
mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
587
591
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
588
592
|
id: z.ZodString;
|
|
593
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
589
594
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
590
595
|
extensions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
591
596
|
mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
592
597
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
593
598
|
id: z.ZodString;
|
|
599
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
594
600
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
595
601
|
extensions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
596
602
|
mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
@@ -638,16 +644,19 @@ export declare const pluginContributionSummarySchema: z.ZodObject<{
|
|
|
638
644
|
}, z.ZodTypeAny, "passthrough">>, "many">>;
|
|
639
645
|
editorViews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
640
646
|
id: z.ZodString;
|
|
647
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
641
648
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
642
649
|
extensions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
643
650
|
mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
644
651
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
645
652
|
id: z.ZodString;
|
|
653
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
646
654
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
647
655
|
extensions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
648
656
|
mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
649
657
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
650
658
|
id: z.ZodString;
|
|
659
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
651
660
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
652
661
|
extensions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
653
662
|
mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
@@ -687,12 +696,12 @@ export declare const pluginCatalogEntrySchema: z.ZodEffects<z.ZodUnknown, {
|
|
|
687
696
|
description: string;
|
|
688
697
|
name: string;
|
|
689
698
|
status: "active" | "pending" | "disabled" | "deprecated" | "revoked";
|
|
699
|
+
id: string;
|
|
690
700
|
owner: {
|
|
691
701
|
name: string;
|
|
692
702
|
verified: boolean;
|
|
693
703
|
url?: string | undefined;
|
|
694
704
|
};
|
|
695
|
-
id: string;
|
|
696
705
|
author: string;
|
|
697
706
|
badges: string[];
|
|
698
707
|
minAppVersion: string;
|
|
@@ -756,14 +765,17 @@ export declare const pluginCatalogEntrySchema: z.ZodEffects<z.ZodUnknown, {
|
|
|
756
765
|
contributes?: z.objectOutputType<{
|
|
757
766
|
editorViews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
758
767
|
id: z.ZodString;
|
|
768
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
759
769
|
label: z.ZodOptional<z.ZodString>;
|
|
760
770
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
761
771
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
762
772
|
id: z.ZodString;
|
|
773
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
763
774
|
label: z.ZodOptional<z.ZodString>;
|
|
764
775
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
765
776
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
766
777
|
id: z.ZodString;
|
|
778
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
767
779
|
label: z.ZodOptional<z.ZodString>;
|
|
768
780
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
769
781
|
}, z.ZodTypeAny, "passthrough">>, "many">>;
|
|
@@ -782,12 +794,12 @@ export declare const pluginCatalogIndexSchema: z.ZodEffects<z.ZodUnknown, {
|
|
|
782
794
|
description: string;
|
|
783
795
|
name: string;
|
|
784
796
|
status: "active" | "pending" | "disabled" | "deprecated" | "revoked";
|
|
797
|
+
id: string;
|
|
785
798
|
owner: {
|
|
786
799
|
name: string;
|
|
787
800
|
verified: boolean;
|
|
788
801
|
url?: string | undefined;
|
|
789
802
|
};
|
|
790
|
-
id: string;
|
|
791
803
|
author: string;
|
|
792
804
|
badges: string[];
|
|
793
805
|
minAppVersion: string;
|
|
@@ -851,14 +863,17 @@ export declare const pluginCatalogIndexSchema: z.ZodEffects<z.ZodUnknown, {
|
|
|
851
863
|
contributes?: z.objectOutputType<{
|
|
852
864
|
editorViews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
853
865
|
id: z.ZodString;
|
|
866
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
854
867
|
label: z.ZodOptional<z.ZodString>;
|
|
855
868
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
856
869
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
857
870
|
id: z.ZodString;
|
|
871
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
858
872
|
label: z.ZodOptional<z.ZodString>;
|
|
859
873
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
860
874
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
861
875
|
id: z.ZodString;
|
|
876
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
862
877
|
label: z.ZodOptional<z.ZodString>;
|
|
863
878
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
864
879
|
}, z.ZodTypeAny, "passthrough">>, "many">>;
|
|
@@ -2617,6 +2632,7 @@ export declare const pluginCatalogDetailSchema: z.ZodEffects<z.ZodUnknown, {
|
|
|
2617
2632
|
description: string;
|
|
2618
2633
|
name: string;
|
|
2619
2634
|
status: "active" | "pending" | "disabled" | "deprecated" | "revoked";
|
|
2635
|
+
id: string;
|
|
2620
2636
|
versions: Record<string, {
|
|
2621
2637
|
version: string;
|
|
2622
2638
|
bundle: {
|
|
@@ -2641,7 +2657,6 @@ export declare const pluginCatalogDetailSchema: z.ZodEffects<z.ZodUnknown, {
|
|
|
2641
2657
|
verified: boolean;
|
|
2642
2658
|
url?: string | undefined;
|
|
2643
2659
|
};
|
|
2644
|
-
id: string;
|
|
2645
2660
|
schemaVersion: 2;
|
|
2646
2661
|
author: string;
|
|
2647
2662
|
channel: "community" | "official";
|
|
@@ -2827,14 +2842,17 @@ export declare const pluginCatalogDetailSchema: z.ZodEffects<z.ZodUnknown, {
|
|
|
2827
2842
|
contributes?: z.objectOutputType<{
|
|
2828
2843
|
editorViews: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
2829
2844
|
id: z.ZodString;
|
|
2845
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
2830
2846
|
label: z.ZodOptional<z.ZodString>;
|
|
2831
2847
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
2832
2848
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
2833
2849
|
id: z.ZodString;
|
|
2850
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
2834
2851
|
label: z.ZodOptional<z.ZodString>;
|
|
2835
2852
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
2836
2853
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
2837
2854
|
id: z.ZodString;
|
|
2855
|
+
fileIcon: z.ZodOptional<z.ZodString>;
|
|
2838
2856
|
label: z.ZodOptional<z.ZodString>;
|
|
2839
2857
|
filenamePatterns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
2840
2858
|
}, z.ZodTypeAny, "passthrough">>, "many">>;
|
|
@@ -3107,8 +3125,8 @@ export declare const pluginReleaseManifestSchema: z.ZodObject<{
|
|
|
3107
3125
|
size: z.ZodNumber;
|
|
3108
3126
|
}, z.ZodTypeAny, "passthrough">[];
|
|
3109
3127
|
type: "lapis.plugin.release";
|
|
3110
|
-
schemaVersion: 1;
|
|
3111
3128
|
version: string;
|
|
3129
|
+
schemaVersion: 1;
|
|
3112
3130
|
pluginId: string;
|
|
3113
3131
|
channel: "community" | "official";
|
|
3114
3132
|
compatibility: {
|
|
@@ -3200,8 +3218,8 @@ export declare const pluginReleaseManifestSchema: z.ZodObject<{
|
|
|
3200
3218
|
size: z.ZodNumber;
|
|
3201
3219
|
}, z.ZodTypeAny, "passthrough">[];
|
|
3202
3220
|
type: "lapis.plugin.release";
|
|
3203
|
-
schemaVersion: 1;
|
|
3204
3221
|
version: string;
|
|
3222
|
+
schemaVersion: 1;
|
|
3205
3223
|
pluginId: string;
|
|
3206
3224
|
channel: "community" | "official";
|
|
3207
3225
|
compatibility: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { normalizeRegistryCatalogEntry, normalizeRegistryCatalogIndex, normalizeRegistryCatalogDetail, } from "../registry-schema/index.js";
|
|
2
|
-
import { z } from "zod";
|
|
2
|
+
import { z } from "zod/v3";
|
|
3
3
|
import { PluginDistributionError } from "./errors";
|
|
4
4
|
const isoDate = z.string().datetime({ offset: true });
|
|
5
5
|
const utcDate = z
|
|
@@ -174,6 +174,7 @@ export const pluginContributionSummarySchema = z
|
|
|
174
174
|
.array(z
|
|
175
175
|
.object({
|
|
176
176
|
id: nonEmpty,
|
|
177
|
+
fileIcon: z.string().optional(),
|
|
177
178
|
filenamePatterns: z.array(nonEmpty).optional(),
|
|
178
179
|
extensions: z.array(nonEmpty).optional(),
|
|
179
180
|
mimeTypes: z.array(nonEmpty).optional(),
|
|
@@ -42,6 +42,7 @@ export interface PluginContributionSummary {
|
|
|
42
42
|
}>;
|
|
43
43
|
editorViews?: Array<{
|
|
44
44
|
id: string;
|
|
45
|
+
fileIcon?: string;
|
|
45
46
|
filenamePatterns?: string[];
|
|
46
47
|
extensions?: string[];
|
|
47
48
|
mimeTypes?: string[];
|
|
@@ -321,7 +322,10 @@ export interface PluginCompatibilityInput {
|
|
|
321
322
|
appVersion: string;
|
|
322
323
|
platform: PluginPlatform;
|
|
323
324
|
workspaceTrusted?: boolean;
|
|
325
|
+
unavailablePlugins?: PluginHostRestrictions;
|
|
324
326
|
}
|
|
327
|
+
/** App-owned exclusions override older manifests' compatibility claims. */
|
|
328
|
+
export type PluginHostRestrictions = Readonly<Record<string, "desktop-only" | "platform-unsupported">>;
|
|
325
329
|
export interface PluginCompatibilityResult {
|
|
326
330
|
compatible: boolean;
|
|
327
331
|
reasons: Array<"app-version-too-old" | "platform-unsupported" | "desktop-only" | "workspace-trust-required" | "revoked">;
|