UNPKG

@grnsft/if-github-plugin

Version:

Github plugin for Impact Framework.

112 lines (94 loc) 3.09 kB
import {z} from 'zod'; import {PluginParams, ConfigParams} from '@grnsft/if-core/types'; import {PluginFactory} from '@grnsft/if-core/interfaces'; import {ERRORS, validate} from '@grnsft/if-core/utils'; import {GithubAPI} from './api'; const {ConfigError} = ERRORS; export const Github = PluginFactory({ metadata: { inputs: {}, outputs: { clones: { description: 'the clones count of the given repository in the specified time range', unit: 'number', 'aggregation-method': {time: 'sum', component: 'sum'}, }, size: { description: 'the size of the given repository', unit: 'GB', 'aggregation-method': {time: 'sum', component: 'sum'}, }, }, }, implementation: async (inputs: PluginParams[], config: ConfigParams) => { const {repo} = config; const {clones, size} = await getRepoData(repo); return inputs.map(input => ({ ...input, clones: getClonesForTimeRange(input, clones), size, })); }, inputValidation: ( input: PluginParams, _config: ConfigParams, index: number ) => { const schema = z.object({ timestamp: z.string().or(z.date()), duration: z.number().or(z.string()), }); return validate<z.infer<typeof schema>>(schema, input, index); }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError('Config is not provided.'); } const schema = z.object({ repo: z.string().regex(/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9._-]+$/), }); return validate<z.infer<typeof schema>>(schema, config); }, }); /** * Gets repo data from the GitHub API. */ const getRepoData = async (repo: string) => { const [owner, repoName] = repo.split('/'); return await GithubAPI().getRepoClonesAndSizes(owner, repoName); }; /** * Gets clones count for the given input data. */ const getClonesForTimeRange = ( input: PluginParams, clones: {timestamp: string; count: number}[] ) => { const twoWeeksInMilliseconds = 14 * 24 * 60 * 60 * 1000; const {timestamp, duration} = input; const evaledDuration = eval(duration) * 1000; const convertedTimestamp = localToUTC(timestamp); const startTime = new Date(convertedTimestamp || timestamp).getTime(); const endTime = startTime + evaledDuration; if (evaledDuration > twoWeeksInMilliseconds) { console.warn( 'The `duration` exceeds two weeks. The GitHub API provides a maximum of 2 weeks of data. The plugin calculated data for two weeks.\n' ); } return clones.reduce((totalCount, clone) => { const cloneTime = new Date(clone.timestamp).getTime(); if (cloneTime >= startTime && cloneTime <= endTime) { return totalCount + clone.count; } return totalCount; }, 0); }; /** * Converts a local time to an ISO string in UTC format. */ const localToUTC = (timestamp: string): string => { const date = new Date(timestamp); const utcDate = new Date(date.getTime() + date.getTimezoneOffset() * 60000); return utcDate.toISOString(); };