Add Claude Code-compatible marketplace plugin infrastructure: - Registry: types, ID helpers, atomic read/write for marketplaces.json and installed_plugins.json (Claude Code format with version: 2) - Fetcher: classifySource (6 ordered rules), parseMarketplaceCatalog, fetchMarketplace (local sources; git/http stubs for Phase 2) - Resolver + Cache: resolvePluginSource with pathIsWithin containment, cachePlugin, removeCachedPlugin, cleanOrphanedCache - MarketplaceManager: orchestrates add/remove/update marketplaces, install/uninstall/enable plugins, clearPluginRootsCache on mutation - CLI: omp plugin marketplace add|remove|update|list, omp plugin discover, classifyInstallTarget for name@marketplace - Discovery: listClaudePluginRoots reads OMP registry alongside Claude's, OMP authoritative for duplicate plugin IDs - Args: --plugin-dir repeatable flag (parsing only, runtime wiring TBD) - Slash command: /reload-plugins clears fs + roots cache - Test fixtures and 130 tests across 8 test files
30 lines
1015 B
TypeScript
30 lines
1015 B
TypeScript
/**
|
|
* Recursively substitute ${CLAUDE_PLUGIN_ROOT} and ${OMP_PLUGIN_ROOT}
|
|
* with the actual plugin root path in strings, arrays, and plain objects.
|
|
*/
|
|
// Use concatenation to avoid noTemplateCurlyInString lint rule on literal placeholder names
|
|
const CLAUDE_VAR = "$" + "{CLAUDE_PLUGIN_ROOT}";
|
|
const OMP_VAR = "$" + "{OMP_PLUGIN_ROOT}";
|
|
|
|
export function substitutePluginRoot<T>(value: T, rootPath: string): T {
|
|
if (typeof value === "string") {
|
|
return value.replaceAll(CLAUDE_VAR, rootPath).replaceAll(OMP_VAR, rootPath) as T;
|
|
}
|
|
if (Array.isArray(value)) {
|
|
return value.map(v => substitutePluginRoot(v, rootPath)) as T;
|
|
}
|
|
if (value && typeof value === "object") {
|
|
const result: Record<string, unknown> = Object.create(null);
|
|
for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
|
|
Object.defineProperty(result, k, {
|
|
value: substitutePluginRoot(v, rootPath),
|
|
enumerable: true,
|
|
writable: true,
|
|
configurable: true,
|
|
});
|
|
}
|
|
return result as T;
|
|
}
|
|
return value;
|
|
}
|