UNPKG

@remcostoeten/fync

Version:

A unified TypeScript library for easy access to popular APIs (GitHub, Spotify, GitLab, etc.)

314 lines (313 loc) 11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NPM = NPM; var _npmClient = require("./services/npm-client"); /** * Creates a new NPM Registry API client * * @param config - Optional configuration for the NPM client * @param config.cache - Enable response caching (default: false) * @param config.cacheTTL - Cache time-to-live in milliseconds (default: 300000) * @param config.baseUrl - Custom NPM registry URL (default: https://registry.npmjs.org) * @param config.timeout - Request timeout in milliseconds (default: 30000) * * @returns NPM client instance with access to packages, search, downloads, users, orgs, and tags * * @example * ```typescript * const npm = NPM({ cache: true, cacheTTL: 600000 }); * * // Get package information * const reactInfo = await npm.package('react').get(); * * // Search for packages * const results = await npm.search.packages('typescript'); * * // Get download statistics * const downloads = await npm.downloads.package('react', 'last-week'); * ``` */ function NPM(config) { const client = (0, _npmClient.createNpmClient)(config); function createPackageClient(packageName) { const packageBase = client[encodeURIComponent(packageName)]; return { get: () => packageBase.get(), version: version => createVersionClient(packageName, version), latest: async () => { const packageInfo = await packageBase.get(); const latestVersion = packageInfo["dist-tags"]?.latest; if (!latestVersion) { throw new Error(`No latest version found for ${packageName}`); } return packageInfo.versions[latestVersion]; }, versions: async () => { const packageInfo = await packageBase.get(); return packageInfo.versions; }, downloads: { last: period => client.downloads.point[`last-${period}`][encodeURIComponent(packageName)].get(), range: (start, end) => client.downloads.range[`${start}:${end}`][encodeURIComponent(packageName)].get() }, // Advanced features vulnerabilities: async () => { // Use npm audit API (hypothetical endpoint) try { const auditClient = (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://registry.npmjs.org/-/npm/v1/security" }); return await auditClient.advisories[packageName].get(); } catch { return []; } }, audit: async () => { // Use npm audit API const auditClient = (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://registry.npmjs.org/-/npm/v1/security" }); return await auditClient.audits.quick[packageName].get(); }, size: async () => { // Get package size info (bundlephobia-like data) const packageInfo = await packageBase.get(); const latestVersion = packageInfo["dist-tags"]?.latest; if (!latestVersion) { throw new Error(`No latest version found for ${packageName}`); } // Calculate size from dist info const version = packageInfo.versions[latestVersion]; const files = version.files?.length || 0; return { size: 0, // Would need external service gzip: 0, // Would need external service files }; }, deprecation: async () => { const packageInfo = await packageBase.get(); // Check for deprecated versions const deprecatedVersions = []; for (const [version, versionInfo] of Object.entries(packageInfo.versions)) { if ("deprecated" in versionInfo && versionInfo.deprecated) { deprecatedVersions.push(version); } } if (deprecatedVersions.length === 0) { return null; } return { versions: deprecatedVersions, message: "Package has deprecated versions", time: new Date().toISOString() }; }, distTags: async () => { const packageInfo = await packageBase.get(); return packageInfo["dist-tags"]; }, collaborators: async () => { // Get package maintainers/collaborators const packageInfo = await packageBase.get(); return packageInfo.maintainers.map(maintainer => ({ name: maintainer.name, email: maintainer.email, access: "write" })); }, isDeprecated: async () => { const packageInfo = await packageBase.get(); const latestVersion = packageInfo["dist-tags"]?.latest; if (!latestVersion) return false; const version = packageInfo.versions[latestVersion]; return !!("deprecated" in version && version.deprecated); }, bundleAnalysis: async () => { // Get bundle analysis (would integrate with bundlephobia API) const packageInfo = await packageBase.get(); const latestVersion = packageInfo["dist-tags"]?.latest; if (!latestVersion) { throw new Error(`No latest version found for ${packageName}`); } const version = packageInfo.versions[latestVersion]; const dependencies = Object.keys(version.dependencies || {}); return { size: 0, // Would need bundlephobia integration gzip: 0, // Would need bundlephobia integration modules: dependencies.length, dependencies }; }, chain: packageBase }; } function createVersionClient(packageName, version) { const versionBase = client[encodeURIComponent(packageName)][version]; return { get: () => versionBase.get(), chain: versionBase }; } const searchClient = { packages: (query, options) => { const params = { text: query, ...options?.params }; if (options?.size) params.size = options.size; if (options?.from) params.from = options.from; if (options?.quality) params.quality = options.quality; if (options?.popularity) params.popularity = options.popularity; if (options?.maintenance) params.maintenance = options.maintenance; // NPM search uses different base URL const searchClient = (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://registry.npmjs.org/-/v1" }); return searchClient.search.get({ ...options, params }); }, chain: client["-"].v1.search }; const downloadsClient = { package: (packageName, period = "last-week") => { // NPM downloads API uses different base URL const downloadsApiClient = (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://api.npmjs.org" }); return downloadsApiClient.downloads.point[period][encodeURIComponent(packageName)].get(); }, packages: async (packageNames, period = "last-week") => { const downloadsApiClient = (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://api.npmjs.org" }); const packageList = packageNames.map(encodeURIComponent).join(","); const response = await downloadsApiClient.downloads.point[period][packageList].get(); return response; }, range: (packageName, start, end) => { const downloadsApiClient = (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://api.npmjs.org" }); return downloadsApiClient.downloads.range[`${start}:${end}`][encodeURIComponent(packageName)].get(); }, chain: (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://api.npmjs.org" }).downloads }; function createUserClient(username) { // NPM user API uses different base URL const npmApiClient = (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://registry.npmjs.org/-/user" }); const userBase = npmApiClient[username]; return { get: () => userBase.get(), packages: async options => { // Search packages by author const searchClient = (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://registry.npmjs.org/-/v1" }); const searchResults = await searchClient.search.get({ ...options, params: { text: `author:${username}`, size: 250, ...options?.params } }); // Convert search results to package info const packages = await Promise.all(searchResults.objects.map(result => client[encodeURIComponent(result.package.name)].get())); return packages; }, chain: userBase }; } function createOrgClient(orgName) { // NPM org API uses different base URL const npmApiClient = (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://registry.npmjs.org/-/org" }); const orgBase = npmApiClient[orgName]; return { get: () => orgBase.get(), packages: async options => { // Search packages by scope const searchClient = (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://registry.npmjs.org/-/v1" }); const searchResults = await searchClient.search.get({ ...options, params: { text: `scope:${orgName}`, size: 250, ...options?.params } }); // Convert search results to package info const packages = await Promise.all(searchResults.objects.map(result => client[encodeURIComponent(result.package.name)].get())); return packages; }, members: async options => { // Get organization members const membersResponse = await orgBase.users.get(options); // Convert to user objects const usernames = Object.keys(membersResponse); const users = await Promise.all(usernames.map(username => createUserClient(username).get())); return users; }, chain: orgBase }; } function createTagClient(tag) { return { packages: async options => { // Search packages by keyword/tag const searchClient = (0, _npmClient.createNpmClient)({ ...config, baseUrl: "https://registry.npmjs.org/-/v1" }); const searchResults = await searchClient.search.get({ ...options, params: { text: `keywords:${tag}`, size: 250, ...options?.params } }); // Convert search results to package info const packages = await Promise.all(searchResults.objects.map(result => client[encodeURIComponent(result.package.name)].get())); return packages; }, chain: client }; } return { api: client, package: createPackageClient, search: searchClient, downloads: downloadsClient, user: createUserClient, org: createOrgClient, tag: createTagClient }; }