@voiden/runner 0.1.0-beta.6 → 2.1.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/dist/cliElectron.d.ts +1 -1
- package/dist/index.js +138 -17
- package/dist/index.js.map +1 -1
- package/dist/plugins/community.d.ts +4 -3
- package/dist/plugins/community.d.ts.map +1 -1
- package/dist/plugins/community.js +23 -19
- package/dist/plugins/community.js.map +1 -1
- package/dist/plugins/loader.d.ts +8 -0
- package/dist/plugins/loader.d.ts.map +1 -1
- package/dist/plugins/loader.js +78 -7
- package/dist/plugins/loader.js.map +1 -1
- package/dist/plugins/registry.d.ts +26 -21
- package/dist/plugins/registry.d.ts.map +1 -1
- package/dist/plugins/registry.js +69 -46
- package/dist/plugins/registry.js.map +1 -1
- package/dist/plugins/registryCache.d.ts +28 -0
- package/dist/plugins/registryCache.d.ts.map +1 -0
- package/dist/plugins/registryCache.js +95 -0
- package/dist/plugins/registryCache.js.map +1 -0
- package/dist/plugins/store.d.ts +6 -1
- package/dist/plugins/store.d.ts.map +1 -1
- package/dist/plugins/store.js +21 -1
- package/dist/plugins/store.js.map +1 -1
- package/dist/plugins/updateCheck.d.ts +14 -0
- package/dist/plugins/updateCheck.d.ts.map +1 -0
- package/dist/plugins/updateCheck.js +46 -0
- package/dist/plugins/updateCheck.js.map +1 -0
- package/dist/runner.d.ts +1 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +19 -2
- package/dist/runner.js.map +1 -1
- package/dist/runtimeVars.d.ts +5 -0
- package/dist/runtimeVars.d.ts.map +1 -1
- package/dist/runtimeVars.js +36 -2
- package/dist/runtimeVars.js.map +1 -1
- package/package.json +10 -5
package/dist/plugins/loader.d.ts
CHANGED
|
@@ -13,5 +13,13 @@
|
|
|
13
13
|
* If a plugin is disabled, its runner.ts never loads, so no handler is ever
|
|
14
14
|
* registered — requests that require that plugin fail gracefully.
|
|
15
15
|
*/
|
|
16
|
+
/**
|
|
17
|
+
* Download a core plugin runner bundle from its GitHub repo release, pinned to
|
|
18
|
+
* the version published in the registry — mirrors the Electron app's
|
|
19
|
+
* `getExtensionFiles` (which fetches `releases/tags/v{version}`), so the
|
|
20
|
+
* version we record locally always matches what we actually downloaded and
|
|
21
|
+
* `plugin update` can detect drift against the registry.
|
|
22
|
+
*/
|
|
23
|
+
export declare function downloadCoreRunner(pluginId: string, repo: string, assetName: string, version: string, verbose: boolean): Promise<boolean>;
|
|
16
24
|
export declare function loadEnabledPlugins(verbose?: boolean, skipPlugins?: ReadonlySet<string>): Promise<string[]>;
|
|
17
25
|
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAiC/I;AAgED,wBAAsB,kBAAkB,CACtC,OAAO,UAAQ,EACf,WAAW,GAAE,WAAW,CAAC,MAAM,CAAa,GAC3C,OAAO,CAAC,MAAM,EAAE,CAAC,CAyEnB"}
|
package/dist/plugins/loader.js
CHANGED
|
@@ -14,12 +14,58 @@
|
|
|
14
14
|
* registered — requests that require that plugin fail gracefully.
|
|
15
15
|
*/
|
|
16
16
|
import { requestOrchestrator, hookRegistry } from '@voiden/executors';
|
|
17
|
-
import {
|
|
17
|
+
import { getCorePlugins, hasCoreRunner, getCoreRunnerImportUrl, getCoreRunnerPath } from './registry.js';
|
|
18
18
|
import { fetchCommunityPlugins, findCommunityPlugin, hasCommunityRunner, getCommunityRunnerImportUrl, } from './community.js';
|
|
19
19
|
import { createHeadlessPluginContext } from '../headlessContext.js';
|
|
20
20
|
import { clearSchemas } from '../blockSchemaRegistry.js';
|
|
21
|
-
import { readStore } from './store.js';
|
|
22
|
-
import
|
|
21
|
+
import { readStore, setPluginVersion } from './store.js';
|
|
22
|
+
import * as https from 'https';
|
|
23
|
+
import { mkdirSync, createWriteStream } from 'fs';
|
|
24
|
+
import { dirname } from 'path';
|
|
25
|
+
/**
|
|
26
|
+
* Download a core plugin runner bundle from its GitHub repo release, pinned to
|
|
27
|
+
* the version published in the registry — mirrors the Electron app's
|
|
28
|
+
* `getExtensionFiles` (which fetches `releases/tags/v{version}`), so the
|
|
29
|
+
* version we record locally always matches what we actually downloaded and
|
|
30
|
+
* `plugin update` can detect drift against the registry.
|
|
31
|
+
*/
|
|
32
|
+
export async function downloadCoreRunner(pluginId, repo, assetName, version, verbose) {
|
|
33
|
+
const destPath = getCoreRunnerPath(pluginId);
|
|
34
|
+
mkdirSync(dirname(destPath), { recursive: true });
|
|
35
|
+
const apiUrl = `https://api.github.com/repos/${repo}/releases/tags/v${version}`;
|
|
36
|
+
const meta = await new Promise((resolve, reject) => {
|
|
37
|
+
https.get(apiUrl, { headers: { 'User-Agent': 'voiden-runner', 'Accept': 'application/vnd.github+json' } }, res => {
|
|
38
|
+
let data = '';
|
|
39
|
+
res.on('data', c => data += c);
|
|
40
|
+
res.on('end', () => {
|
|
41
|
+
try {
|
|
42
|
+
resolve(JSON.parse(data));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
reject(new Error('Invalid JSON from GitHub API'));
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}).on('error', reject);
|
|
49
|
+
});
|
|
50
|
+
const asset = (meta.assets ?? []).find((a) => a.name === assetName);
|
|
51
|
+
if (!asset) {
|
|
52
|
+
if (verbose)
|
|
53
|
+
console.warn(` [plugins] No "${assetName}" asset in release v${version} of ${repo}`);
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
// Download the asset
|
|
57
|
+
await new Promise((resolve, reject) => {
|
|
58
|
+
const file = createWriteStream(destPath);
|
|
59
|
+
https.get(asset.browser_download_url, { headers: { 'User-Agent': 'voiden-runner' } }, res => {
|
|
60
|
+
res.pipe(file);
|
|
61
|
+
file.on('finish', () => { file.close(); resolve(); });
|
|
62
|
+
}).on('error', reject);
|
|
63
|
+
});
|
|
64
|
+
setPluginVersion(pluginId, version);
|
|
65
|
+
if (verbose)
|
|
66
|
+
console.log(` [plugins] Downloaded ${assetName}@${version} → ${destPath}`);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
23
69
|
// ─── Per-plugin enabled check ─────────────────────────────────────────────────
|
|
24
70
|
// Core plugins default to enabled; only skip if explicitly set to false in store.
|
|
25
71
|
function isCorePluginEnabled(name) {
|
|
@@ -37,7 +83,18 @@ function isCommunityPluginEnabled(name) {
|
|
|
37
83
|
async function loadPlugin(pluginPath, pluginName, verbose) {
|
|
38
84
|
try {
|
|
39
85
|
const mod = await import(pluginPath);
|
|
40
|
-
|
|
86
|
+
// Runner bundles are esbuild-compiled CJS (`export default factory` →
|
|
87
|
+
// `module.exports = { __esModule: true, default: factory }`). Node's native
|
|
88
|
+
// ESM loader then wraps that whole CJS object as `mod.default`, so the real
|
|
89
|
+
// factory ends up nested at `mod.default.default`. Unwrap until we hit a
|
|
90
|
+
// function or run out of `__esModule`-marked layers.
|
|
91
|
+
let factory = mod.default ?? mod;
|
|
92
|
+
while (factory &&
|
|
93
|
+
typeof factory === 'object' &&
|
|
94
|
+
factory.__esModule &&
|
|
95
|
+
'default' in factory) {
|
|
96
|
+
factory = factory.default;
|
|
97
|
+
}
|
|
41
98
|
if (typeof factory !== 'function') {
|
|
42
99
|
if (verbose) {
|
|
43
100
|
console.warn(` [plugins] "${pluginName}" export is not a factory function — skipping`);
|
|
@@ -67,7 +124,9 @@ export async function loadEnabledPlugins(verbose = false, skipPlugins = new Set(
|
|
|
67
124
|
const loaded = [];
|
|
68
125
|
// ── Core plugins ──────────────────────────────────────────────────────────
|
|
69
126
|
// Core plugins default to enabled but can be disabled via ~/.voiden/plugins.json.
|
|
70
|
-
|
|
127
|
+
// Runner bundles are downloaded on-demand from each plugin's GitHub repo.
|
|
128
|
+
const corePlugins = await getCorePlugins();
|
|
129
|
+
for (const def of corePlugins) {
|
|
71
130
|
if (skipPlugins.has(def.name)) {
|
|
72
131
|
if (verbose)
|
|
73
132
|
console.log(` [plugins] Skipping plugin (--no-scripts): ${def.name}`);
|
|
@@ -78,7 +137,18 @@ export async function loadEnabledPlugins(verbose = false, skipPlugins = new Set(
|
|
|
78
137
|
console.log(` [plugins] Skipping disabled core plugin: ${def.name}`);
|
|
79
138
|
continue;
|
|
80
139
|
}
|
|
81
|
-
|
|
140
|
+
// Auto-download runner bundle if not cached locally
|
|
141
|
+
if (!hasCoreRunner(def.name)) {
|
|
142
|
+
if (verbose)
|
|
143
|
+
console.log(` [plugins] Downloading runner for ${def.name} from ${def.repo}...`);
|
|
144
|
+
await downloadCoreRunner(def.name, def.repo, def.runnerAsset, def.version, verbose);
|
|
145
|
+
}
|
|
146
|
+
if (!hasCoreRunner(def.name)) {
|
|
147
|
+
if (verbose)
|
|
148
|
+
console.warn(` [plugins] Runner not available for ${def.name} — skipping`);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const ok = await loadPlugin(getCoreRunnerImportUrl(def.name), def.name, verbose);
|
|
82
152
|
if (ok)
|
|
83
153
|
loaded.push(def.name);
|
|
84
154
|
}
|
|
@@ -93,12 +163,13 @@ export async function loadEnabledPlugins(verbose = false, skipPlugins = new Set(
|
|
|
93
163
|
catch {
|
|
94
164
|
communityPlugins = [];
|
|
95
165
|
}
|
|
166
|
+
const corePluginNames = new Set(corePlugins.map((p) => p.name));
|
|
96
167
|
const store = readStore();
|
|
97
168
|
for (const [name, record] of Object.entries(store.installedPlugins)) {
|
|
98
169
|
if (!isCommunityPluginEnabled(name))
|
|
99
170
|
continue;
|
|
100
171
|
// Skip if it's a core plugin (already handled above)
|
|
101
|
-
if (
|
|
172
|
+
if (corePluginNames.has(name))
|
|
102
173
|
continue;
|
|
103
174
|
const commDef = findCommunityPlugin(name, communityPlugins);
|
|
104
175
|
if (!commDef) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACxG,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACxD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAc,MAAM,IAAI,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAE9B;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAgB,EAAE,IAAY,EAAE,SAAiB,EAAE,OAAe,EAAE,OAAgB;IAC3H,MAAM,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IAC5C,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAEjD,MAAM,MAAM,GAAG,gCAAgC,IAAI,mBAAmB,OAAO,EAAE,CAAA;IAC/E,MAAM,IAAI,GAAQ,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtD,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,6BAA6B,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE;YAC/G,IAAI,IAAI,GAAG,EAAE,CAAA;YACb,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAA;YAC9B,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,IAAI,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;gBAAC,CAAC;gBAAC,MAAM,CAAC;oBAAC,MAAM,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAA;gBAAC,CAAC;YAC/F,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IACxB,CAAC,CAAC,CAAA;IAEF,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;IACxE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,OAAO;YAAE,OAAO,CAAC,IAAI,CAAC,mBAAmB,SAAS,uBAAuB,OAAO,OAAO,IAAI,EAAE,CAAC,CAAA;QAClG,OAAO,KAAK,CAAA;IACd,CAAC;IAED,qBAAqB;IACrB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAA;QACxC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE,EAAE,OAAO,EAAE,EAAE,YAAY,EAAE,eAAe,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE;YAC1F,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACd,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;QACtD,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IACxB,CAAC,CAAC,CAAA;IAEF,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACnC,IAAI,OAAO;QAAE,OAAO,CAAC,GAAG,CAAC,0BAA0B,SAAS,IAAI,OAAO,MAAM,QAAQ,EAAE,CAAC,CAAA;IACxF,OAAO,IAAI,CAAA;AACb,CAAC;AAED,iFAAiF;AAEjF,kFAAkF;AAClF,SAAS,mBAAmB,CAAC,IAAY;IACvC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAA;IACzB,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAA;IAC3C,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAA;AACrD,CAAC;AAED,uEAAuE;AACvE,SAAS,wBAAwB,CAAC,IAAY;IAC5C,MAAM,KAAK,GAAG,SAAS,EAAE,CAAA;IACzB,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAA;IAC3C,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,CAAA;AAC/C,CAAC;AAED,iFAAiF;AAEjF,KAAK,UAAU,UAAU,CACvB,UAAkB,EAClB,UAAkB,EAClB,OAAgB;IAEhB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAA;QACpC,sEAAsE;QACtE,4EAA4E;QAC5E,4EAA4E;QAC5E,yEAAyE;QACzE,qDAAqD;QACrD,IAAI,OAAO,GAAY,GAAG,CAAC,OAAO,IAAI,GAAG,CAAA;QACzC,OACE,OAAO;YACP,OAAO,OAAO,KAAK,QAAQ;YAC1B,OAAe,CAAC,UAAU;YAC3B,SAAS,IAAK,OAAe,EAC7B,CAAC;YACD,OAAO,GAAI,OAAe,CAAC,OAAO,CAAA;QACpC,CAAC;QAED,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;YAClC,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,IAAI,CAAC,gBAAgB,UAAU,+CAA+C,CAAC,CAAA;YACzF,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;QAED,MAAM,GAAG,GAAG,2BAA2B,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;QAC5D,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAA;QAE3B,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,8BAA8B,UAAU,EAAE,CAAC,CAAA;QACpE,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,+BAA+B,UAAU,MAAM,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC5F,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAO,GAAG,KAAK,EACf,cAAmC,IAAI,GAAG,EAAE;IAE5C,kEAAkE;IAClE,6EAA6E;IAC7E,mBAAmB,CAAC,KAAK,EAAE,CAAA;IAC3B,YAAY,CAAC,QAAQ,EAAE,CAAA;IACvB,YAAY,EAAE,CAAA;IAEd,MAAM,MAAM,GAAa,EAAE,CAAA;IAE3B,6EAA6E;IAC7E,kFAAkF;IAClF,0EAA0E;IAC1E,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAA;IAC1C,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,IAAI,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,+CAA+C,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;YACnF,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,IAAI,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,8CAA8C,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;YAClF,SAAQ;QACV,CAAC;QAED,oDAAoD;QACpD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,IAAI,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,sCAAsC,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,IAAI,KAAK,CAAC,CAAA;YAC9F,MAAM,kBAAkB,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACrF,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,IAAI,OAAO;gBAAE,OAAO,CAAC,IAAI,CAAC,wCAAwC,GAAG,CAAC,IAAI,aAAa,CAAC,CAAA;YACxF,SAAQ;QACV,CAAC;QAED,MAAM,EAAE,GAAG,MAAM,UAAU,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAChF,IAAI,EAAE;YAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC/B,CAAC;IAED,8EAA8E;IAC9E,yEAAyE;IACzE,0EAA0E;IAC1E,uCAAuC;IACvC,IAAI,gBAAmE,CAAA;IACvE,IAAI,CAAC;QACH,gBAAgB,GAAG,MAAM,qBAAqB,EAAE,CAAA;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB,GAAG,EAAE,CAAA;IACvB,CAAC;IAED,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IAC/D,MAAM,KAAK,GAAG,SAAS,EAAE,CAAA;IACzB,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC;YAAE,SAAQ;QAE7C,qDAAqD;QACrD,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAQ;QAEvC,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAA;QAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,OAAO;gBAAE,OAAO,CAAC,IAAI,CAAC,+BAA+B,IAAI,0CAA0C,CAAC,CAAA;YACxG,SAAQ;QACV,CAAC;QAED,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,IAAI,OAAO;gBAAE,OAAO,CAAC,IAAI,CAAC,iCAAiC,IAAI,0DAA0D,IAAI,EAAE,CAAC,CAAA;YAChI,SAAQ;QACV,CAAC;QAED,MAAM,EAAE,GAAG,MAAM,UAAU,CAAC,2BAA2B,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;QAC7E,IAAI,EAAE;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -1,30 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Plugin Registry
|
|
2
|
+
* Core Plugin Registry
|
|
3
3
|
*
|
|
4
|
-
* Derives the list of runner-capable core
|
|
5
|
-
*
|
|
4
|
+
* Derives the list of runner-capable core plugins from the same
|
|
5
|
+
* VoidenHQ/plugin-registry `extensions.json` that the Electron app reads
|
|
6
|
+
* (see registryCache.ts) — no separate static snapshot to keep in sync.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* ID_TO_FOLDER handles the few cases where the registry ID differs from the
|
|
14
|
-
* folder name inside @voiden/core-extensions/src/.
|
|
8
|
+
* A core plugin is runner-capable when the registry marks it `hasRunner: true`
|
|
9
|
+
* (set by plugin-registry maintainers when the plugin publishes a headless
|
|
10
|
+
* runner.js bundle). Each such plugin is built and released as
|
|
11
|
+
* {pluginId}-runner.js in its own GitHub repo (VoidenHQ/plugin-{dir}).
|
|
12
|
+
* voiden-runner downloads and caches these files the same way community
|
|
13
|
+
* plugins do: ~/.voiden/extensions/{id}/runner.js
|
|
15
14
|
*/
|
|
15
|
+
export declare function getCoreRunnerPath(pluginId: string): string;
|
|
16
|
+
export declare function hasCoreRunner(pluginId: string): boolean;
|
|
17
|
+
export declare function getCoreRunnerImportUrl(pluginId: string): string;
|
|
16
18
|
export interface PluginDefinition {
|
|
17
|
-
/** Registry ID (e.g. 'voiden-rest-api'
|
|
19
|
+
/** Registry ID (e.g. 'voiden-rest-api') */
|
|
18
20
|
name: string;
|
|
19
21
|
description: string;
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
/** GitHub repo slug for downloading the runner bundle */
|
|
23
|
+
repo: string;
|
|
24
|
+
/** Asset name in the GitHub release (e.g. 'voiden-rest-api-runner.js') */
|
|
25
|
+
runnerAsset: string;
|
|
26
|
+
/** Latest version published in the registry — used for update detection */
|
|
27
|
+
version: string;
|
|
28
|
+
/** Import URL — file:// path to cached runner.js, or undefined if not cached */
|
|
29
|
+
pluginPath: string | undefined;
|
|
26
30
|
}
|
|
27
|
-
|
|
28
|
-
export declare function
|
|
29
|
-
export declare function
|
|
31
|
+
/** Core, runner-capable plugins — derived live from the plugin registry. */
|
|
32
|
+
export declare function getCorePlugins(): Promise<PluginDefinition[]>;
|
|
33
|
+
export declare function findPlugin(name: string): Promise<PluginDefinition | undefined>;
|
|
34
|
+
export declare function listPluginNames(): Promise<string[]>;
|
|
30
35
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/plugins/registry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/plugins/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAuBH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ/D;AAID,MAAM,WAAW,gBAAgB;IAC/B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAA;IACZ,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAA;IACnB,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAA;IACf,gFAAgF;IAChF,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;AAaD,4EAA4E;AAC5E,wBAAsB,cAAc,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAKlE;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAGpF;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAEzD"}
|
package/dist/plugins/registry.js
CHANGED
|
@@ -1,52 +1,75 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Plugin Registry
|
|
2
|
+
* Core Plugin Registry
|
|
3
3
|
*
|
|
4
|
-
* Derives the list of runner-capable core
|
|
5
|
-
*
|
|
4
|
+
* Derives the list of runner-capable core plugins from the same
|
|
5
|
+
* VoidenHQ/plugin-registry `extensions.json` that the Electron app reads
|
|
6
|
+
* (see registryCache.ts) — no separate static snapshot to keep in sync.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* ID_TO_FOLDER handles the few cases where the registry ID differs from the
|
|
14
|
-
* folder name inside @voiden/core-extensions/src/.
|
|
8
|
+
* A core plugin is runner-capable when the registry marks it `hasRunner: true`
|
|
9
|
+
* (set by plugin-registry maintainers when the plugin publishes a headless
|
|
10
|
+
* runner.js bundle). Each such plugin is built and released as
|
|
11
|
+
* {pluginId}-runner.js in its own GitHub repo (VoidenHQ/plugin-{dir}).
|
|
12
|
+
* voiden-runner downloads and caches these files the same way community
|
|
13
|
+
* plugins do: ~/.voiden/extensions/{id}/runner.js
|
|
15
14
|
*/
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
'
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
import { homedir } from 'os';
|
|
17
|
+
import { existsSync } from 'fs';
|
|
18
|
+
import { pathToFileURL } from 'url';
|
|
19
|
+
import { getRegistry } from './registryCache.js';
|
|
20
|
+
// ─── Runner paths (priority: bundled-at-build-time > user cache > download) ───
|
|
21
|
+
const RUNNER_CACHE_DIR = join(homedir(), '.voiden', 'extensions');
|
|
22
|
+
// Bundled runners pre-downloaded by cleanup.sh at Voiden build time
|
|
23
|
+
function getBundledRunnerPath(pluginId) {
|
|
24
|
+
const candidates = [
|
|
25
|
+
join(new URL('.', import.meta.url).pathname, '../../../../packages/voiden-runner/bundled-runners', `${pluginId}-runner.js`),
|
|
26
|
+
join(new URL('.', import.meta.url).pathname, '../../../bundled-runners', `${pluginId}-runner.js`),
|
|
27
|
+
];
|
|
28
|
+
for (const p of candidates) {
|
|
29
|
+
if (existsSync(p))
|
|
30
|
+
return p;
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
export function getCoreRunnerPath(pluginId) {
|
|
35
|
+
return join(RUNNER_CACHE_DIR, pluginId, 'runner.js');
|
|
36
|
+
}
|
|
37
|
+
export function hasCoreRunner(pluginId) {
|
|
38
|
+
return !!getBundledRunnerPath(pluginId) || existsSync(getCoreRunnerPath(pluginId));
|
|
39
|
+
}
|
|
40
|
+
export function getCoreRunnerImportUrl(pluginId) {
|
|
41
|
+
// User cache (~/.voiden/extensions) takes priority over the bundled snapshot —
|
|
42
|
+
// mirrors Electron's OTA-cache-over-bundled resolution (seedBundledPluginsToCache /
|
|
43
|
+
// isOtaCached) — so `plugin update` can actually supersede a bundled runner.
|
|
44
|
+
if (existsSync(getCoreRunnerPath(pluginId)))
|
|
45
|
+
return pathToFileURL(getCoreRunnerPath(pluginId)).href;
|
|
46
|
+
const bundled = getBundledRunnerPath(pluginId);
|
|
47
|
+
if (bundled)
|
|
48
|
+
return pathToFileURL(bundled).href;
|
|
49
|
+
return pathToFileURL(getCoreRunnerPath(pluginId)).href;
|
|
50
|
+
}
|
|
51
|
+
function toPluginDefinition(entry) {
|
|
52
|
+
return {
|
|
53
|
+
name: entry.id,
|
|
54
|
+
description: entry.description,
|
|
55
|
+
repo: entry.repo,
|
|
56
|
+
runnerAsset: entry.runnerAsset ?? `${entry.id}-runner.js`,
|
|
57
|
+
version: entry.version,
|
|
58
|
+
pluginPath: hasCoreRunner(entry.id) ? getCoreRunnerImportUrl(entry.id) : undefined,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** Core, runner-capable plugins — derived live from the plugin registry. */
|
|
62
|
+
export async function getCorePlugins() {
|
|
63
|
+
const entries = await getRegistry();
|
|
64
|
+
return entries
|
|
65
|
+
.filter((p) => p.type === 'core' && p.hasRunner)
|
|
66
|
+
.map(toPluginDefinition);
|
|
67
|
+
}
|
|
68
|
+
export async function findPlugin(name) {
|
|
69
|
+
const plugins = await getCorePlugins();
|
|
70
|
+
return plugins.find((p) => p.name === name);
|
|
71
|
+
}
|
|
72
|
+
export async function listPluginNames() {
|
|
73
|
+
return (await getCorePlugins()).map((p) => p.name);
|
|
51
74
|
}
|
|
52
75
|
//# sourceMappingURL=registry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/plugins/registry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/plugins/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared registry cache — fetches the community plugin-registry's
|
|
3
|
+
* `extensions.json` (the same source the Electron app reads, see
|
|
4
|
+
* apps/electron/src/main/extension/extensionFetcher.ts) and caches it so
|
|
5
|
+
* `voiden-runner` doesn't refetch on every invocation and keeps working
|
|
6
|
+
* offline after the first successful fetch.
|
|
7
|
+
*/
|
|
8
|
+
export interface RegistryEntry {
|
|
9
|
+
type: 'core' | 'community';
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
author: string;
|
|
14
|
+
version: string;
|
|
15
|
+
repo: string;
|
|
16
|
+
hasRunner?: boolean;
|
|
17
|
+
runnerAsset?: string;
|
|
18
|
+
icon?: string;
|
|
19
|
+
voidenVersion?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Returns the full plugin-registry catalogue (core + community plugins).
|
|
23
|
+
* Cached in-memory for the process lifetime and on-disk for 24h. If the
|
|
24
|
+
* registry is unreachable, falls back to the last known-good on-disk cache
|
|
25
|
+
* (even if stale) so `run` keeps working offline.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getRegistry(): Promise<RegistryEntry[]>;
|
|
28
|
+
//# sourceMappingURL=registryCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registryCache.d.ts","sourceRoot":"","sources":["../../src/plugins/registryCache.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAmDD;;;;;GAKG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAsB5D"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared registry cache — fetches the community plugin-registry's
|
|
3
|
+
* `extensions.json` (the same source the Electron app reads, see
|
|
4
|
+
* apps/electron/src/main/extension/extensionFetcher.ts) and caches it so
|
|
5
|
+
* `voiden-runner` doesn't refetch on every invocation and keeps working
|
|
6
|
+
* offline after the first successful fetch.
|
|
7
|
+
*/
|
|
8
|
+
import * as https from 'https';
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
10
|
+
import { join } from 'path';
|
|
11
|
+
import { homedir } from 'os';
|
|
12
|
+
const REGISTRY_URL = 'https://raw.githubusercontent.com/VoidenHQ/plugin-registry/main/extensions.json';
|
|
13
|
+
const CACHE_PATH = join(homedir(), '.voiden', 'registry-cache.json');
|
|
14
|
+
const CACHE_TTL = 24 * 60 * 60 * 1000; // 1 day
|
|
15
|
+
let memCache;
|
|
16
|
+
function httpsGetText(url, maxRedirects = 5) {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
const options = {
|
|
19
|
+
headers: {
|
|
20
|
+
'User-Agent': 'voiden-runner',
|
|
21
|
+
'Accept': 'application/vnd.github.v3+json',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
function doGet(u, hops) {
|
|
25
|
+
https.get(u, options, (res) => {
|
|
26
|
+
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
27
|
+
if (hops <= 0) {
|
|
28
|
+
reject(new Error('Too many redirects'));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
doGet(res.headers.location, hops - 1);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (res.statusCode && res.statusCode >= 400) {
|
|
35
|
+
reject(new Error(`HTTP ${res.statusCode}`));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
let data = '';
|
|
39
|
+
res.on('data', (c) => (data += c));
|
|
40
|
+
res.on('end', () => resolve(data));
|
|
41
|
+
res.on('error', reject);
|
|
42
|
+
}).on('error', reject);
|
|
43
|
+
}
|
|
44
|
+
doGet(url, maxRedirects);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function readDiskCache() {
|
|
48
|
+
if (!existsSync(CACHE_PATH))
|
|
49
|
+
return undefined;
|
|
50
|
+
try {
|
|
51
|
+
return JSON.parse(readFileSync(CACHE_PATH, 'utf-8'));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function writeDiskCache(entries) {
|
|
58
|
+
try {
|
|
59
|
+
mkdirSync(join(homedir(), '.voiden'), { recursive: true });
|
|
60
|
+
writeFileSync(CACHE_PATH, JSON.stringify({ fetchedAt: Date.now(), entries }, null, 2), 'utf-8');
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Best-effort — the on-disk cache is an offline optimization, not a requirement.
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns the full plugin-registry catalogue (core + community plugins).
|
|
68
|
+
* Cached in-memory for the process lifetime and on-disk for 24h. If the
|
|
69
|
+
* registry is unreachable, falls back to the last known-good on-disk cache
|
|
70
|
+
* (even if stale) so `run` keeps working offline.
|
|
71
|
+
*/
|
|
72
|
+
export async function getRegistry() {
|
|
73
|
+
if (memCache)
|
|
74
|
+
return memCache;
|
|
75
|
+
const disk = readDiskCache();
|
|
76
|
+
if (disk && Date.now() - disk.fetchedAt < CACHE_TTL) {
|
|
77
|
+
memCache = disk.entries;
|
|
78
|
+
return memCache;
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const raw = await httpsGetText(REGISTRY_URL);
|
|
82
|
+
const entries = JSON.parse(raw);
|
|
83
|
+
memCache = entries;
|
|
84
|
+
writeDiskCache(entries);
|
|
85
|
+
return entries;
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
if (disk) {
|
|
89
|
+
memCache = disk.entries;
|
|
90
|
+
return memCache;
|
|
91
|
+
}
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=registryCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registryCache.js","sourceRoot":"","sources":["../../src/plugins/registryCache.ts"],"names":[],"mappings":"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"}
|
package/dist/plugins/store.d.ts
CHANGED
|
@@ -5,13 +5,18 @@ export interface InstalledPlugin {
|
|
|
5
5
|
name: string;
|
|
6
6
|
enabled: boolean;
|
|
7
7
|
installedAt: string;
|
|
8
|
+
/** Runner bundle version that was downloaded — compared against the registry to detect updates */
|
|
9
|
+
version?: string;
|
|
8
10
|
}
|
|
9
11
|
export interface PluginStore {
|
|
10
12
|
installedPlugins: Record<string, InstalledPlugin>;
|
|
11
13
|
}
|
|
12
14
|
export declare const STORE_DIR: string;
|
|
13
15
|
export declare function readStore(): PluginStore;
|
|
14
|
-
export declare function installPlugin(name: string): boolean;
|
|
16
|
+
export declare function installPlugin(name: string, version?: string): boolean;
|
|
17
|
+
/** Records the runner bundle version for an installed plugin (used by `plugin update`). */
|
|
18
|
+
export declare function setPluginVersion(name: string, version: string): void;
|
|
19
|
+
export declare function getInstalledVersion(name: string): string | undefined;
|
|
15
20
|
export declare function uninstallPlugin(name: string): boolean;
|
|
16
21
|
export declare function setPluginEnabled(name: string, enabled: boolean): void;
|
|
17
22
|
export declare function getEnabledPlugins(): InstalledPlugin[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/plugins/store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/plugins/store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,kGAAkG;IAClG,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CAClD;AAED,eAAO,MAAM,SAAS,QAA6B,CAAA;AAOnD,wBAAgB,SAAS,IAAI,WAAW,CAOvC;AAOD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAarE;AAED,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAapE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEpE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMrD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAYrE;AAED,wBAAgB,iBAAiB,IAAI,eAAe,EAAE,CAGrD;AAED,wBAAgB,sBAAsB,IAAI,eAAe,EAAE,CAE1D"}
|
package/dist/plugins/store.js
CHANGED
|
@@ -23,7 +23,7 @@ function writeStore(store) {
|
|
|
23
23
|
mkdirSync(STORE_DIR, { recursive: true });
|
|
24
24
|
writeFileSync(STORE_PATH, JSON.stringify(store, null, 2) + '\n', 'utf-8');
|
|
25
25
|
}
|
|
26
|
-
export function installPlugin(name) {
|
|
26
|
+
export function installPlugin(name, version) {
|
|
27
27
|
const store = readStore();
|
|
28
28
|
const alreadyInstalled = !!store.installedPlugins[name];
|
|
29
29
|
if (!alreadyInstalled) {
|
|
@@ -31,11 +31,31 @@ export function installPlugin(name) {
|
|
|
31
31
|
name,
|
|
32
32
|
enabled: true,
|
|
33
33
|
installedAt: new Date().toISOString(),
|
|
34
|
+
version,
|
|
34
35
|
};
|
|
35
36
|
writeStore(store);
|
|
36
37
|
}
|
|
37
38
|
return !alreadyInstalled;
|
|
38
39
|
}
|
|
40
|
+
/** Records the runner bundle version for an installed plugin (used by `plugin update`). */
|
|
41
|
+
export function setPluginVersion(name, version) {
|
|
42
|
+
const store = readStore();
|
|
43
|
+
if (!store.installedPlugins[name]) {
|
|
44
|
+
store.installedPlugins[name] = {
|
|
45
|
+
name,
|
|
46
|
+
enabled: true,
|
|
47
|
+
installedAt: new Date().toISOString(),
|
|
48
|
+
version,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
store.installedPlugins[name].version = version;
|
|
53
|
+
}
|
|
54
|
+
writeStore(store);
|
|
55
|
+
}
|
|
56
|
+
export function getInstalledVersion(name) {
|
|
57
|
+
return readStore().installedPlugins[name]?.version;
|
|
58
|
+
}
|
|
39
59
|
export function uninstallPlugin(name) {
|
|
40
60
|
const store = readStore();
|
|
41
61
|
if (!store.installedPlugins[name])
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/plugins/store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAA;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/plugins/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin update detection — compares each installed plugin's recorded runner
|
|
3
|
+
* version (store.ts) against the latest version published in the shared
|
|
4
|
+
* plugin-registry (registryCache.ts). Used by `plugin update` and the
|
|
5
|
+
* post-command update notice in index.ts.
|
|
6
|
+
*/
|
|
7
|
+
export interface PluginUpdateInfo {
|
|
8
|
+
id: string;
|
|
9
|
+
type: 'core' | 'community';
|
|
10
|
+
installedVersion: string;
|
|
11
|
+
latestVersion: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function checkForPluginUpdates(): Promise<PluginUpdateInfo[]>;
|
|
14
|
+
//# sourceMappingURL=updateCheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updateCheck.d.ts","sourceRoot":"","sources":["../../src/plugins/updateCheck.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;IAC1B,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,EAAE,MAAM,CAAA;CACtB;AAeD,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAsBzE"}
|