UNPKG

@remcostoeten/fync

Version:

Unified TypeScript library for 9 popular APIs with consistent functional architecture

224 lines 8.7 kB
import { createApiBuilder, defineResource } from "../core"; const VERCEL_API_BASE = "https://api.vercel.com"; const projectResource = defineResource({ name: "projects", basePath: "/v9/projects", methods: { listProjects: { path: "" }, getProject: { path: "/{projectId}" }, createProject: { path: "", method: "POST" }, updateProject: { path: "/{projectId}", method: "PATCH" }, deleteProject: { path: "/{projectId}", method: "DELETE" }, getProjectDomains: { path: "/{projectId}/domains" }, getProjectEnvVars: { path: "/{projectId}/env" }, createProjectEnvVar: { path: "/{projectId}/env", method: "POST" }, }, }); const deploymentResource = defineResource({ name: "deployments", basePath: "/v13/deployments", methods: { listDeployments: { path: "" }, getDeployment: { path: "/{deploymentId}" }, deleteDeployment: { path: "/{deploymentId}", method: "DELETE" }, getDeploymentEvents: { path: "/{deploymentId}/events" }, getDeploymentFiles: { path: "/{deploymentId}/files" }, cancelDeployment: { path: "/{deploymentId}/cancel", method: "PATCH" }, }, }); const domainResource = defineResource({ name: "domains", basePath: "/v5/domains", methods: { listDomains: { path: "" }, getDomain: { path: "/{domain}" }, addDomain: { path: "", method: "POST" }, removeDomain: { path: "/{domain}", method: "DELETE" }, verifyDomain: { path: "/{domain}/verify", method: "POST" }, getDomainConfig: { path: "/{domain}/config" }, }, }); const teamResource = defineResource({ name: "teams", basePath: "/v2/teams", methods: { listTeams: { path: "" }, getTeam: { path: "/{teamId}" }, createTeam: { path: "", method: "POST" }, updateTeam: { path: "/{teamId}", method: "PATCH" }, deleteTeam: { path: "/{teamId}", method: "DELETE" }, getTeamMembers: { path: "/{teamId}/members" }, inviteTeamMember: { path: "/{teamId}/members", method: "POST" }, }, }); const userResource = defineResource({ name: "user", basePath: "/v2/user", methods: { getUser: { path: "" }, updateUser: { path: "", method: "PATCH" }, deleteUser: { path: "", method: "DELETE" }, getUserEvents: { path: "/events" }, getUserTokens: { path: "/tokens" }, }, }); const resources = { projects: projectResource, deployments: deploymentResource, domains: domainResource, teams: teamResource, user: userResource, }; const buildVercel = createApiBuilder({ baseUrl: VERCEL_API_BASE, auth: { type: "bearer" }, headers: { "Content-Type": "application/json", }, }); export function Vercel(config) { const apiConfig = { token: config.token, headers: config.teamId ? { "x-vercel-team-id": config.teamId } : undefined, }; const base = buildVercel(apiConfig, resources); const vercel = base; vercel.getProject = function (projectId) { return base.projects.getProject({ projectId }); }; vercel.listProjects = function (teamId) { const params = {}; if (teamId) params.teamId = teamId; return base.projects.listProjects(params); }; vercel.getLatestDeployment = async function (projectId) { const deployments = await base.deployments.listDeployments({ projectId, limit: 1, }); return deployments[0] || null; }; vercel.getDeploymentStatus = async function (deploymentId) { const deployment = await base.deployments.getDeployment({ deploymentId }); return { id: deployment.id, state: deployment.state, ready: deployment.ready, url: deployment.url, createdAt: deployment.createdAt, }; }; vercel.redeployProject = async function (projectId) { const latest = await vercel.getLatestDeployment(projectId); if (!latest) throw new Error("No deployments found"); return base.deployments.createDeployment({ name: latest.name, project: projectId, gitSource: latest.gitSource, }); }; vercel.getProjectAnalytics = async function (projectId, options) { // Vercel Analytics API endpoint // Note: This requires the project to have analytics enabled const period = options?.period || "7d"; const from = options?.from || new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(); const to = options?.to || new Date().toISOString(); try { // Get project details const project = await base.projects.getProject({ projectId }); // Analytics data is available through a separate endpoint // The actual analytics API requires special permissions and may vary const analyticsResponse = await fetch(`https://api.vercel.com/v1/analytics/projects/${projectId}`, { headers: { Authorization: `Bearer ${config.token}`, "Content-Type": "application/json", }, method: "GET", }); if (!analyticsResponse.ok) { // Fallback to Web Analytics API if available const webAnalyticsResponse = await fetch(`https://api.vercel.com/v1/web/analytics/${projectId}?from=${from}&to=${to}&limit=100`, { headers: { Authorization: `Bearer ${config.token}`, "Content-Type": "application/json", }, method: "GET", }); if (webAnalyticsResponse.ok) { const webAnalytics = await webAnalyticsResponse.json(); return { project, analytics: { period, data: webAnalytics, visits: webAnalytics.total?.visits || 0, uniqueVisitors: webAnalytics.total?.uniqueVisitors || 0, pageViews: webAnalytics.total?.pageViews || 0, avgDuration: webAnalytics.total?.avgDuration || 0, bounceRate: webAnalytics.total?.bounceRate || 0, }, }; } // If analytics are not available, return basic project metrics return { project, analytics: { period, message: "Analytics not available for this project. Ensure analytics is enabled.", visits: null, uniqueVisitors: null, }, }; } const analyticsData = await analyticsResponse.json(); return { project, analytics: { period, data: analyticsData, visits: analyticsData.visits || 0, uniqueVisitors: analyticsData.uniqueVisitors || 0, pageViews: analyticsData.pageViews || 0, avgDuration: analyticsData.avgDuration || 0, bounceRate: analyticsData.bounceRate || 0, }, }; } catch (error) { // Handle error gracefully const project = await base.projects.getProject({ projectId }); return { project, analytics: { period, error: error instanceof Error ? error.message : "Failed to fetch analytics", visits: null, uniqueVisitors: null, }, }; } }; vercel.getDomainStatus = async function (domain) { const domainInfo = await base.domains.getDomain({ domain }); return { domain: domainInfo.name, verified: domainInfo.verified, configured: domainInfo.configured, expires: domainInfo.expiresAt, }; }; vercel.getTeamUsage = async function (teamId) { const team = await base.teams.getTeam({ teamId }); return { team: team.name, usage: { projects: team.projectsCount || 0, members: team.membersCount || 0, }, }; }; return vercel; } //# sourceMappingURL=index.js.map