@larkup/marketplace 0.1.4 → 0.1.5
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 +6 -0
- package/package.json +1 -1
- package/src/tool-installer.ts +9 -0
- package/src/tool-loader.ts +24 -4
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
package/src/tool-installer.ts
CHANGED
|
@@ -147,8 +147,15 @@ export async function checkSystemDeps(toolId: string): Promise<string[]> {
|
|
|
147
147
|
const descriptor = await getToolById(toolId);
|
|
148
148
|
if (!descriptor?.systemDeps?.length) return [];
|
|
149
149
|
|
|
150
|
+
const target = detectDeploymentTarget();
|
|
151
|
+
|
|
150
152
|
const missing: string[] = [];
|
|
151
153
|
for (const dep of descriptor.systemDeps) {
|
|
154
|
+
// A container cannot normally talk to the host Docker daemon. Do not block
|
|
155
|
+
// installation of tools that use Docker only for optional capabilities
|
|
156
|
+
// (for example DOCX/PPTX editing); those capabilities report their own
|
|
157
|
+
// actionable error when actually used.
|
|
158
|
+
if (target === 'docker' && dep === 'docker') continue;
|
|
152
159
|
try {
|
|
153
160
|
await execAsync(`which ${dep}`);
|
|
154
161
|
} catch {
|
|
@@ -492,6 +499,8 @@ export async function uninstallTool(toolId: string): Promise<void> {
|
|
|
492
499
|
|
|
493
500
|
// Refresh registry cache
|
|
494
501
|
invalidateRegistryCache();
|
|
502
|
+
const { unloadTool } = await import('./tool-loader');
|
|
503
|
+
unloadTool(toolId);
|
|
495
504
|
}
|
|
496
505
|
|
|
497
506
|
export async function updateToolConfig(toolId: string, config: Record<string, any>): Promise<void> {
|
package/src/tool-loader.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
1
2
|
import path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
2
4
|
import type { InstalledTool } from './types';
|
|
3
5
|
import { getInstalledTool } from './tool-installer';
|
|
4
6
|
|
|
@@ -37,7 +39,7 @@ export async function loadTool<T = any>(toolId: string): Promise<T | null> {
|
|
|
37
39
|
|
|
38
40
|
try {
|
|
39
41
|
// Determine what to import
|
|
40
|
-
const importPath = resolveImportPath(installed);
|
|
42
|
+
const importPath = await resolveImportPath(installed);
|
|
41
43
|
const mod = await import(/* webpackIgnore: true */ importPath);
|
|
42
44
|
moduleCache.set(toolId, mod);
|
|
43
45
|
return mod as T;
|
|
@@ -54,7 +56,7 @@ export async function loadTool<T = any>(toolId: string): Promise<T | null> {
|
|
|
54
56
|
* - `registry` (npm): import from the isolated node_modules via absolute path
|
|
55
57
|
* - `sandbox`: import from the sandbox tool path
|
|
56
58
|
*/
|
|
57
|
-
function resolveImportPath(installed: InstalledTool): string {
|
|
59
|
+
async function resolveImportPath(installed: InstalledTool): Promise<string> {
|
|
58
60
|
switch (installed.source) {
|
|
59
61
|
case 'local':
|
|
60
62
|
// In monorepo, the package name resolves via pnpm workspace linking
|
|
@@ -62,8 +64,10 @@ function resolveImportPath(installed: InstalledTool): string {
|
|
|
62
64
|
|
|
63
65
|
case 'registry':
|
|
64
66
|
case 'sandbox':
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
+
// Node ESM cannot import a package directory by absolute path. Resolve
|
|
68
|
+
// the package's declared ESM entry so isolated marketplace installs work
|
|
69
|
+
// the same way as a normal package-name import.
|
|
70
|
+
return resolvePackageEntry(installed.resolvedPath);
|
|
67
71
|
|
|
68
72
|
default:
|
|
69
73
|
// Fallback: try package name (backwards compat)
|
|
@@ -71,6 +75,22 @@ function resolveImportPath(installed: InstalledTool): string {
|
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
|
|
78
|
+
async function resolvePackageEntry(packageDir: string): Promise<string> {
|
|
79
|
+
const manifestPath = path.join(packageDir, 'package.json');
|
|
80
|
+
const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8')) as {
|
|
81
|
+
exports?: string | { '.': string | { import?: string; default?: string } };
|
|
82
|
+
main?: string;
|
|
83
|
+
};
|
|
84
|
+
const rootExport =
|
|
85
|
+
typeof manifest.exports === 'object' ? manifest.exports['.'] : manifest.exports;
|
|
86
|
+
const entry =
|
|
87
|
+
(typeof rootExport === 'object' ? rootExport.import ?? rootExport.default : rootExport) ??
|
|
88
|
+
manifest.main ??
|
|
89
|
+
'index.js';
|
|
90
|
+
|
|
91
|
+
return pathToFileURL(path.resolve(packageDir, entry)).href;
|
|
92
|
+
}
|
|
93
|
+
|
|
74
94
|
/**
|
|
75
95
|
* Check if a tool is loaded and available for use.
|
|
76
96
|
*/
|