@lobehub/market-sdk
Version:
LobeHub Market JavaScript SDK
1,444 lines (1,435 loc) • 195 kB
JavaScript
// src/admin/MarketAdmin.ts
import debug10 from "debug";
// src/core/BaseSDK.ts
import debug from "debug";
import { SignJWT } from "jose";
import urlJoin from "url-join";
// src/core/MarketAPIError.ts
var normalizeErrorDetails = (errorBody) => {
if (!errorBody) return void 0;
if (typeof errorBody.error === "object" && errorBody.error !== null) {
return errorBody.error;
}
if (typeof errorBody.error === "string") {
return {
...errorBody.code ? { code: errorBody.code } : {},
message: errorBody.error
};
}
if (typeof errorBody.message === "string") {
return {
...errorBody.code ? { code: errorBody.code } : {},
message: errorBody.message
};
}
return void 0;
};
var MarketAPIError = class _MarketAPIError extends Error {
constructor(status, statusText, errorBody) {
const errorDetails = normalizeErrorDetails(errorBody);
const errorCode = errorDetails == null ? void 0 : errorDetails.code;
const errorMessage = errorDetails == null ? void 0 : errorDetails.message;
const message = errorMessage || statusText;
super(message);
this.name = "MarketAPIError";
this.status = status;
this.code = errorCode;
this.errorBody = errorBody;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, _MarketAPIError);
}
}
/**
* Check if this is a specific error code
*/
isErrorCode(code) {
return this.code === code;
}
/**
* Get the full error details from the API response
*/
getErrorDetails() {
return normalizeErrorDetails(this.errorBody);
}
/**
* Convert to a plain object for logging or serialization
*/
toJSON() {
return {
code: this.code,
errorBody: this.errorBody,
message: this.message,
name: this.name,
status: this.status
};
}
};
// src/core/version.ts
var SDK_VERSION = "0.31.3";
var SDK_USER_AGENT = `LobeHub-Market-SDK/${SDK_VERSION}`;
// src/core/BaseSDK.ts
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;
const userAgent = options.userAgent || SDK_USER_AGENT;
if (sharedHeaders) {
this.headers = sharedHeaders;
log("Using shared headers object");
} else {
this.headers = {
"Content-Type": "application/json",
"User-Agent": userAgent
};
log("Created new headers object with User-Agent: %s", userAgent);
}
if (apiKey) {
this.headers.Authorization = `Bearer ${apiKey}`;
}
if (this.initialAccessToken) {
this.headers.Authorization = `Bearer ${this.initialAccessToken}`;
}
if (options.trustedClientToken) {
this.headers["x-lobe-trust-token"] = options.trustedClientToken;
log("Trusted client token configured");
}
log("BaseSDK instance created: %O", {
baseUrl: this.baseUrl,
defaultLocale: this.defaultLocale,
hasApiKey: !!apiKey,
hasInitialAccessToken: !!this.initialAccessToken,
hasM2MCredentials: !!this.clientId,
hasSharedTokenState: !!this.sharedTokenState,
hasTrustedClientToken: !!options.trustedClientToken
});
}
/**
* 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 mergedHeaders = {
...this.headers,
...options.headers
};
log("Request headers: %O", mergedHeaders);
const response = await fetch(requestUrl, {
...options,
headers: mergedHeaders
});
if (!response.ok) {
let errorBody;
try {
errorBody = await response.json();
console.error("Request error: %s", JSON.stringify(errorBody));
} catch (e) {
errorBody = void 0;
}
throw new MarketAPIError(response.status, response.statusText, errorBody);
}
log("Request successful: %s", url);
if (response.status === 204) {
return void 0;
}
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/AgentService.ts
import debug2 from "debug";
var log2 = debug2("lobe-market-sdk:admin:agents");
var AgentService = class extends BaseSDK {
/**
* Retrieves a list of agents with admin details
*
* Supports filtering, pagination, and sorting of results.
*
* @param params - Query parameters for filtering and pagination
* @returns Promise resolving to the agent list response with admin details
*/
async getAgents(params = {}) {
log2("Getting agents with params: %O", params);
const queryString = this.buildQueryString(params);
const url = `/admin/agents${queryString}`;
const result = await this.request(url);
log2("Retrieved %d agents", result.data.length);
return result;
}
/**
* Retrieves agents filtered by status
*
* @param status - The status to filter by
* @returns Promise resolving to agents matching the status
*/
async getAgentsByStatus(status) {
log2("Getting agents by status: %s", status);
const result = await this.request(
`/admin/agents/by-status/${status}`
);
log2("Retrieved %d agents with status %s", result.total, status);
return result;
}
/**
* Retrieves agent versions filtered by status
*
* @param status - The status to filter by
* @returns Promise resolving to agent versions matching the status
*/
async getAgentVersionsByStatus(status) {
log2("Getting agent versions by status: %s", status);
const result = await this.request(
`/admin/agents/versions/by-status/${status}`
);
log2("Retrieved %d agent versions with status %s", result.total, status);
return result;
}
/**
* Retrieves a single agent with full admin details
*
* @param id - Agent ID or identifier
* @param options - Optional query parameters
* @returns Promise resolving to the detailed agent information
*/
async getAgent(id, options = {}) {
log2("Getting agent details (admin): %s", id);
const queryString = this.buildQueryString(options);
const result = await this.request(`/admin/agents/${id}${queryString}`);
log2("Retrieved agent: %s", result.identifier);
return result;
}
/**
* Updates agent information
*
* @param id - Agent ID or identifier
* @param data - Agent update data containing fields to update
* @returns Promise resolving to the updated agent
*/
async updateAgent(id, data) {
log2("Updating agent: %s, data: %O", id, data);
const result = await this.request(`/admin/agents/${id}`, {
body: JSON.stringify(data),
method: "PUT"
});
log2("Agent updated successfully");
return result;
}
/**
* Updates agent publication status
*
* @param id - Agent ID or identifier
* @param status - New status to set
* @returns Promise resolving to success response
*/
async updateAgentStatus(id, status) {
log2("Updating agent status: %s to %s", id, status);
const result = await this.request(
`/admin/agents/${id}/status`,
{
body: JSON.stringify({ status }),
method: "PATCH"
}
);
log2("Agent status updated successfully");
return result;
}
/**
* Updates agent visibility
*
* @param id - Agent ID or identifier
* @param visibility - New visibility setting
* @returns Promise resolving to success response
*/
async updateAgentVisibility(id, visibility) {
log2("Updating agent visibility: %s to %s", id, visibility);
const result = await this.request(
`/admin/agents/${id}/visibility`,
{
body: JSON.stringify({ visibility }),
method: "PATCH"
}
);
log2("Agent visibility updated successfully");
return result;
}
/**
* Deletes an agent
*
* @param id - Agent ID or identifier
* @returns Promise resolving to success response
*/
async deleteAgent(id) {
log2("Deleting agent: %s", id);
const result = await this.request(
`/admin/agents/${id}`,
{ method: "DELETE" }
);
log2("Agent deleted successfully");
return result;
}
/**
* Updates status for multiple agents in a single operation
*
* @param ids - Array of agent IDs to update
* @param status - New status to set for all specified agents
* @returns Promise resolving to success response
*/
async batchUpdateAgentStatus(ids, status) {
log2("Batch updating agent status: %O to %s", ids, status);
const result = await this.request(
"/admin/agents/batch/status",
{
body: JSON.stringify({ ids, status }),
method: "PATCH"
}
);
log2("Batch agent status update completed: %d updated", result.updatedCount);
return result;
}
/**
* Deletes multiple agents in a single operation
*
* @param ids - Array of agent IDs to delete
* @returns Promise resolving to success response
*/
async batchDeleteAgents(ids) {
log2("Batch deleting agents: %O", ids);
const result = await this.request(
"/admin/agents/batch/delete",
{
body: JSON.stringify({ ids }),
method: "DELETE"
}
);
log2("Batch agent deletion completed: %d deleted", result.deletedCount);
return result;
}
};
// src/admin/services/AnalysisService.ts
import debug3 from "debug";
var log3 = debug3("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;
log3("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);
log3("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() {
log3("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() {
log3("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() {
log3("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() {
log3("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() {
log3("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() {
log3("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;
log3("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);
log3("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;
log3("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);
log3(
"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;
log3("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);
log3(
"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;
log3("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);
log3(
"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;
log3("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);
log3(
"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 debug4 from "debug";
var log4 = debug4("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) {
log4(`Starting batch plugin import of ${manifests.length} manifests`);
if (ownerId) {
log4(`Using specified owner ID for import: ${ownerId}`);
}
const response = await this.request("/admin/plugins/import", {
body: JSON.stringify({
manifests,
ownerId
}),
method: "POST"
});
log4(
`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) {
log4(
`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"
});
log4(
`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 = {}) {
log4("Getting plugins with params: %O", params);
const queryString = this.buildQueryString(params);
const url = `/admin/plugins${queryString}`;
const result = await this.request(url);
log4("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() {
log4("Getting published plugin identifiers (admin)");
const result = await this.request("/v1/plugins/identifiers");
log4("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) {
log4("Getting plugin details (admin): %d", id);
const result = await this.request(`/admin/plugins/${id}`);
log4("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) {
log4("Getting plugin by GitHub URL: %s", githubUrl);
const queryString = this.buildQueryString({ url: githubUrl });
const result = await this.request(
`/admin/plugins/by-github-url${queryString}`
);
log4("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) {
log4("Updating plugin: %d, data: %O", id, data);
const result = await this.request(`/admin/plugins/${id}`, {
body: JSON.stringify(data),
method: "PUT"
});
log4("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) {
log4("Updating plugin status: %d to %s", id, status);
const result = await this.request(
`/admin/plugins/${id}/status`,
{
body: JSON.stringify({ status }),
method: "PATCH"
}
);
log4("Plugin status updated successfully");
return result;
}
/**
* Deletes a plugin
*
* @param id - Plugin ID
* @returns Promise resolving to success response
*/
async deletePlugin(id) {
log4("Deleting plugin: %d", id);
const result = await this.request(
`/admin/plugins/${id}`,
{ method: "DELETE" }
);
log4("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) {
log4("Getting plugin versions: pluginId=%d", pluginId);
const result = await this.request(`/admin/plugins/${pluginId}/versions`);
log4("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) {
log4("Getting version details: pluginId=%d, versionId=%d", pluginId, versionId);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}`
);
log4("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) {
log4("Getting localizations: pluginId=%s, versionId=%d", pluginId, versionId);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}/localizations`
);
log4("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) {
log4("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"
});
log4("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;
log4(
"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) {
log4(
"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"
}
);
log4("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) {
log4("Deleting version: pluginId=%d, versionId=%d", pluginId, versionId);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}`,
{ method: "DELETE" }
);
log4("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) {
log4("Setting version as latest: pluginId=%d, versionId=%d", pluginId, versionId);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}/latest`,
{ method: "POST" }
);
log4("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) {
log4("Updating plugin visibility: %d to %s", id, visibility);
const result = await this.request(
`/admin/plugins/${id}/visibility`,
{
body: JSON.stringify({ visibility }),
method: "PATCH"
}
);
log4("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) {
log4("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"
}
);
log4("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) {
log4("Batch deleting plugins: %O", ids);
const result = await this.request(
"/admin/plugins/batch/delete",
{
body: JSON.stringify({ ids }),
method: "DELETE"
}
);
log4("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) {
log4(
"Getting version details with deployment options: pluginId=%d, versionId=%d",
pluginId,
versionId
);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}`
);
log4("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) {
log4("Getting deployment options: pluginId=%d, versionId=%d", pluginId, versionId);
const result = await this.request(
`/admin/plugins/${pluginId}/versions/${versionId}/deployment-options`
);
log4("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) {
log4("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"
}
);
log4("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) {
log4(
"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"
}
);
log4("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) {
log4(
"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" }
);
log4("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) {
log4(
"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`
);
log4("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() {
log4("Getting verified plugins without summary");
const result = await this.request("/admin/plugins/verified-without-summary");
log4("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() {
log4("Getting plugins with incomplete i18n");
const result = await this.request("/admin/plugins/incomplete-i18n");
log4("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() {
log4("Getting unclaimed plugins");
const result = await this.request("/admin/plugins/unclaimed");
log4("Retrieved %d unclaimed plugins", result.length);
return result;
}
};
// src/admin/services/SystemDependencyService.ts
import debug5 from "debug";
var log5 = debug5("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() {
log5("Getting all system dependencies");
const result = await this.request(`/admin/plugins/dependencies`);
log5("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) {
log5("Getting system dependency details: %d", id);
const result = await this.request(`/admin/plugins/dependencies/${id}`);
log5("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) {
log5("Creating system dependency: %O", data);
const result = await this.request(`/admin/plugins/dependencies`, {
body: JSON.stringify(data),
method: "POST"
});
log5("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) {
log5("Updating system dependency: %d, data: %O", id, data);
const result = await this.request(`/admin/plugins/dependencies/${id}`, {
body: JSON.stringify(data),
method: "PUT"
});
log5("System dependency updated successfully");
return result;
}
/**
* Deletes a system dependency
*
* @param id - System dependency ID
* @returns Promise resolving to success response
*/
async deleteSystemDependency(id) {
log5("Deleting system dependency: %d", id);
const result = await this.request(
`/admin/plugins/dependencies/${id}`,
{ method: "DELETE" }
);
log5("System dependency deleted successfully");
return result;
}
};
// src/admin/services/SettingsService.ts
import debug6 from "debug";
var log6 = debug6("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) {
log6("Getting setting: %s", key);
const result = await this.request(`/admin/settings/${key}`);
log6("Setting retrieved");
return result;
}
/**
* Creates a new system setting
*
* @param data - Setting creation parameters
* @returns Promise resolving to the created setting
*/
async createSetting(data) {
log6("Creating setting: %O", data);
const result = await this.request("/admin/settings", {
body: JSON.stringify(data),
method: "POST"
});
log6("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) {
log6("Updating setting: %s, data: %O", key, data);
const result = await this.request(`/admin/settings/${key}`, {
body: JSON.stringify(data),
method: "PUT"
});
log6("Setting updated successfully");
return result;
}
/**
* Deletes a setting
*
* @param key - Setting key name
* @returns Promise resolving to success message
*/
async deleteSe