UNPKG

@lobehub/market-sdk

Version:
1,424 lines (1,412 loc) 58.5 kB
// 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. *