@lobehub/market-sdk
Version:
LobeHub Market JavaScript SDK
1,424 lines (1,412 loc) • 58.5 kB
JavaScript
// src/admin/MarketAdmin.ts
import debug8 from "debug";
// src/core/BaseSDK.ts
import debug from "debug";
import { SignJWT } from "jose";
import urlJoin from "url-join";
var log = debug("lobe-market-sdk:core");
var BaseSDK = class {
/**
* Creates a new BaseSDK instance
*
* @param options - Configuration options for the SDK
* @param sharedHeaders - Optional shared headers object for reuse across services
* @param sharedTokenState - Optional shared token state object for reuse across services
*/
constructor(options = {}, sharedHeaders, sharedTokenState) {
this.baseUrl = options.baseURL || process.env.MARKET_BASE_URL || "https://market.lobehub.com";
this.apiBaseUrl = urlJoin(this.baseUrl, "api");
this.oauthBaseUrl = urlJoin(this.baseUrl, "oauth");
this.defaultLocale = options.defaultLocale || "en-US";
this.initialAccessToken = options.accessToken;
this.clientId = options.clientId;
this.clientSecret = options.clientSecret;
this.sharedTokenState = sharedTokenState;
const apiKey = options.apiKey || process.env.MARKET_API_KEY;
if (sharedHeaders) {
this.headers = sharedHeaders;
log("Using shared headers object");
} else {
this.headers = {
"Content-Type": "application/json"
};
log("Created new headers object");
}
if (apiKey) {
this.headers.Authorization = `Bearer ${apiKey}`;
}
if (this.initialAccessToken) {
this.headers.Authorization = `Bearer ${this.initialAccessToken}`;
}
log("BaseSDK instance created: %O", {
baseUrl: this.baseUrl,
defaultLocale: this.defaultLocale,
hasApiKey: !!apiKey,
hasInitialAccessToken: !!this.initialAccessToken,
hasM2MCredentials: !!this.clientId,
hasSharedTokenState: !!this.sharedTokenState
});
}
/**
* Sends an HTTP request to the API and handles the response
*
* @param url - Request URL path (will be appended to baseUrl)
* @param options - Fetch API request options
* @returns Promise resolving to the parsed JSON response
* @throws Error if the request fails
*/
// eslint-disable-next-line no-undef
async request(url, options = {}) {
const requestUrl = urlJoin(this.apiBaseUrl, url);
log("Sending request: %s", requestUrl);
if (!this.initialAccessToken && this.clientId && this.clientSecret) {
await this.setM2MAuthToken();
}
const response = await fetch(requestUrl, {
...options,
headers: {
...this.headers,
...options.headers
}
});
if (!response.ok) {
const errorMsg = `Request failed: ${response.status} ${response.statusText}`;
try {
const errorBody = await response.json();
console.error("Request error: %s", JSON.stringify(errorBody));
throw new Error(`${errorMsg} - ${JSON.stringify(errorBody)}`);
} catch (e) {
throw new Error(errorMsg);
}
}
log("Request successful: %s", url);
return response.json();
}
/**
* Builds a URL query string from a parameters object
*
* @param params - Object containing query parameters
* @returns Formatted query string (including leading ? if params exist)
*/
buildQueryString(params) {
const query = Object.entries(params).filter(([_, value]) => value !== void 0 && value !== null).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`).join("&");
return query ? `?${query}` : "";
}
/**
* Sets an authentication token for API requests
*
* @param token - API authentication token
*/
setAuthToken(token) {
log("Setting authentication token");
this.accessToken = void 0;
this.tokenExpiry = void 0;
if (this.sharedTokenState) {
this.sharedTokenState.accessToken = void 0;
this.sharedTokenState.tokenExpiry = void 0;
}
this.headers.Authorization = `Bearer ${token}`;
}
/**
* Clears the authentication token
*/
clearAuthToken() {
log("Clearing authentication token");
this.accessToken = void 0;
this.tokenExpiry = void 0;
if (this.sharedTokenState) {
this.sharedTokenState.accessToken = void 0;
this.sharedTokenState.tokenExpiry = void 0;
}
delete this.headers.Authorization;
}
/**
* Fetches an M2M access token.
* This method is designed for server-side use cases where you need to manage the token lifecycle
* (e.g., storing it in a cookie).
*
* @returns A promise that resolves to an object containing the access token and its expiry time.
*/
async fetchM2MToken() {
if (!this.clientId || !this.clientSecret) {
throw new Error("clientId and clientSecret are required to fetch an M2M token.");
}
log("Fetching M2M token for server-side use");
const assertion = await this.createClientAssertion();
const tokenData = await this.exchangeTokenForServer(assertion);
log("M2M token fetched successfully");
return {
accessToken: tokenData.access_token,
expiresIn: tokenData.expires_in || 3600
};
}
async createClientAssertion() {
if (!this.clientId || !this.clientSecret) {
throw new Error("Missing clientId or clientSecret for M2M authentication.");
}
const secret = new TextEncoder().encode(this.clientSecret);
const tokenEndpoint = `${this.oauthBaseUrl}/token`;
return await new SignJWT({}).setProtectedHeader({ alg: "HS256" }).setIssuer(this.clientId).setSubject(this.clientId).setAudience(tokenEndpoint).setJti(crypto.randomUUID()).setIssuedAt().setExpirationTime("5m").sign(secret);
}
async exchangeToken(clientAssertion) {
const tokenData = await this.exchangeTokenForServer(clientAssertion);
const expiresInSeconds = tokenData.expires_in || 3600;
this.tokenExpiry = Date.now() + (expiresInSeconds - 60) * 1e3;
return tokenData.access_token;
}
async exchangeTokenForServer(clientAssertion) {
const tokenEndpoint = urlJoin(this.oauthBaseUrl, "token");
log("Exchanging token at endpoint: %s", tokenEndpoint);
const params = new URLSearchParams();
params.append("grant_type", "client_credentials");
params.append(
"client_assertion_type",
"urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
);
params.append("client_assertion", clientAssertion);
const response = await fetch(tokenEndpoint, {
body: params,
headers: { "Content-Type": "application/x-www-form-urlencoded" },
method: "POST"
});
const tokenData = await response.json();
if (!response.ok) {
throw new Error(`Token exchange failed: ${JSON.stringify(tokenData)}`);
}
return tokenData;
}
async setM2MAuthToken() {
var _a, _b, _c;
const currentAccessToken = ((_a = this.sharedTokenState) == null ? void 0 : _a.accessToken) || this.accessToken;
const currentTokenExpiry = ((_b = this.sharedTokenState) == null ? void 0 : _b.tokenExpiry) || this.tokenExpiry;
log(
"Token check: hasSharedState=%s, hasCurrentToken=%s, tokenExpiry=%d, currentTime=%d",
!!this.sharedTokenState,
!!currentAccessToken,
currentTokenExpiry || 0,
Date.now()
);
if (currentAccessToken && currentTokenExpiry && Date.now() < currentTokenExpiry) {
log(
"Using existing M2M access token (expires in %d seconds)",
Math.floor((currentTokenExpiry - Date.now()) / 1e3)
);
this.headers.Authorization = `Bearer ${currentAccessToken}`;
return;
}
if ((_c = this.sharedTokenState) == null ? void 0 : _c.tokenPromise) {
log("Token request already in progress, waiting for completion...");
const token = await this.sharedTokenState.tokenPromise;
this.headers.Authorization = `Bearer ${token}`;
log("Using token from concurrent request");
return;
}
log("Fetching new M2M access token...");
const tokenPromise = this.fetchNewToken();
if (this.sharedTokenState) {
this.sharedTokenState.tokenPromise = tokenPromise;
}
try {
const newAccessToken = await tokenPromise;
this.accessToken = newAccessToken;
this.headers.Authorization = `Bearer ${newAccessToken}`;
if (this.sharedTokenState) {
this.sharedTokenState.accessToken = newAccessToken;
this.sharedTokenState.tokenExpiry = this.tokenExpiry;
this.sharedTokenState.tokenPromise = void 0;
log(
"Updated shared token state (expires in %d seconds)",
Math.floor(((this.tokenExpiry || 0) - Date.now()) / 1e3)
);
}
log("Successfully set new M2M access token");
} catch (error) {
if (this.sharedTokenState) {
this.sharedTokenState.tokenPromise = void 0;
}
throw error;
}
}
async fetchNewToken() {
const assertion = await this.createClientAssertion();
return await this.exchangeToken(assertion);
}
};
// src/admin/services/AnalysisService.ts
import debug2 from "debug";
var log2 = debug2("lobe-market-sdk:admin:analysis");
var AnalysisService = class extends BaseSDK {
/**
* Retrieves market overview statistics
*
* Returns comprehensive market statistics including plugin counts,
* installation metrics, new plugin trends, and rating averages
* with comparison to previous periods.
*
* @param params - Query parameters for the analysis
* @returns Promise resolving to market overview statistics
*/
async getMarketOverview(params = {}) {
const { period = "30d" } = params;
log2("Getting market overview statistics for period: %s", period);
const searchParams = new URLSearchParams();
if (period) {
searchParams.append("period", period);
}
const url = `/admin/analysis/plugin/overview${searchParams.toString() ? `?${searchParams.toString()}` : ""}`;
const result = await this.request(url);
log2("Market overview statistics retrieved successfully: %s", result.data);
return result.data;
}
/**
* Retrieves market overview statistics for 1 day period
*
* Convenience method for getting daily market statistics.
*
* @returns Promise resolving to market overview statistics for 1 day
*/
async getDailyOverview() {
log2("Getting daily market overview");
return this.getMarketOverview({ period: "1d" });
}
/**
* Retrieves market overview statistics for 7 days period
*
* Convenience method for getting weekly market statistics.
*
* @returns Promise resolving to market overview statistics for 7 days
*/
async getWeeklyOverview() {
log2("Getting weekly market overview");
return this.getMarketOverview({ period: "7d" });
}
/**
* Retrieves market overview statistics for 30 days period
*
* Convenience method for getting monthly market statistics.
*
* @returns Promise resolving to market overview statistics for 30 days
*/
async getMonthlyOverview() {
log2("Getting monthly market overview");
return this.getMarketOverview({ period: "30d" });
}
/**
* Retrieves market overview statistics for current natural month
*
* Convenience method for getting current month vs previous month statistics.
*
* @returns Promise resolving to market overview statistics for current month
*/
async getThisMonthOverview() {
log2("Getting this month market overview");
return this.getMarketOverview({ period: "1mo" });
}
/**
* Retrieves market overview statistics for current quarter
*
* Convenience method for getting current quarter vs previous quarter statistics.
*
* @returns Promise resolving to market overview statistics for current quarter
*/
async getQuarterlyOverview() {
log2("Getting quarterly market overview");
return this.getMarketOverview({ period: "3mo" });
}
/**
* Retrieves market overview statistics for current year
*
* Convenience method for getting current year vs previous year statistics.
*
* @returns Promise resolving to market overview statistics for current year
*/
async getYearlyOverview() {
log2("Getting yearly market overview");
return this.getMarketOverview({ period: "1y" });
}
/**
* Retrieves install failure analysis for plugins within a date range
*
* Returns detailed analysis of plugin installation failures including failure counts,
* failure rates, and most common error messages for each plugin with failures.
*
* @param params - Query parameters for the failure analysis
* @returns Promise resolving to install failure analysis data
*/
async getInstallFailureAnalysis(params) {
const { range, limit = 15 } = params;
log2("Getting install failure analysis for range: %o, limit: %d", range, limit);
const searchParams = new URLSearchParams();
searchParams.append("range", JSON.stringify(range));
if (limit !== 15) {
searchParams.append("limit", limit.toString());
}
const url = `/admin/analysis/plugin/install-failure?${searchParams.toString()}`;
const result = await this.request(url);
log2("Install failure analysis retrieved successfully for %d plugins", result.data.length);
return result.data;
}
/**
* Calculates growth rate between current and previous values
*
* Utility method for calculating percentage growth rates from the statistics.
*
* @param current - Current period value
* @param previous - Previous period value
* @returns Growth rate as percentage (e.g., 15.5 for 15.5% growth)
*/
static calculateGrowthRate(current, previous) {
if (previous === 0) return current > 0 ? 100 : 0;
return Math.round((current - previous) / previous * 100 * 10) / 10;
}
/**
* Formats market overview statistics with calculated growth rates
*
* Utility method that enhances the raw statistics with calculated growth rates
* for easier consumption in dashboards and reports.
*
* @param stats - Raw market overview statistics
* @returns Enhanced statistics with growth rate calculations
*/
static formatMarketOverview(stats) {
return {
...stats,
growth: {
devices: this.calculateGrowthRate(stats.devices.count, stats.devices.prevCount),
installs: this.calculateGrowthRate(stats.installs.count, stats.installs.prevCount),
pluginCalls: this.calculateGrowthRate(stats.pluginCalls.count, stats.pluginCalls.prevCount),
plugins: this.calculateGrowthRate(stats.plugins.count, stats.plugins.prevCount)
}
};
}
/**
* Retrieves installation trend statistics for a specified date range
*
* Returns daily installation counts and trends for the specified period
* with optional comparison to a previous period.
*
* @param params - Query parameters including date range and display config
* @returns Promise resolving to installation trend statistics
*/
async getRangeInstalls(params) {
const { display, range, prevRange } = params;
log2("Getting installation trend statistics for range: %s to %s", range[0], range[1]);
const searchParams = new URLSearchParams();
searchParams.append("display", display);
searchParams.append("range", range.join(","));
if (prevRange) {
searchParams.append("prevRange", prevRange.join(","));
}
const url = `/admin/analysis/plugin/range-installs?${searchParams.toString()}`;
const result = await this.request(url);
log2(
"Installation trend statistics retrieved successfully: %d data points",
result.data.data.length
);
return result.data;
}
/**
* Retrieves plugin growth trend statistics for a specified date range
*
* Returns daily plugin creation counts and trends for the specified period
* with optional comparison to a previous period.
*
* @param params - Query parameters including date range and display config
* @returns Promise resolving to plugin growth trend statistics
*/
async getRangePlugins(params) {
const { display, range, prevRange } = params;
log2("Getting plugin growth trend statistics for range: %s to %s", range[0], range[1]);
const searchParams = new URLSearchParams();
searchParams.append("display", display);
searchParams.append("range", range.join(","));
if (prevRange) {
searchParams.append("prevRange", prevRange.join(","));
}
const url = `/admin/analysis/plugin/range-plugins?${searchParams.toString()}`;
const result = await this.request(url);
log2(
"Plugin growth trend statistics retrieved successfully: %d data points",
result.data.data.length
);
return result.data;
}
/**
* Retrieves device growth trend statistics for a specified date range
*
* Note: This is a system-level statistic that tracks device registrations,
* not plugin-specific metrics. It provides daily device registration counts
* and trends for the specified period with optional comparison to a previous period.
*
* @param params - Query parameters including date range and display config
* @returns Promise resolving to device growth trend statistics
*/
async getRangeDevices(params) {
const { display, range, prevRange } = params;
log2("Getting device growth trend statistics for range: %s to %s", range[0], range[1]);
const searchParams = new URLSearchParams();
searchParams.append("display", display);
searchParams.append("range", range.join(","));
if (prevRange) {
searchParams.append("prevRange", prevRange.join(","));
}
const url = `/admin/analysis/system/range-devices?${searchParams.toString()}`;
const result = await this.request(url);
log2(
"Device growth trend statistics retrieved successfully: %d data points",
result.data.data.length
);
return result.data;
}
/**
* Retrieves plugin call trend statistics for a specified date range
*
* Returns daily plugin call counts and trends for the specified period
* with optional comparison to a previous period.
*
* @param params - Query parameters including date range and display config
* @returns Promise resolving to plugin call trend statistics
*/
async getRangeCalls(params) {
const { display, range, prevRange } = params;
log2("Getting plugin call trend statistics for range: %s to %s", range[0], range[1]);
const searchParams = new URLSearchParams();
searchParams.append("display", display);
searchParams.append("range", range.join(","));
if (prevRange) {
searchParams.append("prevRange", prevRange.join(","));
}
const url = `/admin/analysis/plugin/range-calls?${searchParams.toString()}`;
const result = await this.request(url);
log2(
"Plugin call trend statistics retrieved successfully: %d data points",
result.data.data.length
);
return result.data;
}
/**
* Calculates trend growth rate between current and previous period totals
*
* Utility method for calculating percentage growth rates from range statistics.
*
* @param stats - Range statistics with sum and prevSum
* @returns Growth rate as percentage (e.g., 15.5 for 15.5% growth)
*/
static calculateTrendGrowthRate(stats) {
return this.calculateGrowthRate(stats.sum, stats.prevSum);
}
/**
* Retrieves top plugins sorted by specified criteria within a date range
*
* Returns list of plugins sorted by the specified criteria (installs or calls)
* in descending order for the specified date range.
*
* @param params - Query parameters including date range, sort criteria, and limit
* @returns Promise resolving to list of top plugins
*/
async getTopPlugins(params) {
const { range, sortBy = "installs", limit = 10 } = params;
const searchParams = new URLSearchParams();
searchParams.append("range", range.join(","));
searchParams.append("sortBy", sortBy);
searchParams.append("limit", limit.toString());
const url = `/admin/analysis/plugin/top-plugins?${searchParams.toString()}`;
const result = await this.request(url);
return result.data;
}
};
// src/admin/services/PluginService.ts
import debug3 from "debug";
var log3 = debug3("lobe-market-sdk:admin:plugins");
var PluginService = class extends BaseSDK {
/**
* Batch imports plugin manifests using the dedicated import endpoint
*
* This method is intended for use with scripts and bulk import operations.
*
* @param manifests - Array of plugin manifests to import
* @param ownerId - Optional owner ID to associate with the imported plugins
* @returns Promise resolving to the import results with counts of success, skipped, failed, and a list of failed IDs
*/
async importPlugins(manifests, ownerId) {
log3(`Starting batch plugin import of ${manifests.length} manifests`);
if (ownerId) {
log3(`Using specified owner ID for import: ${ownerId}`);
}
const response = await this.request("/admin/plugins/import", {
body: JSON.stringify({
manifests,
ownerId
}),
method: "POST"
});
log3(
`Plugin import completed: ${response.data.success} succeeded, ${response.data.skipped} skipped, ${response.data.failed} failed`
);
return response.data;
}
/**
* Imports plugin internationalization (i18n) data
*
* Allows importing localized content for a specific plugin version.
* This method creates or updates localizations for the specified plugin.
*
* @param params - Plugin i18n import parameters containing identifier, version, and localizations
* @returns Promise resolving to the import results with counts of success and failure
*/
async importPluginI18n(params) {
log3(
`Starting i18n import for plugin ${params.identifier} v${params.version} with ${params.localizations.length} localizations`
);
const response = await this.request("/admin/plugins/import/i18n", {
body: JSON.stringify(params),
method: "POST"
});
log3(
`Plugin i18n import completed: ${response.data.success} succeeded, ${response.data.failed} failed, ${response.data.totalLocalizations} total`
);
return response.data;
}
/**
* Retrieves a list of plugins with admin details
*
* Supports filtering, pagination, and sorting of results.
*
* @param params - Query parameters for filtering and pagination
* @returns Promise resolving to the plugin list response with admin details
*/
async getPlugins(params = {}) {
log3("Getting plugins with params: %O", params);
const queryString = this.buildQueryString(params);
const url = `/admin/plugins${queryString}`;
const result = await this.request(url);
log3("Retrieved %d plugins", result.data.length);
return result;
}
/**
* Retrieves all published plugin identifiers
*
* Returns a lightweight list of all published plugin identifiers without
* full plugin metadata. This is useful for admin operations that need to know
* which plugins are currently published and available to users.
*
* @returns Promise resolving to an array containing identifiers array and last modified time
*/
async getPublishedIdentifiers() {
log3("Getting published plugin identifiers (admin)");
const result = await this.request("/v1/plugins/identifiers");
log3("Retrieved %d published plugin identifiers (admin)", result.length);
return result;
}
/**
* Retrieves a single plugin with full admin details
*
* @param id - Plugin ID or identifier
* @returns Promise resolving to the detailed plugin information with version history
*/
async getPlugin(id) {
log3("Getting plugin details (admin): %d", id);
const result = await this.request(`/admin/plugins/${id}`);
log3("Retrieved plugin with %d versions", result.versions.length);
return result;
}
/**
* Retrieves a plugin by its GitHub repository URL
*
* @param githubUrl - The GitHub repository URL to search for
* @returns Promise resolving to the detailed plugin information with version history
*/
async getPluginByGithubUrl(githubUrl) {
log3("Getting plugin by GitHub URL: %s", githubUrl);
const queryString = this.buildQueryString({ url: githubUrl });
const result = await this.request(
`/admin/plugins/by-github-url${queryString}`
);
log3("Retrieved plugin with %d versions", result.versions.length);
return result;
}
/**
* Updates plugin information
*
* @param id - Plugin ID
* @param data - Plugin update data containing fields to update
* @returns Promise resolving to the updated plugin
*/
async updatePlugin(id, data) {
log3("Updating plugin: %d, data: %O", id, data);
const result = await this.request(`/admin/plugins/${id}`, {
body: JSON.stringify(data),
method: "PUT"
});
log3("Plugin updated successfully");
return result;
}
/**
* Updates plugin publication status
*
* @param id - Plugin ID
* @param status - New status to set
* @returns Promise resolving to success response
*/
async updatePluginStatus(id, status) {
log3("Updating plugin status: %d to %s", id, status);
const result = await this.request(
`/admin/plugins/${id}/status`,
{
body: JSON.stringify({ status }),
method: "PATCH"
}
);
log3("Plugin status updated successfully");
return result;
}
/**
* Deletes a plugin
*
* @param id - Plugin ID
* @returns Promise resolving to success response
*/
async deletePlugin(id) {
log3("Deleting plugin: %d", id);
const result = await this.request(
`/admin/plugins/${id}`,
{ method: "DELETE" }
);
log3("Plugin deleted successfully");
return result;
}
/**
* Retrieves the version history for a plugin
*
* @param pluginId - Plugin ID
* @returns Promise resolving to an array of plugin versions
*/
async getPluginVersions(pluginId) {
log3("Getting plugin versions: pluginId=%d", pluginId);
const result = await this.request(`/admin/plugins/${pluginId}/versions`);
log3("Retrieved %d versions", result.length);
return result;
}
/**
* Retrieves a specific plugin version
*
* @param pluginId - Plugin ID
* @param versionId - Version ID
* @returns Promise resolving to the plugin version details
*/
async getPluginVersion(pluginId, versionId) {
log3("Getting version details: pluginId=%d, versionId=%d", pluginId, versionId);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}`
);
log3("Version details retrieved");
return result;
}
/**
* Retrieves all localizations for a specific plugin version
*
* @param pluginId - Plugin ID or identifier
* @param versionId - Version ID
* @returns Promise resolving to an array of plugin version localizations
*/
async getPluginLocalizations(pluginId, versionId) {
log3("Getting localizations: pluginId=%s, versionId=%d", pluginId, versionId);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}/localizations`
);
log3("Retrieved %d localizations for plugin %s, version %d", result.length, pluginId, versionId);
return result;
}
/**
* Creates a new plugin version with all version-specific data
*
* @param pluginId - Plugin ID
* @param data - Version creation data including all version-specific fields
* @returns Promise resolving to the created plugin version
*/
async createPluginVersion(pluginId, data) {
log3("Creating new plugin version: pluginId=%d, data: %O", pluginId, data);
const result = await this.request(`/admin/plugins/${pluginId}/versions`, {
body: JSON.stringify(data),
method: "POST"
});
log3("Plugin version created successfully: version=%s", data.version);
return result;
}
/**
* Creates a new plugin version from a manifest
* Extracts version data from the manifest for easier creation
*
* @param pluginId - Plugin ID
* @param manifest - Plugin manifest containing all version data
* @param options - Additional options for version creation
* @returns Promise resolving to the created plugin version
*/
async createPluginVersionFromManifest(pluginId, manifest, options = {}) {
var _a, _b, _c, _d, _e, _f, _g;
log3(
"Creating plugin version from manifest: pluginId=%d, version=%s",
pluginId,
manifest.version
);
const versionData = {
author: (_a = manifest.author) == null ? void 0 : _a.name,
authorUrl: (_b = manifest.author) == null ? void 0 : _b.url,
capabilitiesPrompts: (_c = manifest.capabilities) == null ? void 0 : _c.prompts,
capabilitiesResources: (_d = manifest.capabilities) == null ? void 0 : _d.resources,
capabilitiesTools: (_e = manifest.capabilities) == null ? void 0 : _e.tools,
category: manifest.category,
description: manifest.description,
icon: manifest.icon,
isLatest: options.isLatest,
isValidated: options.isValidated,
name: manifest.name,
prompts: manifest.prompts,
readme: (_f = manifest.overview) == null ? void 0 : _f.readme,
resources: manifest.resources,
summary: (_g = manifest.overview) == null ? void 0 : _g.summary,
tags: manifest.tags,
tools: manifest.tools,
version: manifest.version
};
return this.createPluginVersion(pluginId, versionData);
}
/**
* Updates a plugin version with comprehensive version-specific data
*
* @param idOrIdentifier - Plugin ID
* @param versionId - Version ID
* @param data - Version update data including all version-specific fields
* @returns Promise resolving to the updated plugin version
*/
async updatePluginVersion(idOrIdentifier, versionId, data) {
log3(
"Updating plugin version: pluginId=%d, versionId=%d, data: %O",
idOrIdentifier,
versionId,
data
);
const result = await this.request(
`/admin/plugins/${idOrIdentifier}/versions/${versionId}`,
{
body: JSON.stringify(data),
method: "PUT"
}
);
log3("Plugin version updated successfully");
return result;
}
/**
* Deletes a plugin version
*
* @param pluginId - Plugin ID
* @param versionId - Version ID
* @returns Promise resolving to success response
*/
async deletePluginVersion(pluginId, versionId) {
log3("Deleting version: pluginId=%d, versionId=%d", pluginId, versionId);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}`,
{ method: "DELETE" }
);
log3("Plugin version deleted successfully");
return result;
}
/**
* Sets a specific version as the latest version of a plugin
*
* @param pluginId - Plugin ID
* @param versionId - Version ID to set as latest
* @returns Promise resolving to success response
*/
async setPluginVersionAsLatest(pluginId, versionId) {
log3("Setting version as latest: pluginId=%d, versionId=%d", pluginId, versionId);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}/latest`,
{ method: "POST" }
);
log3("Version set as latest successfully");
return result;
}
/**
* Updates plugin visibility
*
* @param id - Plugin ID
* @param visibility - New visibility setting
* @returns Promise resolving to success response
*/
async updatePluginVisibility(id, visibility) {
log3("Updating plugin visibility: %d to %s", id, visibility);
const result = await this.request(
`/admin/plugins/${id}/visibility`,
{
body: JSON.stringify({ visibility }),
method: "PATCH"
}
);
log3("Plugin visibility updated successfully");
return result;
}
/**
* Updates status for multiple plugins in a single operation
*
* @param ids - Array of plugin IDs to update
* @param status - New status to set for all specified plugins
* @returns Promise resolving to success response
*/
async batchUpdatePluginStatus(ids, status) {
log3("Batch updating plugin status: %O to %s", ids, status);
const result = await this.request(
"/admin/plugins/batch/status",
{
body: JSON.stringify({ ids, status }),
method: "PATCH"
}
);
log3("Batch plugin status update completed");
return result;
}
/**
* Deletes multiple plugins in a single operation
*
* @param ids - Array of plugin IDs to delete
* @returns Promise resolving to success response
*/
async batchDeletePlugins(ids) {
log3("Batch deleting plugins: %O", ids);
const result = await this.request(
"/admin/plugins/batch/delete",
{
body: JSON.stringify({ ids }),
method: "DELETE"
}
);
log3("Batch plugin deletion completed");
return result;
}
/**
* Retrieves detailed information about a plugin version including deployment options
*
* @param pluginId - Plugin ID
* @param versionId - Version ID
* @returns Promise resolving to version details with deployment options
*/
async getPluginVersionDetails(pluginId, versionId) {
log3(
"Getting version details with deployment options: pluginId=%d, versionId=%d",
pluginId,
versionId
);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}`
);
log3("Version details with deployment options retrieved");
return result;
}
/**
* Retrieves deployment options for a specific plugin version
*
* @param pluginId - Plugin ID
* @param versionId - Version ID
* @returns Promise resolving to an array of deployment options
*/
async getDeploymentOptions(pluginId, versionId) {
log3("Getting deployment options: pluginId=%d, versionId=%d", pluginId, versionId);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}/deployment-options`
);
log3("Retrieved %d deployment options", result.length);
return result;
}
/**
* Creates a new deployment option for a plugin version
*
* @param pluginId - Plugin ID
* @param versionId - Version ID
* @param data - Deployment option configuration data
* @returns Promise resolving to the created deployment option
*/
async createDeploymentOption(pluginId, versionId, data) {
log3("Creating deployment option: pluginId=%d, versionId=%d", pluginId, versionId);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}/deployment-options`,
{
body: JSON.stringify(data),
method: "POST"
}
);
log3("Deployment option created successfully");
return result;
}
/**
* Updates an existing deployment option
*
* @param pluginId - Plugin ID
* @param versionId - Version ID
* @param optionId - Deployment option ID
* @param data - Updated deployment option configuration
* @returns Promise resolving to the updated deployment option
*/
async updateDeploymentOption(pluginId, versionId, optionId, data) {
log3(
"Updating deployment option: pluginId=%d, versionId=%d, optionId=%d",
pluginId,
versionId,
optionId
);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}/deployment-options/${optionId}`,
{
body: JSON.stringify(data),
method: "PUT"
}
);
log3("Deployment option updated successfully");
return result;
}
/**
* Deletes a deployment option
*
* @param pluginId - Plugin ID
* @param versionId - Version ID
* @param optionId - Deployment option ID
* @returns Promise resolving to success response
*/
async deleteDeploymentOption(pluginId, versionId, optionId) {
log3(
"Deleting deployment option: pluginId=%d, versionId=%d, optionId=%d",
pluginId,
versionId,
optionId
);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}/deployment-options/${optionId}`,
{ method: "DELETE" }
);
log3("Deployment option deleted successfully");
return result;
}
/**
* Retrieves system dependencies for a deployment option
*
* @param pluginId - Plugin ID
* @param versionId - Version ID
* @param optionId - Deployment option ID
* @returns Promise resolving to an array of system dependencies
*/
async getDeploymentOptionSystemDependencies(pluginId, versionId, optionId) {
log3(
"Getting system dependencies: pluginId=%d, versionId=%d, optionId=%d",
pluginId,
versionId,
optionId
);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}/deployment-options/${optionId}/system-dependencies`
);
log3("Retrieved %d system dependencies", result.length);
return result;
}
/**
* Retrieves verified plugins without summary information
*
* Returns plugins that are validated but missing summary data.
*
* @returns Promise resolving to array of plugins with incomplete summary data
*/
async getVerifiedPluginsWithoutSummary() {
log3("Getting verified plugins without summary");
const result = await this.request("/admin/plugins/verified-without-summary");
log3("Retrieved %d verified plugins without summary", result.length);
return result;
}
/**
* Retrieves plugins with incomplete internationalization
*
* Returns plugins where pluginVersionLocalizations has only 1 entry.
*
* @returns Promise resolving to an array of plugins with incomplete i18n
*/
async getIncompleteI18nPlugins() {
log3("Getting plugins with incomplete i18n");
const result = await this.request("/admin/plugins/incomplete-i18n");
log3("Retrieved %d plugins with incomplete i18n", result.length);
return result;
}
/**
* Retrieves unclaimed plugins
*
* Returns plugins where isClaimed is false, containing only ID and identifier.
*
* @returns Promise resolving to an array of unclaimed plugins with basic info
*/
async getUnclaimedPlugins() {
log3("Getting unclaimed plugins");
const result = await this.request("/admin/plugins/unclaimed");
log3("Retrieved %d unclaimed plugins", result.length);
return result;
}
};
// src/admin/services/SystemDependencyService.ts
import debug4 from "debug";
var log4 = debug4("lobe-market-sdk:admin:dependency");
var SystemDependencyService = class extends BaseSDK {
/**
* Retrieves all system dependencies
*
* Gets a list of all defined system dependencies that plugins may require.
*
* @returns Promise resolving to an array of system dependencies
*/
async getSystemDependencies() {
log4("Getting all system dependencies");
const result = await this.request(`/admin/plugins/dependencies`);
log4("Retrieved %d system dependencies", result.length);
return result;
}
/**
* Retrieves a specific system dependency by ID
*
* @param id - System dependency ID
* @returns Promise resolving to the system dependency details
*/
async getSystemDependency(id) {
log4("Getting system dependency details: %d", id);
const result = await this.request(`/admin/plugins/dependencies/${id}`);
log4("System dependency details retrieved");
return result;
}
/**
* Creates a new system dependency
*
* @param data - System dependency creation data
* @returns Promise resolving to the created system dependency
*/
async createSystemDependency(data) {
log4("Creating system dependency: %O", data);
const result = await this.request(`/admin/plugins/dependencies`, {
body: JSON.stringify(data),
method: "POST"
});
log4("System dependency created successfully");
return result;
}
/**
* Updates an existing system dependency
*
* @param id - System dependency ID
* @param data - System dependency update data
* @returns Promise resolving to the updated system dependency
*/
async updateSystemDependency(id, data) {
log4("Updating system dependency: %d, data: %O", id, data);
const result = await this.request(`/admin/plugins/dependencies/${id}`, {
body: JSON.stringify(data),
method: "PUT"
});
log4("System dependency updated successfully");
return result;
}
/**
* Deletes a system dependency
*
* @param id - System dependency ID
* @returns Promise resolving to success response
*/
async deleteSystemDependency(id) {
log4("Deleting system dependency: %d", id);
const result = await this.request(
`/admin/plugins/dependencies/${id}`,
{ method: "DELETE" }
);
log4("System dependency deleted successfully");
return result;
}
};
// src/admin/services/SettingsService.ts
import debug5 from "debug";
var log5 = debug5("lobe-market-sdk:admin:settings");
var SettingsService = class extends BaseSDK {
/**
* Retrieves all system settings
*
* Returns a consolidated map of all settings with typed values
* for known setting keys.
*
* @returns Promise resolving to the settings map
*/
async getSettings() {
return await this.request("/admin/settings");
}
/**
* Retrieves a specific setting by key
*
* @param key - Setting key name
* @returns Promise resolving to the setting details
*/
async getSettingByKey(key) {
log5("Getting setting: %s", key);
const result = await this.request(`/admin/settings/${key}`);
log5("Setting retrieved");
return result;
}
/**
* Creates a new system setting
*
* @param data - Setting creation parameters
* @returns Promise resolving to the created setting
*/
async createSetting(data) {
log5("Creating setting: %O", data);
const result = await this.request("/admin/settings", {
body: JSON.stringify(data),
method: "POST"
});
log5("Setting created successfully");
return result;
}
/**
* Updates an existing setting
*
* @param key - Setting key name
* @param data - Setting update parameters
* @returns Promise resolving to the updated setting
*/
async updateSetting(key, data) {
log5("Updating setting: %s, data: %O", key, data);
const result = await this.request(`/admin/settings/${key}`, {
body: JSON.stringify(data),
method: "PUT"
});
log5("Setting updated successfully");
return result;
}
/**
* Deletes a setting
*
* @param key - Setting key name
* @returns Promise resolving to success message
*/
async deleteSetting(key) {
log5("Deleting setting: %s", key);
const result = await this.request(`/admin/settings/${key}`, {
method: "DELETE"
});
log5("Setting deleted successfully");
return result;
}
};
// src/admin/services/ReviewService.ts
import debug6 from "debug";
var log6 = debug6("lobe-market-sdk:admin:review");
var ReviewService = class extends BaseSDK {
/**
* Retrieves a list of reviews with filtering options
*
* @param params - Query parameters for filtering and pagination
* @returns Promise resolving to the review list response
*/
async getReviews(params = {}) {
log6("Getting reviews with params: %O", params);
const queryString = this.buildQueryString(params);
const url = `/admin/reviews${queryString ? `?${queryString}` : ""}`;
const result = await this.request(url);
log6("Retrieved %d reviews", result.data.length);
return result;
}
/**
* Retrieves a specific review by ID
*
* @param id - Review ID
* @returns Promise resolving to the review details
*/
async getReviewById(id) {
log6("Getting review details: %d", id);
const result = await this.request(`/admin/reviews/${id}`);
log6("Review details retrieved");
return result;
}
/**
* Updates a review's status and comment
*
* @param id - Review ID
* @param data - Update parameters containing new status and optional comment
* @returns Promise resolving to the updated review
*/
async updateReview(id, data) {
log6("Updating review: %d, data: %O", id, data);
const result = await this.request(`/admin/reviews/${id}`, {
body: JSON.stringify(data),
method: "PUT"
});
log6("Review updated successfully");
return result;
}
/**
* Retrieves the review history for a specific plugin
*
* @param pluginId - Plugin ID
* @returns Promise resolving to an array of reviews for the plugin
*/
async getPluginReviews(pluginId) {
log6("Getting plugin reviews: pluginId=%d", pluginId);
const result = await this.request(`/admin/reviews/plugin/${pluginId}`);
log6("Retrieved %d reviews for plugin", result.data.length);
return result;
}
};
// src/admin/services/PluginEnvService.ts
import debug7 from "debug";
var log7 = debug7("lobe-market-sdk:admin:plugin-env");
var PluginEnvService = class extends BaseSDK {
/**
* Retrieves a paginated list of plugin environment variables
*
* @param params - Query parameters for filtering and pagination
* @returns Promise resolving to the env list response
*/
async getPluginEnvs(params = {}) {
log7("Getting plugin envs with params: %O", params);
const queryString = this.buildQueryString(params);
const url = `/admin/plugins/env${queryString}`;
const result = await this.request(url);
log7("Retrieved %d plugin envs", result.data.length);
return result;
}
/**
* Retrieves a single plugin environment variable by ID
*
* @param id - Env ID
* @returns Promise resolving to the env item
*/
async getPluginEnv(id) {
log7("Getting plugin env: %d", id);
const result = await this.request(`/admin/plugins/env/${id}`);
log7("Retrieved plugin env: %d", id);
return result;
}
/**
* Creates a new plugin environment variable
*
* @param data - Env creation data
* @returns Promise resolving to the created env item
*/
async createPluginEnv(data) {
log7("Creating plugin env: %O", data);
const result = await this.request(`/admin/plugins/env`, {
body: JSON.stringify(data),
method: "POST"
});
log7("Plugin env created successfully");
return result;
}
/**
* Updates a plugin environment variable
*
* @param id - Env ID
* @param data - Env update data
* @returns Promise resolving to the updated env item
*/
async updatePluginEnv(id, data) {
log7("Updating plugin env: %d, data: %O", id, data);
const result = await this.request(`/admin/plugins/env/${id}`, {
body: JSON.stringify(data),
method: "PUT"
});
log7("Plugin env updated successfully");
return result;
}
/**
* Deletes a plugin environment variable
*
* @param id - Env ID
* @returns Promise resolving to success response
*/
async deletePluginEnv(id) {
log7("Deleting plugin env: %d", id);
const result = await this.request(`/admin/plugins/env/${id}`, {
method: "DELETE"
});
log7("Plugin env deleted successfully");
return result;
}
/**
* Batch import plugin environment variables
*
* @param data - Batch import data, format: { [plugin: string]: { [envKey: string]: string } }
* @returns Promise resolving to import result
*/
async importPluginEnvs(data) {
log7("Batch importing plugin envs: %O", data);
const result = await this.request(`/admin/plugins/env/import`, {
body: JSON.stringify(data),
method: "POST"
});
log7("Batch import completed: %d envs imported", result.success);
return result;
}
};
// src/admin/MarketAdmin.ts
var log8 = debug8("lobe-market-sdk:admin");
var MarketAdmin = class extends BaseSDK {
/**
* Creates a new MarketAdmin instance
*
* @param options - Configuration options for the SDK
*/
constructor(options = {}) {
const apiKey = options.apiKey || process.env.MARKET_ADMIN_API_KEY;
const sharedTokenState = {
accessToken: void 0,
tokenExpiry: void 0
};
super({ ...options, apiKey }, void 0, sharedTokenState);
log8("MarketAdmin instance created");
this.analysis = new AnalysisService(options, this.headers, sharedTokenState);
this.plugins = new PluginService(options, this.headers, sharedTokenState);
this.reviews = new ReviewService(options, this.headers, sharedTokenState);
this.settings = new SettingsService(options, this.headers, sharedTokenState);
this.dependencies = new SystemDependencyService(options, this.headers, sharedTokenState);
this.env = new PluginEnvService(options, this.headers, sharedTokenState);
}
};
// src/market/market-sdk.ts
import debug11 from "debug";
// src/market/services/DiscoveryService.ts
import debug9 from "debug";
import urlJoin2 from "url-join";
var log9 = debug9("lobe-market-sdk:discovery");
var DiscoveryService = class extends BaseSDK {
/**
* Retrieves the service discovery document
*
* This document contains information about available API endpoints,
* authentication methods, and other capabilities of the Market API.
* The result is cached after the first request to improve performance.
*
* @returns Promise resolving to the service discovery document
*/
async getDiscoveryDocument() {
log9("Fetching discovery document");
if (this.discoveryDoc) {
log9("Returning cached discovery document");
return this.discoveryDoc;
}
const res = await fetch(urlJoin2(this.baseUrl, "/.well-known/discovery"));
if (!res.ok) {
throw new Error(await res.text());
}
this.discoveryDoc = await res.json();
log9("Discovery document successfully fetched");
return this.discoveryDoc;
}
};
// src/market/services/PluginsService.ts
import debug10 from "debug";
var log10 = debug10("lobe-market-sdk:plugins");
var PluginsService = class extends BaseSDK {
/**
* Retrieves a list of plugins from the marketplace
*
* Supports filtering, pagination, and localization of results.
*