@vesk/adapter 0.2.9 → 0.2.11
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/client-bundle.d.ts +29 -0
- package/dist/client-bundle.d.ts.map +1 -1
- package/dist/client-bundle.js +333 -52
- package/dist/dev-api.d.ts +78 -0
- package/dist/dev-api.d.ts.map +1 -0
- package/dist/dev-api.js +338 -0
- package/dist/dev-config.d.ts +48 -0
- package/dist/dev-config.d.ts.map +1 -0
- package/dist/dev-config.js +964 -0
- package/dist/dev-server.d.ts +85 -0
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +329 -8
- package/dist/error-codeframe.d.ts +23 -0
- package/dist/error-codeframe.d.ts.map +1 -0
- package/dist/error-codeframe.js +127 -0
- package/dist/error-tips.d.ts +7 -0
- package/dist/error-tips.d.ts.map +1 -0
- package/dist/error-tips.js +91 -0
- package/dist/hmr-utils.d.ts +14 -0
- package/dist/hmr-utils.d.ts.map +1 -0
- package/dist/hmr-utils.js +56 -0
- package/dist/hmr.d.ts +40 -0
- package/dist/hmr.d.ts.map +1 -1
- package/dist/hmr.js +139 -20
- package/dist/index.d.ts +37 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +105 -22
- package/dist/paths.d.ts +8 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +32 -0
- package/dist/platform-handler.d.ts.map +1 -1
- package/dist/platform-handler.js +2 -1
- package/dist/plugins.d.ts +147 -0
- package/dist/plugins.d.ts.map +1 -0
- package/dist/plugins.js +1109 -0
- package/dist/prod-server.d.ts.map +1 -1
- package/dist/prod-server.js +43 -9
- package/dist/ssr-function.d.ts.map +1 -1
- package/dist/ssr-function.js +14 -2
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { mkdirSync, writeFileSync, existsSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { resolve, dirname, relative } from 'node:path';
|
|
2
|
+
import { resolve, dirname, relative, basename } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { cssBlockEnd } from '@vesk/compiler/src/scan';
|
|
5
5
|
import { bundleRuntime } from '@vesk/adapter/src/runtime-bundle';
|
|
@@ -22,6 +22,45 @@ async function resolveCompilerApi(name) {
|
|
|
22
22
|
}
|
|
23
23
|
return import(`@vesk/compiler/src/${name.replace(/\.js$/, '')}`);
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Defensive local mirror of the plugin-manager's `filterActivePlugins`
|
|
27
|
+
* (`@vesk/adapter/src/plugins`): keep when there is no matching record, or the
|
|
28
|
+
* record's `active` is true; drop when a name-matched record is explicitly
|
|
29
|
+
* inactive. Names match CASE-INSENSITIVELY to stay aligned with the manager —
|
|
30
|
+
* it reads/writes state via `eqIgnoreCase`. Only used as the fallback when the
|
|
31
|
+
* plugin-manager module is unavailable during a build; the live build gate in
|
|
32
|
+
* `build()` calls the module's own filter.
|
|
33
|
+
*/
|
|
34
|
+
export function filterActivePlugins(plugins, records) {
|
|
35
|
+
if (!records || records.length === 0)
|
|
36
|
+
return plugins;
|
|
37
|
+
return plugins.filter(p => {
|
|
38
|
+
const record = records.find(r => String(r.name || '').toLowerCase() === String(p.name || '').toLowerCase());
|
|
39
|
+
return record ? record.active : true;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build-time enforcement gate (fallback): an INACTIVE plugin must NEVER ship —
|
|
44
|
+
* it must not have any hook invoked and must not appear in CSS / transformed
|
|
45
|
+
* JS / platform output. Returns the actives-only list. A null/absent state
|
|
46
|
+
* degrades to "all config plugins stay active" (defensive). The live gate in
|
|
47
|
+
* `build()` prefers `@vesk/adapter/src/plugins#filterActivePlugins`; this
|
|
48
|
+
* helper exists for the no-module fallback and for direct unit testing.
|
|
49
|
+
*/
|
|
50
|
+
export function filterPluginsForBuild(plugins, state) {
|
|
51
|
+
if (!state || !Array.isArray(state.plugins))
|
|
52
|
+
return plugins;
|
|
53
|
+
return filterActivePlugins(plugins, state.plugins);
|
|
54
|
+
}
|
|
55
|
+
/** Resolve the `.vesk` dir that owns plugin activation state. `outDir` is
|
|
56
|
+
* `.vesk` itself (versioned builds) or `.vesk/{dev|build}`; in both cases the
|
|
57
|
+
* `.vesk` parent holds `plugins.json`. */
|
|
58
|
+
function veskDirFromOutDir(outDir) {
|
|
59
|
+
const base = basename(outDir);
|
|
60
|
+
if (base === 'dev' || base === 'build')
|
|
61
|
+
return dirname(outDir);
|
|
62
|
+
return outDir;
|
|
63
|
+
}
|
|
25
64
|
export async function build(appDir, options) {
|
|
26
65
|
appDir = resolve(appDir);
|
|
27
66
|
const outDir = resolve(options?.outDir || resolve(appDir, '..', '.vesk'));
|
|
@@ -33,7 +72,41 @@ export async function build(appDir, options) {
|
|
|
33
72
|
const { configureMd } = await import('@vesk/runtime/src/md');
|
|
34
73
|
configureMd(options.md);
|
|
35
74
|
}
|
|
75
|
+
// Build-time plugin activation gate. Read plugin activation from the
|
|
76
|
+
// plugin-manager module (`@vesk/adapter/src/plugins`): `getPluginRecords`
|
|
77
|
+
// returns full `PluginRecord[]` (name + active are the fields we consume);
|
|
78
|
+
// `readPluginState` is the `.vesk/plugins.json` fallback. An INACTIVE plugin
|
|
79
|
+
// must never ship — drop it from `pluginsPipelines`, which is the ONLY list
|
|
80
|
+
// every plugin hook / CSS pipeline iterates. If the module is missing
|
|
81
|
+
// (pre-rebuild) or throws, degrade to all-active.
|
|
82
|
+
const veskDir = veskDirFromOutDir(outDir);
|
|
83
|
+
let pluginsPipelines = plugins;
|
|
84
|
+
try {
|
|
85
|
+
const pluginApi = await import('@vesk/adapter/src/plugins');
|
|
86
|
+
let records = [];
|
|
87
|
+
if (typeof pluginApi.getPluginRecords === 'function') {
|
|
88
|
+
records = pluginApi.getPluginRecords(appDir, veskDir, plugins.map(p => p.name));
|
|
89
|
+
}
|
|
90
|
+
else if (typeof pluginApi.readPluginState === 'function') {
|
|
91
|
+
const st = pluginApi.readPluginState(veskDir);
|
|
92
|
+
records = (st && Array.isArray(st.plugins) ? st.plugins : []);
|
|
93
|
+
}
|
|
94
|
+
if (typeof pluginApi.filterActivePlugins === 'function') {
|
|
95
|
+
pluginsPipelines = pluginApi.filterActivePlugins(plugins, records);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
pluginsPipelines = filterPluginsForBuild(plugins, { version: 1, plugins: records });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
pluginsPipelines = plugins;
|
|
103
|
+
}
|
|
36
104
|
for (const plugin of plugins) {
|
|
105
|
+
if (!pluginsPipelines.includes(plugin)) {
|
|
106
|
+
console.error(`vesk build: skipping inactive plugin "${plugin.name}"`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (const plugin of pluginsPipelines) {
|
|
37
110
|
if (typeof plugin.onBuildStart === 'function') {
|
|
38
111
|
await plugin.onBuildStart();
|
|
39
112
|
}
|
|
@@ -194,33 +267,40 @@ export async function build(appDir, options) {
|
|
|
194
267
|
const userCssTarget = resolve(outDir, 'static', 'global.css');
|
|
195
268
|
writeFileSync(userCssTarget, userCss, 'utf-8');
|
|
196
269
|
console.error(`vesk build: css → static/global.css (${userCss.length} bytes)`);
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
270
|
+
const twCssTarget = resolve(outDir, 'static', '_tailwind.css');
|
|
271
|
+
const isTailwindActive = pluginsPipelines.some((p) => String(p.name).toLowerCase().includes('tailwind'));
|
|
272
|
+
if (!isTailwindActive) {
|
|
273
|
+
writeFileSync(twCssTarget, '', 'utf-8');
|
|
274
|
+
console.error('vesk build: css → static/_tailwind.css (empty, tailwind plugin inactive)');
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
let twCss = cssContent;
|
|
278
|
+
for (const plugin of pluginsPipelines) {
|
|
279
|
+
if (typeof plugin.onCSS === 'function') {
|
|
280
|
+
const result = await plugin.onCSS(twCss, cssSourcePath);
|
|
281
|
+
if (result !== null && typeof result === 'string') {
|
|
282
|
+
twCss = result;
|
|
283
|
+
}
|
|
203
284
|
}
|
|
204
285
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
286
|
+
const hasUnresolvedTailwindImport = /@import\s+['"]tailwindcss['"]/.test(twCss);
|
|
287
|
+
if (hasUnresolvedTailwindImport) {
|
|
288
|
+
const lines = twCss.split('\n').filter(l => !/^\s*@import\s+['"]tailwindcss['"]/.test(l));
|
|
289
|
+
twCss = lines.join('\n').trim();
|
|
290
|
+
if (twCss.length === 0) {
|
|
291
|
+
writeFileSync(twCssTarget, '', 'utf-8');
|
|
292
|
+
console.error('vesk build: css → static/_tailwind.css (empty, tailwind unresolved)');
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
writeFileSync(twCssTarget, twCss, 'utf-8');
|
|
296
|
+
console.error(`vesk build: css → static/_tailwind.css (${twCss.length} bytes, tailwind partially unresolved)`);
|
|
297
|
+
}
|
|
214
298
|
}
|
|
215
299
|
else {
|
|
216
300
|
writeFileSync(twCssTarget, twCss, 'utf-8');
|
|
217
|
-
console.error(`vesk build: css → static/_tailwind.css (${twCss.length} bytes
|
|
301
|
+
console.error(`vesk build: css → static/_tailwind.css (${twCss.length} bytes)`);
|
|
218
302
|
}
|
|
219
303
|
}
|
|
220
|
-
else {
|
|
221
|
-
writeFileSync(twCssTarget, twCss, 'utf-8');
|
|
222
|
-
console.error(`vesk build: css → static/_tailwind.css (${twCss.length} bytes)`);
|
|
223
|
-
}
|
|
224
304
|
}
|
|
225
305
|
let prerenderedRoutes = [];
|
|
226
306
|
if (options?.ssg) {
|
|
@@ -286,7 +366,7 @@ export async function build(appDir, options) {
|
|
|
286
366
|
}
|
|
287
367
|
}
|
|
288
368
|
}
|
|
289
|
-
for (const plugin of
|
|
369
|
+
for (const plugin of pluginsPipelines) {
|
|
290
370
|
if (typeof plugin.onBuildEnd === 'function') {
|
|
291
371
|
await plugin.onBuildEnd();
|
|
292
372
|
}
|
|
@@ -295,3 +375,6 @@ export async function build(appDir, options) {
|
|
|
295
375
|
return { routeTree, apiTree, ssrRoutes, apiRoutes, manifest };
|
|
296
376
|
}
|
|
297
377
|
export { startProdServer } from '@vesk/adapter/src/prod-server';
|
|
378
|
+
// DevTools unified API surface — the shared, exportable connector both the
|
|
379
|
+
// adapter and CLI dev servers route their `/__vesk/*` panel through.
|
|
380
|
+
export { createDevApiRouter, DEFAULT_CAPABILITIES, DEFAULT_COMMAND_ALLOWLIST, CapabilityTable, } from '@vesk/adapter/src/dev-api';
|
package/dist/paths.d.ts
CHANGED
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
* serving / prerender writes so traversal defenses cannot drift.
|
|
6
6
|
*/
|
|
7
7
|
export declare function resolveWithin(baseDir: string, relPath: string): string | null;
|
|
8
|
+
/**
|
|
9
|
+
* Installs `globalThis.__vsk_md_read_file` — the server-side backing of <Md>
|
|
10
|
+
* runtime markdown-file loading. Reads ONLY `.md`/`.markdown` files strictly
|
|
11
|
+
* inside one of the given public dirs (never above them, never other file
|
|
12
|
+
* types) and returns null otherwise, so a client-supplied path can only ever
|
|
13
|
+
* surface a public markdown file, never arbitrary filesystem content.
|
|
14
|
+
*/
|
|
15
|
+
export declare function installMdReadHook(publicDirs: string[]): void;
|
|
8
16
|
/**
|
|
9
17
|
* True when an incoming WebSocket upgrade may connect: same-origin when the
|
|
10
18
|
* client sends an Origin header, always allowed for non-browser clients that
|
package/dist/paths.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM7E;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,CAkB5D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAU5E"}
|
package/dist/paths.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolve, sep } from 'node:path';
|
|
2
|
+
import { existsSync, statSync, readFileSync } from 'node:fs';
|
|
2
3
|
/**
|
|
3
4
|
* Resolves `relPath` against `baseDir` and returns the absolute path ONLY if
|
|
4
5
|
* it stays strictly inside `baseDir` (never the directory itself, never a
|
|
@@ -13,6 +14,37 @@ export function resolveWithin(baseDir, relPath) {
|
|
|
13
14
|
return null;
|
|
14
15
|
return target;
|
|
15
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Installs `globalThis.__vsk_md_read_file` — the server-side backing of <Md>
|
|
19
|
+
* runtime markdown-file loading. Reads ONLY `.md`/`.markdown` files strictly
|
|
20
|
+
* inside one of the given public dirs (never above them, never other file
|
|
21
|
+
* types) and returns null otherwise, so a client-supplied path can only ever
|
|
22
|
+
* surface a public markdown file, never arbitrary filesystem content.
|
|
23
|
+
*/
|
|
24
|
+
export function installMdReadHook(publicDirs) {
|
|
25
|
+
const dirs = publicDirs.map((d) => resolve(d));
|
|
26
|
+
globalThis.__vsk_md_read_file = (p) => {
|
|
27
|
+
for (const dir of dirs) {
|
|
28
|
+
try {
|
|
29
|
+
let rel = String(p);
|
|
30
|
+
while (rel.length > 0 && rel.charCodeAt(0) === 47)
|
|
31
|
+
rel = rel.slice(1); // strip leading '/'
|
|
32
|
+
const abs = resolveWithin(dir, rel);
|
|
33
|
+
if (!abs)
|
|
34
|
+
continue;
|
|
35
|
+
const lower = abs.toLowerCase();
|
|
36
|
+
if (!lower.endsWith('.md') && !lower.endsWith('.markdown'))
|
|
37
|
+
continue;
|
|
38
|
+
if (existsSync(abs) && statSync(abs).isFile())
|
|
39
|
+
return readFileSync(abs, 'utf8');
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
/* try the next public dir */
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
16
48
|
/**
|
|
17
49
|
* True when an incoming WebSocket upgrade may connect: same-origin when the
|
|
18
50
|
* client sends an Origin header, always allowed for non-browser clients that
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-handler.d.ts","sourceRoot":"","sources":["../src/platform-handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAIvE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAMpD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtC;AAQD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"platform-handler.d.ts","sourceRoot":"","sources":["../src/platform-handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAIvE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAMpD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtC;AAQD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAiIjF;AAED,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsFzF;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;CACxB"}
|
package/dist/platform-handler.js
CHANGED
|
@@ -96,7 +96,7 @@ export async function handleRequest(request) {
|
|
|
96
96
|
return new Response(null, { status: 308, headers: { Location: '/_vesk/static/public' + (pathname.endsWith('/') ? pathname + 'index.html' : pathname + '.html') } });
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
let mwCtx = { params: {}, url, locals: {}, cookies: {}, request, set() {}, get() { return undefined; } };
|
|
99
|
+
let mwCtx = { params: {}, url, locals: {}, cookies: {}, request, resolveUrl(u) { return new URL(u, request.url).href; }, set() {}, get() { return undefined; } };
|
|
100
100
|
if (${hasMwLiteral}) {
|
|
101
101
|
mwCtx = {
|
|
102
102
|
request,
|
|
@@ -104,6 +104,7 @@ export async function handleRequest(request) {
|
|
|
104
104
|
url,
|
|
105
105
|
locals: {},
|
|
106
106
|
cookies: typeof parseCookies !== 'undefined' ? parseCookies(request.headers.get('cookie') || '') : {},
|
|
107
|
+
resolveUrl(u) { return new URL(u, request.url).href; },
|
|
107
108
|
set(key, value) { this.locals[key] = value; },
|
|
108
109
|
get(key) { return this.locals[key]; },
|
|
109
110
|
};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev-side plugin ("module") manager for Vesk.
|
|
3
|
+
*
|
|
4
|
+
* The user-facing surface is a Nuxt-like flow: INSTALL/UNINSTALL packages and
|
|
5
|
+
* ACTIVATE/DEACTIVATE plugins. Active/installed state lives in a state file
|
|
6
|
+
* (`.vesk/<PLUGIN_STATE_FILENAME>`) that the build-enforcement agent consumes
|
|
7
|
+
* so that INACTIVE plugins never ship in a production build. The dev panel
|
|
8
|
+
* talks to dev-server HTTP endpoints which call into this module.
|
|
9
|
+
*
|
|
10
|
+
* No compiler/runtime imports: this module only touches node built-ins.
|
|
11
|
+
*/
|
|
12
|
+
export interface PluginRecord {
|
|
13
|
+
name: string;
|
|
14
|
+
package: string;
|
|
15
|
+
path: string | null;
|
|
16
|
+
active: boolean;
|
|
17
|
+
installed: boolean;
|
|
18
|
+
version: string | null;
|
|
19
|
+
latest: string | null;
|
|
20
|
+
description: string | null;
|
|
21
|
+
author: string | null;
|
|
22
|
+
license: string | null;
|
|
23
|
+
homepage: string | null;
|
|
24
|
+
repository: string | null;
|
|
25
|
+
updatedAt: string | null;
|
|
26
|
+
keywords: string[];
|
|
27
|
+
iconUrl: string | null;
|
|
28
|
+
metaSource: 'vesk.meta.json' | 'package.json' | 'none';
|
|
29
|
+
source: 'config' | 'state';
|
|
30
|
+
error: string | null;
|
|
31
|
+
}
|
|
32
|
+
export interface PluginStateFile {
|
|
33
|
+
version: 1;
|
|
34
|
+
plugins: {
|
|
35
|
+
name: string;
|
|
36
|
+
package: string;
|
|
37
|
+
active: boolean;
|
|
38
|
+
}[];
|
|
39
|
+
}
|
|
40
|
+
export interface PluginSearchResult {
|
|
41
|
+
name: string;
|
|
42
|
+
version: string | null;
|
|
43
|
+
description: string | null;
|
|
44
|
+
author: string | null;
|
|
45
|
+
date: string | null;
|
|
46
|
+
keywords: string[];
|
|
47
|
+
links: Record<string, string> | null;
|
|
48
|
+
}
|
|
49
|
+
export interface PluginExportsInfo {
|
|
50
|
+
ok: boolean;
|
|
51
|
+
name: string;
|
|
52
|
+
entry: string | null;
|
|
53
|
+
packageJsonExports: Record<string, string> | null;
|
|
54
|
+
dtsPath: string | null;
|
|
55
|
+
dtsExports: string[];
|
|
56
|
+
}
|
|
57
|
+
export declare const PLUGIN_STATE_FILENAME = "plugins.json";
|
|
58
|
+
/**
|
|
59
|
+
* Read the plugin state file. Tolerates a missing file (returns defaults) and
|
|
60
|
+
* a corrupt file (mismatched version or invalid JSON → reseed to defaults).
|
|
61
|
+
*/
|
|
62
|
+
export declare function readPluginState(veskDir: string): PluginStateFile;
|
|
63
|
+
/** Write the plugin state file. */
|
|
64
|
+
export declare function writePluginState(veskDir: string, state: PluginStateFile): void;
|
|
65
|
+
/**
|
|
66
|
+
* Merge config-declared plugins and state-only entries into a unified record
|
|
67
|
+
* list.
|
|
68
|
+
*
|
|
69
|
+
* Precedence: a state entry (matched by name OR package, case-insensitive)
|
|
70
|
+
* overrides a config plugin's activation. Config plugins default to ACTIVE
|
|
71
|
+
* unless a matching state entry deactivates them. Entries that exist only in
|
|
72
|
+
* the state file are reported as source 'state'. `active` is the resolved
|
|
73
|
+
* build participation — always AND-ed with `installed`.
|
|
74
|
+
*/
|
|
75
|
+
export declare function getPluginRecords(appDir: string, veskDir: string, configPluginNames: string[]): PluginRecord[];
|
|
76
|
+
/** Toggle a plugin's active flag in the state file (matched by name). Returns the new state. */
|
|
77
|
+
export declare function setPluginActive(veskDir: string, name: string, active: boolean): PluginStateFile;
|
|
78
|
+
declare function runNpm(appDir: string, args: string[], timeoutMs?: number): Promise<{
|
|
79
|
+
code: number;
|
|
80
|
+
stdout: string;
|
|
81
|
+
stderr: string;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* Install a package into the app and register it as an active plugin in the
|
|
85
|
+
* state file. The package spec is validated first; then it is verified to be
|
|
86
|
+
* a Vesk plugin (via its package.json, never by importing module code). A
|
|
87
|
+
* plausible-but-unflagged package is still registered but flagged with an
|
|
88
|
+
* `error` noting it may not be a Vesk plugin.
|
|
89
|
+
*/
|
|
90
|
+
export declare function installPlugin(appDir: string, veskDir: string, pkg: string): Promise<PluginRecord>;
|
|
91
|
+
/** Uninstall a package from the app and drop all state entries whose package matches. */
|
|
92
|
+
export declare function uninstallPlugin(appDir: string, veskDir: string, pkg: string): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Update (reinstall at latest) an installed plugin and refresh its state entry.
|
|
95
|
+
* Returns the fresh record. `npm install <pkg>@latest` runs through the
|
|
96
|
+
* `runNpm` seam; the state entry keeps its activation, and the record is
|
|
97
|
+
* re-resolved against the freshly installed package.
|
|
98
|
+
*/
|
|
99
|
+
export declare function updatePlugin(appDir: string, veskDir: string, pkg: string): Promise<PluginRecord>;
|
|
100
|
+
/**
|
|
101
|
+
* Filter the config-declared plugin array down to the active set.
|
|
102
|
+
*
|
|
103
|
+
* Rule (source of truth = records): for each config plugin whose `name`
|
|
104
|
+
* matches an ACTIVE record → keep; matched INACTIVE record → drop (never
|
|
105
|
+
* ships); config plugin with no matching record → keep (defaults active).
|
|
106
|
+
*/
|
|
107
|
+
export declare function filterActivePlugins(configPlugins: unknown[], records: PluginRecord[]): unknown[];
|
|
108
|
+
/** Resolve the icon a plugin declares in `vesk.meta.json` (or conventional
|
|
109
|
+
* `icon.png`/`icon.ico`) from its package dir. Returns the absolute file plus
|
|
110
|
+
* MIME, or null when nothing is declared/present. Never a default image. */
|
|
111
|
+
export declare function findPluginIcon(appDir: string, name: string): {
|
|
112
|
+
file: string;
|
|
113
|
+
mime: string;
|
|
114
|
+
} | null;
|
|
115
|
+
/**
|
|
116
|
+
* Parse top-level `export ...` declarations from a `.d.ts` source into the
|
|
117
|
+
* exported-name list (adapter text processing — no module execution). Wildcard
|
|
118
|
+
* re-exports contribute nothing; `export { a as b }` yields `b`.
|
|
119
|
+
*/
|
|
120
|
+
export declare function parseDtsExports(source: string): string[];
|
|
121
|
+
/**
|
|
122
|
+
* Introspect an installed plugin's public surface WITHOUT importing/executing
|
|
123
|
+
* it: resolved entry (package.json main/module), flat package.json `exports`
|
|
124
|
+
* map, and the `.d.ts`-parsed export names.
|
|
125
|
+
*/
|
|
126
|
+
export declare function introspectPlugin(appDir: string, name: string): PluginExportsInfo;
|
|
127
|
+
type FetchLike = (url: string, init?: {
|
|
128
|
+
signal?: AbortSignal;
|
|
129
|
+
}) => Promise<Response>;
|
|
130
|
+
/**
|
|
131
|
+
* Fill registry-backed fields (latest, updatedAt, and any still-empty
|
|
132
|
+
* author/repository/license/description) on the given records, best-effort and
|
|
133
|
+
* cached so repeated GETs never hang. Returns the same array (mutated).
|
|
134
|
+
*/
|
|
135
|
+
export declare function enrichPluginRecords(records: PluginRecord[]): Promise<PluginRecord[]>;
|
|
136
|
+
/**
|
|
137
|
+
* Search the npm registry (proxied). Empty `q` surfaces a curated `@vesk/*`
|
|
138
|
+
* scope set (`scope:vesk`). Best-effort: an unreachable registry yields `[]`.
|
|
139
|
+
*/
|
|
140
|
+
export declare function searchPlugins(q: string): Promise<PluginSearchResult[]>;
|
|
141
|
+
export declare const __internals: {
|
|
142
|
+
runNpm: typeof runNpm;
|
|
143
|
+
fetch: FetchLike;
|
|
144
|
+
clearRegistryCache: () => void;
|
|
145
|
+
};
|
|
146
|
+
export {};
|
|
147
|
+
//# sourceMappingURL=plugins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"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"}
|