diff --git a/docs/ts-github-models.md b/docs/ts-github-models.md new file mode 100644 index 0000000..ddde35d --- /dev/null +++ b/docs/ts-github-models.md @@ -0,0 +1,91 @@ +# GitHub Integration Types (TypeScript) + +## Core Types + +interface GitHubConfig { + githubUsername: string; + githubToken?: string; +} + +interface Repository { + id: number; + name: string; + full_name: string; + private: boolean; + html_url: string; + description: string | null; + language: string | null; + stargazers_count: number; + forks_count: number; + updated_at: string; +} + +interface FormattedRepo { + name: string; + description: string; + language: string; + stars: number; + forks: number; + updatedAt: string; + url: string; +} + +## Activity Types + +type ActivityType = + | 'PushEvent' + | 'CreateEvent' + | 'PullRequestEvent' + | 'IssuesEvent'; + +interface Activity { + id: string; + type: ActivityType; + repo: { + name: string; + }; + created_at: string; + payload: { + action?: string; + ref?: string; + }; +} + +interface FormattedActivity { + text: string; + icon: string; + date: string; +} + +## User Types + +interface UserProfile { + login: string; + name: string | null; + bio: string | null; + public_repos: number; + followers: number; + following: number; +} + +interface FormattedProfile { + avatarUrl: string; + name: string; + bio: string; + followers: number; + following: number; + publicRepos: number; +} + +## Utility Types + +interface Helpers { + getAuthHeaders(token?: string | null): Record; + formatFileSize(bytes: number): string; + formatDate(date: Date | string): string; +} + +interface Formatters { + formatCommitMessage(message: string): string; + formatDateTime(date: Date | string): string; +} diff --git a/examples/example_01/public/app.js b/examples/example_01/public/app.js index b5869a1..32b2a6d 100644 --- a/examples/example_01/public/app.js +++ b/examples/example_01/public/app.js @@ -1,3 +1,18 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ /** * GitHub Dashboard - Frontend Application * diff --git a/examples/example_01/server.js b/examples/example_01/server.js index d48efd2..03a2295 100644 --- a/examples/example_01/server.js +++ b/examples/example_01/server.js @@ -1,3 +1,18 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ /** * GitHub API Explorer Server * diff --git a/examples/example_03/package-lock.json b/examples/example_03/package-lock.json new file mode 100644 index 0000000..aa3cdd1 --- /dev/null +++ b/examples/example_03/package-lock.json @@ -0,0 +1,270 @@ +{ + "name": "github-explorer-example-03", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "github-explorer-example-03", + "version": "1.0.0", + "dependencies": { + "github-explorer-framework": "file:../.." + }, + "devDependencies": { + "@types/node": "^18.15.11", + "ts-node": "^10.9.1", + "typescript": "^4.9.5" + } + }, + "../..": { + "name": "@LuisOtavio13/github-explorer-framework", + "version": "1.0.1", + "license": "GPL-3.0-only", + "dependencies": { + "axios": "^1.6.7" + }, + "devDependencies": { + "@babel/core": "^7.28.0", + "@babel/preset-env": "^7.28.0", + "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-commonjs": "^28.0.6", + "@rollup/plugin-node-resolve": "^16.0.1", + "@rollup/plugin-terser": "^0.4.4", + "@types/axios": "^0.9.36", + "@types/node": "^24.1.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "jest": "^29.7.0", + "prettier": "^3.2.4", + "rollup": "^4.45.1", + "rollup-plugin-dts": "^6.1.0", + "typescript": "^5.8.3" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "18.19.120", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.120.tgz", + "integrity": "sha512-WtCGHFXnVI8WHLxDAt5TbnCM4eSE+nI0QN2NJtwzcgMhht2eNz6V9evJrk+lwC8bCY8OWV5Ym8Jz7ZEyGnKnMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/github-explorer-framework": { + "resolved": "../..", + "link": true + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/examples/example_03/package.json b/examples/example_03/package.json new file mode 100644 index 0000000..cddbd95 --- /dev/null +++ b/examples/example_03/package.json @@ -0,0 +1,28 @@ +{ + "name": "github-explorer-example-03", + "version": "1.0.0", + "description": "Exemplo TypeScript para GitHub Explorer Framework", + "main": "dist/main.js", + "scripts": { + "build": "tsc", + "start": "node dist/main.js", + "dev": "ts-node src/main.ts", + "clean": "rm -rf dist node_modules", + "prepare": "npm run build", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "dependencies": { + "github-explorer-framework": "file:../..", + "axios": "^1.6.2" + }, + "devDependencies": { + "typescript": "^5.0.4", + "ts-node": "^10.9.2", + "@types/node": "^20.11.19", + "@types/axios": "^0.14.0" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=9.0.0" + } +} \ No newline at end of file diff --git a/examples/example_03/src/main.ts b/examples/example_03/src/main.ts new file mode 100644 index 0000000..d9a2762 --- /dev/null +++ b/examples/example_03/src/main.ts @@ -0,0 +1,132 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * GitHub Profile Explorer + * + * This script demonstrates the usage of GitHubAPIHelper class to fetch, process, + * and display GitHub profile data including repositories, activities, and charts. + */ + +// Import the GitHubAPIHelper class and ChartData type from the source directory +// (3 levels up: example_03 → examples → github-explorer-framework → src) +import GitHubAPIHelper from '../../../src'; +import { ChartData } from '../../../src/types'; + +/** + * Configuration object for GitHub API access + * @type {Object} + * @property {string} githubUsername - GitHub username to analyze + * @property {string} githubToken - Personal access token for private data access + * + * Note: In production, the token should be stored securely (environment variables) + * and not hardcoded in the source. + */ +const config = { + githubUsername: 'your-github-username-here', + githubToken: 'your-github-token-here' // Optional: For accessing private data +}; + +// Create an instance of GitHubAPIHelper with the configuration +const githubHelper = new GitHubAPIHelper(config); + +/** + * Main asynchronous function to load and display GitHub data + * Handles the complete workflow from data loading to display + */ +async function loadAndDisplayData() { + try { + console.log(' Loading GitHub data...'); + + // Load all GitHub data (profile, repos, activities, etc.) + await githubHelper.loadAllData(); + + // Display basic profile information + displayProfileInfo(); + + // Display top repositories sorted by stars + displayTopRepositories(); + + // Display recent user activities + displayRecentActivities(); + + // Prepare and display chart data + displayChartData(); + + } catch (error) { + console.error(' Error loading data:', error instanceof Error ? error.message : error); + } +} + +/** + * Displays basic profile information + */ +function displayProfileInfo() { + const profile = githubHelper.renderProfile(); + console.log('\n=== PROFILE '); + console.log(` Name: ${profile.name}`); + console.log(` Bio: ${profile.bio}`); + console.log(` Followers: ${profile.followers}`); + console.log(` Public Repositories: ${profile.publicRepos}`); +} + +/** + * Displays top 3 repositories sorted by star count + */ +function displayTopRepositories() { + const repos = githubHelper.renderRepos('stars'); + console.log('\nTOP 3 REPOSITORIES'); + repos.slice(0, 3).forEach(repo => { + console.log(`⭐ ${repo.name} - ${repo.stars} stars`); + console.log(` ${repo.description || 'No description'}`); + console.log(` ${repo.url}`); + }); +} + +/** + * Displays 5 most recent activities + */ +function displayRecentActivities() { + const activities = githubHelper.renderActivities(); + console.log('\nRECENT ACTIVITIES '); + activities.slice(0, 5).forEach(activity => { + console.log(`[${activity.date}] ${activity.text}`); + }); +} + +/** + * Prepares and displays chart data for languages and commits + */ +function displayChartData() { + const charts = githubHelper.renderCharts(); + console.log('\nCHART DATA'); + logChartData('Most used languages', charts.languages); + logChartData('Commits by repository', charts.commits); +} + +/** + * Helper function to display chart data in console + * @param {string} title - Chart title + * @param {ChartData} chartData - Data to display (labels and values) + */ +function logChartData(title: string, chartData: ChartData) { + console.log(`\n📊 ${title}:`); + chartData.labels.forEach((label, i) => { + console.log(` ${label}: ${chartData.data[i]}`); + }); +} + +// Execute the main function +loadAndDisplayData(); \ No newline at end of file diff --git a/examples/example_03/tsconfig.json b/examples/example_03/tsconfig.json new file mode 100644 index 0000000..ab3b8af --- /dev/null +++ b/examples/example_03/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "CommonJS", + "outDir": "./dist", + "rootDir": "./src", + "baseUrl": ".", + "paths": { + "github-explorer-framework": ["../../src/index.d.ts"], + "@services/*": ["../../src/services/*.d.ts"], + "@utils/*": ["../../src/utils/*.d.ts"] + }, + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node" + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist"] +} \ No newline at end of file diff --git a/examples/exemple_02/package-lock.json b/examples/exemple_02/package-lock.json index 936f1cc..0694644 100644 --- a/examples/exemple_02/package-lock.json +++ b/examples/exemple_02/package-lock.json @@ -11,12 +11,128 @@ "dependencies": { "axios": "^1.10.0", "cors": "^2.8.5", - "express": "^4.21.2" + "dotenv": "^17.2.0", + "express": "^4.21.2", + "express-openid-connect": "^2.18.1" }, "devDependencies": { "nodemon": "^3.0.1" } }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@panva/asn1.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", + "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "24.0.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.15.tgz", + "integrity": "sha512-oaeTSbCef7U/z7rDeJA138xpG3NuKc64/rZ2qmUFkFJmnMsAPaluIifqyWd8hSSMxyP9oie3dLAqYPblag9KgA==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.8.0" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -30,6 +146,19 @@ "node": ">= 0.6" } }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -74,6 +203,15 @@ "dev": true, "license": "MIT" }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -144,6 +282,33 @@ "node": ">= 0.8" } }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -198,6 +363,36 @@ "fsevents": "~2.3.2" } }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -275,6 +470,42 @@ "ms": "2.0.0" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -303,6 +534,18 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dotenv": { + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.0.tgz", + "integrity": "sha512-Q4sgBT60gzd0BB0lSyYD3xM4YxrXA9y4uBDof1JNYGzOXrQdQ6yX+7XIAqoFOGQFOTK1D3Hts5OllpxMDZFONQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -332,6 +575,15 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -438,6 +690,88 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-openid-connect": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/express-openid-connect/-/express-openid-connect-2.18.1.tgz", + "integrity": "sha512-trHqgwXxWF0n/XrDsRzsvQtnBNbU03iCNXbKR/sHwBqXlvCgup341bW7B8t6nr3L/CMoDpK+9gsTnx3qLCqdjQ==", + "license": "MIT", + "dependencies": { + "base64url": "^3.0.1", + "clone": "^2.1.2", + "cookie": "^0.7.1", + "debug": "^4.3.4", + "futoin-hkdf": "^1.5.1", + "http-errors": "^1.8.1", + "joi": "^17.7.0", + "jose": "^2.0.7", + "on-headers": "^1.0.2", + "openid-client": "^4.9.1", + "url-join": "^4.0.1" + }, + "engines": { + "node": "^10.19.0 || >=12.0.0 < 13 || >=13.7.0 < 14 || >= 14.2.0" + }, + "peerDependencies": { + "express": ">= 4.17.0" + } + }, + "node_modules/express-openid-connect/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/express-openid-connect/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-openid-connect/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-openid-connect/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/express-openid-connect/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -547,6 +881,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/futoin-hkdf": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.5.3.tgz", + "integrity": "sha512-SewY5KdMpaoCeh7jachEWFsh1nNlaDjNHZXWqL5IGwtpEYHTgkr2+AMCgNwKWkcc0wpSYrZfR7he4WdmHFtDxQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -584,6 +927,21 @@ "node": ">= 0.4" } }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -609,6 +967,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -658,6 +1041,12 @@ "node": ">= 0.4" } }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -674,6 +1063,19 @@ "node": ">= 0.8" } }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -693,6 +1095,15 @@ "dev": true, "license": "ISC" }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -754,6 +1165,76 @@ "node": ">=0.12.0" } }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/jose": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.7.tgz", + "integrity": "sha512-5hFWIigKqC+e/lRyQhfnirrAqUdIPMB7SJRqflJaO29dW7q5DFvH1XCSTmv6PQ6pb++0k6MJlLRoS0Wv4s38Wg==", + "license": "MIT", + "dependencies": { + "@panva/asn1.js": "^1.0.0" + }, + "engines": { + "node": ">=10.13.0 < 13 || >=13.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "license": "ISC" + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -823,6 +1304,15 @@ "node": ">= 0.6" } }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -915,6 +1405,18 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -924,6 +1426,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -936,6 +1447,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oidc-token-hash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.1.0.tgz", + "integrity": "sha512-y0W+X7Ppo7oZX6eovsRkuzcSM40Bicg2JEJkDJ4irIt1wsYAP5MLSNv+QAogO8xivMffw/9OvV3um1pxXgt1uA==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || >=12.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -948,6 +1468,54 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/openid-client": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-4.9.1.tgz", + "integrity": "sha512-DYUF07AHjI3QDKqKbn2F7RqozT4hyi4JvmpodLrq0HHoNP7t/AjeG/uqiBK1/N2PZSAQEThVjDLHSmJN4iqu/w==", + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.1.0", + "got": "^11.8.0", + "jose": "^2.0.5", + "lru-cache": "^6.0.0", + "make-error": "^1.3.6", + "object-hash": "^2.0.1", + "oidc-token-hash": "^5.0.1" + }, + "engines": { + "node": "^10.19.0 || >=12.0.0 < 13 || >=13.7.0 < 14 || >= 14.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1002,6 +1570,16 @@ "dev": true, "license": "MIT" }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -1017,6 +1595,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -1054,6 +1644,24 @@ "node": ">=8.10.0" } }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1312,6 +1920,12 @@ "dev": true, "license": "MIT" }, + "node_modules/undici-types": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "license": "MIT" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -1321,6 +1935,12 @@ "node": ">= 0.8" } }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "license": "MIT" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -1338,6 +1958,18 @@ "engines": { "node": ">= 0.8" } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" } } } diff --git a/examples/exemple_02/package.json b/examples/exemple_02/package.json index 06afc7e..a0d3e16 100644 --- a/examples/exemple_02/package.json +++ b/examples/exemple_02/package.json @@ -19,7 +19,9 @@ "dependencies": { "axios": "^1.10.0", "cors": "^2.8.5", - "express": "^4.21.2" + "dotenv": "^17.2.0", + "express": "^4.21.2", + "express-openid-connect": "^2.18.1" }, "devDependencies": { "nodemon": "^3.0.1" diff --git a/examples/exemple_02/public/app.js b/examples/exemple_02/public/app.js index 6de5823..0d2c098 100644 --- a/examples/exemple_02/public/app.js +++ b/examples/exemple_02/public/app.js @@ -1,3 +1,18 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ /** * GitHub Dashboard - Frontend Application */ @@ -395,8 +410,14 @@ document.addEventListener('DOMContentLoaded', async () => { } function formatNumber(num) { - return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); + const safeNum = Number(num); + if (isNaN(safeNum)) { + console.warn('⚠️ [formatNumber] Valor inválido:', num); + return '0'; } + return safeNum.toLocaleString(); // formato automático com vírgulas +} + function formatDate(dateString) { const options = { day: 'numeric', month: 'short', year: 'numeric' }; diff --git a/examples/exemple_02/server.js b/examples/exemple_02/server.js index 9d9d6db..9c56874 100644 --- a/examples/exemple_02/server.js +++ b/examples/exemple_02/server.js @@ -1,13 +1,25 @@ /** - * GitHub Dashboard Server - Modern ES Modules Version - * - * Provides API endpoints for GitHub data and serves the frontend + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ - -import express from 'express'; -import cors from 'cors'; -import path from 'path'; -import { fileURLToPath } from 'url'; +// Import required modules +import express from 'express'; // Express framework for building the server +import cors from 'cors'; // Cross-Origin Resource Sharing middleware +import path from 'path'; // Path utilities for working with file/directory paths +import { fileURLToPath } from 'url'; // URL utilities for ES modules +import { auth } from 'express-openid-connect'; // Auth0 authentication middleware +import dotenv from 'dotenv'; // Environment variables loader import { UserService, RepoService, @@ -15,201 +27,155 @@ import { LanguageService, CommitService, ContributionService -} from '../../src/index.js'; +} from '../../src/index.js'; // Custom GitHub data services + +// 1. Configuration Setup +dotenv.config(); // Load environment variables from .env file -// Configure __dirname equivalent for ES Modules +// Get current module path (ES modules alternative to __dirname) const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -// Initialize Express app -const app = express(); - -// Middleware Configuration -app.use(cors({ - origin: '*', - methods: ['GET', 'OPTIONS'], - allowedHeaders: ['Content-Type'] -})); +// List of required environment variables +const requiredEnv = [ + 'AUTH0_CLIENT_ID', // Auth0 application client ID + 'AUTH0_CLIENT_SECRET', // Auth0 application client secret + 'AUTH0_ISSUER_BASE_URL', // Auth0 domain URL + 'BASE_URL', // Base URL of the application + 'SESSION_SECRET', // Secret for session encryption + 'GITHUB_TOKEN', // GitHub personal access token + 'GITHUB_USERNAME' // GitHub username to fetch data for +]; + +// Check for missing environment variables +const missing = requiredEnv.filter(k => !process.env[k]); +if (missing.length > 0) { + console.error('❌ Missing environment variables:', missing); + process.exit(1); // Exit if any required variables are missing +} -app.use(express.json()); -app.use(express.static(path.join(__dirname, 'public'))); +// 2. Auth0 Configuration +const getAuth0Config = () => ({ + authRequired: false, // Authentication not required for all routes + auth0Logout: true, // Enable Auth0 logout + secret: process.env.SESSION_SECRET, // Session encryption secret + baseURL: process.env.BASE_URL, // Base URL of the application + clientID: process.env.AUTH0_CLIENT_ID, // Auth0 client ID + issuerBaseURL: process.env.AUTH0_ISSUER_BASE_URL, // Auth0 domain + clientSecret: process.env.AUTH0_CLIENT_SECRET, // Auth0 client secret + authorizationParams: { + response_type: 'code', // Authorization code flow + scope: 'openid profile email' // Requested user data + } +}); -// GitHub API Configuration -const githubConfig = { - githubUsername: 'TylorSwift2', - githubToken: 'YOUR_TOKEN' -}; +// 3. Application Initialization +const app = express(); // Create Express application -// API Endpoints +// Configure middleware +app.use(cors({ + origin: process.env.BASE_URL, // Allow requests from frontend + credentials: true // Allow credentials/cookies +})); +app.use(auth(getAuth0Config())); // Add Auth0 authentication +app.use(express.json()); // Parse JSON request bodies +app.use(express.static(path.join(__dirname, 'public'))); // Serve static files + +// 4. GitHub Authentication Fallback +// Attach GitHub credentials to every request +app.use((req, res, next) => { + req.githubConfig = { + githubUsername: process.env.GITHUB_USERNAME, + githubToken: process.env.GITHUB_TOKEN + }; + next(); +}); -// Health Check +// 5. Health Check Endpoint +// Simple endpoint to verify server is running app.get('/api/health', (req, res) => { - res.json({ status: 'healthy', timestamp: new Date().toISOString() }); + res.json({ + status: 'ok', + auth: req.oidc.isAuthenticated() ? req.oidc.user : 'unauthenticated' + }); }); -// Main GitHub Data Endpoint +// 6. GitHub Data Endpoint +// Main endpoint that aggregates GitHub data app.get('/api/github-data', async (req, res) => { try { - console.log('Fetching GitHub data...'); - - const services = { - user: new UserService(githubConfig), - repo: new RepoService(githubConfig), - activity: new ActivityService(githubConfig), - language: new LanguageService(githubConfig), - commit: new CommitService(githubConfig), - contribution: new ContributionService(githubConfig) - }; - - // Load independent data in parallel - await Promise.all([ - services.user.loadUserData(), - services.repo.loadReposData(), - services.activity.loadActivities(), - services.contribution.loadContributionsData() - ]); + const { githubToken, githubUsername } = req.githubConfig; - // Load dependent data - await services.language.loadLanguagesData(services.repo.reposData); - await services.commit.loadCommitsData(services.repo.reposData); - - const response = { - user: formatUserProfile(services.user.userData), - repositories: formatRepositories(services.repo.reposData), - activities: formatActivities(services.activity.activitiesData), - languages: services.language.languagesData, - commits: formatCommits(services.commit.commitsData), - contributions: formatContributions(services.contribution.contributionsData), - lastUpdated: new Date().toISOString() - }; - - console.log('GitHub data fetched successfully'); - res.json(response); - - } catch (error) { - console.error('Error fetching GitHub data:', error); - res.status(500).json({ - error: 'Failed to fetch GitHub data', - details: process.env.NODE_ENV === 'development' ? error.message : undefined - }); - } -}); + // Validate GitHub credentials + if (!githubToken || !githubUsername) { + throw new Error('GITHUB_TOKEN and GITHUB_USERNAME are not configured.'); + } -// Serve Frontend -app.get('*', (req, res) => { - res.sendFile(path.join(__dirname, 'public', 'index.html')); -}); + // Initialize GitHub data services + const user = new UserService(req.githubConfig); + const repo = new RepoService(req.githubConfig); + const activity = new ActivityService(req.githubConfig); + const contribution = new ContributionService(req.githubConfig); + + // Fetch all primary data in parallel + const [userData, reposData, activitiesData, contributionsData] = await Promise.all([ + user.loadUserData(), // User profile data + repo.loadReposData(), // Repository list + activity.loadActivities(), // User activity + contribution.loadContributionsData() // Contribution stats + ]); -// Data Formatting Functions -function formatUserProfile(userData) { - if (!userData) return null; - - return { - avatarUrl: userData.avatar_url || '', - name: userData.name || userData.login || 'GitHub User', - bio: userData.bio || 'No bio available', - followers: userData.followers || 0, - following: userData.following || 0, - publicRepos: userData.public_repos || 0, - location: userData.location || 'Unknown', - profileUrl: userData.html_url || '#' - }; -} + // Validate repositories data + if (!Array.isArray(reposData)) { + console.error('❌ reposData is not an array:', reposData); + throw new Error('Error loading repositories. Check if user exists and token has sufficient permissions.'); + } -function formatRepositories(reposData) { - if (!reposData || !reposData.length) return []; - - return reposData.map(repo => ({ - name: repo.name || 'Unnamed repository', - fullName: repo.full_name || '', - description: repo.description || 'No description', - language: repo.language || 'Not specified', - stars: repo.stargazers_count || 0, - forks: repo.forks_count || 0, - updatedAt: repo.updated_at || new Date().toISOString(), - url: repo.html_url || '#', - openIssues: repo.open_issues_count || 0 - })).sort((a, b) => b.stars - a.stars); -} + // Initialize services that depend on repositories + const language = new LanguageService(req.githubConfig); + const commit = new CommitService(req.githubConfig); -function formatActivities(activitiesData) { - if (!activitiesData || !activitiesData.length) return []; - - return activitiesData.map(activity => { - const repoName = activity.repo?.name || 'Unknown repository'; - - let icon, text; - switch(activity.type) { - case 'PushEvent': - icon = 'fa-code-commit'; - text = `Pushed to ${repoName}`; - break; - case 'CreateEvent': - icon = 'fa-plus-circle'; - text = `Created ${activity.payload.ref_type || 'resource'} in ${repoName}`; - break; - case 'WatchEvent': - icon = 'fa-star'; - text = `Starred ${repoName}`; - break; - default: - icon = 'fa-github-alt'; - text = `Performed ${activity.type} on ${repoName}`; - } + // Fetch language and commit data for all repositories + await Promise.all([ + language.loadLanguagesData(reposData), // Repository languages + commit.loadCommitsData(reposData) // Commit history + ]); - return { - icon, - text, - date: activity.created_at || new Date().toISOString(), - type: activity.type - }; - }); -} + // Return complete GitHub data + res.json({ + user: userData, + repositories: reposData, + activities: activitiesData, + languages: language.languagesData, + commits: commit.commitsData, + contributions: contributionsData + }); -function formatCommits(commitsData) { - if (!commitsData) return []; - - if (Array.isArray(commitsData)) { - return commitsData.map(commit => ({ - repository: commit.repository || 'Unknown repository', - commitCount: commit.commitCount || 0, - message: commit.message || `Made ${commit.commitCount || 0} commits` - })); + } catch (err) { + console.error('❌ Error in /api/github-data:', err); + res.status(500).json({ error: err.message }); } - - return Object.entries(commitsData).map(([repo, count]) => ({ - repository: repo, - commitCount: count, - message: `Made ${count} ${count === 1 ? 'commit' : 'commits'} in ${repo}` - })); -} +}); -function formatContributions(contributionsData) { - if (!contributionsData) return []; - - return Object.entries(contributionsData).map(([month, count]) => ({ - month: month || 'Unknown month', - contributionCount: count || 0 - })); -} +// 7. Authentication Routes +// Route to initiate Auth0 login +app.get('/login', (req, res) => { + res.oidc.login({ returnTo: '/dashboard' }); // Redirect to dashboard after login +}); -// Error Handling Middleware -app.use((err, req, res, next) => { - console.error('Unhandled error:', err.stack); - res.status(500).json({ - error: 'Internal server error', - message: process.env.NODE_ENV === 'development' ? err.message : undefined - }); +// Route to handle logout +app.get('/logout', (req, res) => { + res.oidc.logout({ returnTo: process.env.BASE_URL }); // Redirect to base URL after logout }); -// Start Server -const PORT = process.env.PORT || 3000; -const ENV = process.env.NODE_ENV || 'development'; +// 8. Frontend Fallback Route +// Serve frontend for all other routes +app.get('*', (req, res) => { + res.sendFile(path.join(__dirname, 'public', 'index.html')); +}); +// 9. Server Startup +const PORT = process.env.PORT || 3000; // Use configured port or default to 3000 app.listen(PORT, () => { - console.log(` - 🚀 Server running in ${ENV} mode - 🔗 http://localhost:${PORT} - 📅 ${new Date().toLocaleString()} - `); + console.log(`🚀 Server running on ${process.env.BASE_URL} (${PORT})`); }); \ No newline at end of file diff --git a/src/core/GitHubAPIHelper.d.ts b/src/core/GitHubAPIHelper.d.ts new file mode 100644 index 0000000..e09ac98 --- /dev/null +++ b/src/core/GitHubAPIHelper.d.ts @@ -0,0 +1,168 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * GitHub API Helper - Core Class + * + * Provides a high-level interface for accessing and processing GitHub data. + * Orchestrates all services (users, repos, activities, etc.) under a unified API. + * + * @class GitHubAPIHelper + */ + +import { + GitHubConfig, + Repository, + FormattedRepo, + FormattedActivity, + LanguageStats, + FormattedCommit, + ContributionCalendar, + FormattedContentItem, + ChartData, + Commit +} from '../types'; + +declare class GitHubAPIHelper { + /** + * Creates a GitHubAPIHelper instance + * @param {GitHubConfig} config - Configuration object with GitHub credentials + */ + constructor(config: GitHubConfig); + + /** + * Loads all available GitHub data (profile, repos, activities, etc.) + * @returns {Promise} True if all data loaded successfully + * @throws {Error} If any critical data fails to load + * @example + * await apiHelper.loadAllData(); + */ + loadAllData(): Promise; + + // ==================== DATA ACCESSORS ==================== + + /** + * Raw user profile data + * @readonly + * @type {any} + */ + readonly userData: any; + + /** + * Array of repository data + * @readonly + * @type {Repository[]} + */ + readonly reposData: Repository[]; + + /** + * Array of user activities/events + * @readonly + * @type {any[]} + */ + readonly activitiesData: any[]; + + /** + * Language statistics across all repositories + * @readonly + * @type {LanguageStats} + */ + readonly languagesData: LanguageStats; + + /** + * Commit statistics by repository + * @readonly + * @type {Record} + */ + readonly commitsData: Record; + + /** + * Contribution calendar data + * @readonly + * @type {ContributionCalendar} + */ + readonly contributionsData: ContributionCalendar; + + // ==================== RENDERING METHODS ==================== + + /** + * Formats user profile data for display + * @returns {any} Formatted profile object + */ + renderProfile(): any; + + /** + * Formats activity data for display + * @returns {FormattedActivity[]} Array of formatted activities + */ + renderActivities(): FormattedActivity[]; + + /** + * Formats repository data for display + * @param {string} [sort='stars'] - Sort order ('stars', 'forks', 'updated', 'name') + * @returns {FormattedRepo[]} Array of formatted repositories + */ + renderRepos(sort?: string): FormattedRepo[]; + + /** + * Prepares chart-ready data + * @returns {Object} Chart data objects for: + * - languages: Language usage distribution + * - commits: Commit activity + * - contributions: Contribution calendar + */ + renderCharts(): { + languages: ChartData, + commits: ChartData, + contributions: ChartData + }; + + // ==================== REPOSITORY OPERATIONS ==================== + + /** + * Loads commits for a specific repository + * @param {string} repoName - Full repository name (owner/repo) + * @param {number} [page=1] - Page number for paginated results + * @param {number} [per_page=30] - Number of commits per page + * @returns {Promise} Array of formatted commits + */ + loadRepoCommits(repoName: string, page?: number, per_page?: number): Promise; + + /** + * Loads file/directory contents from a repository + * @param {string} repoName - Full repository name (owner/repo) + * @param {string} [path=''] - Path within repository + * @returns {Promise} Array of formatted content items + */ + loadRepoFiles(repoName: string, path?: string): Promise; + + /** + * Loads raw content of a file + * @param {string} repoName - Full repository name (owner/repo) + * @param {string} filePath - Path to file within repository + * @returns {Promise} File content as string + */ + loadFileContent(repoName: string, filePath: string): Promise; + + /** + * Loads detailed commit information + * @param {string} repoName - Full repository name (owner/repo) + * @param {string} sha - Commit SHA hash + * @returns {Promise} Detailed commit object + */ + loadCommitDetails(repoName: string, sha: string): Promise; +} + +export default GitHubAPIHelper; \ No newline at end of file diff --git a/src/core/GitHubAPIHelper.js b/src/core/GitHubAPIHelper.js index ca3ab19..4c2a133 100644 --- a/src/core/GitHubAPIHelper.js +++ b/src/core/GitHubAPIHelper.js @@ -1,3 +1,19 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + import UserService from '../services/UserService.js'; import RepoService from '../services/RepoService.js'; import ActivityService from '../services/ActivityService.js'; diff --git a/src/index.d.ts b/src/index.d.ts new file mode 100644 index 0000000..33d026f --- /dev/null +++ b/src/index.d.ts @@ -0,0 +1,75 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * Main entry point for GitHub Explorer Framework + * + * This module serves as the central export point for all framework functionality, + * including the main helper class, individual services, utility functions, and type definitions. + * + * @module GitHubAPIHelper + */ + +/** + * Core GitHub API Helper class + * Provides high-level access to GitHub data through integrated services + */ +import GitHubAPIHelper from './core/GitHubAPIHelper'; + +/** + * Service Modules + * Individual services that handle specific GitHub data domains + */ +import UserService from './services/UserService'; // Handles user profile data +import RepoService from './services/RepoService'; // Manages repository data +import ActivityService from './services/ActivityService'; // Processes user activities +import LanguageService from './services/LanguageService'; // Analyzes language usage +import CommitService from './services/CommitService'; // Tracks commit statistics +import ContributionService from './services/ContributionService'; // Manages contribution data + +/** + * Utility Modules + * Helper functions for data processing and formatting + */ +import * as helpers from './utils/helpers'; // General utility functions +import * as formatters from './utils/formatters'; // Data formatting utilities + +// Main framework export - the GitHubAPIHelper class +export default GitHubAPIHelper; + +/** + * Service Exports + * Individual services can be imported for specialized use cases + */ +export { + UserService, + RepoService, + ActivityService, + LanguageService, + CommitService, + ContributionService +}; + +/** + * Utility Exports + * Helper functions for custom data processing + */ +export { helpers, formatters }; + +/** + * Type Exports + * All type definitions for TypeScript support + */ +export * from './types'; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 906a039..579eb7c 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,18 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ /** * @file Main entry point for GitHub API Helper framework * @module GitHubAPIHelper diff --git a/src/services/ActivityService.d.ts b/src/services/ActivityService.d.ts new file mode 100644 index 0000000..0affaf3 --- /dev/null +++ b/src/services/ActivityService.d.ts @@ -0,0 +1,58 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * Activity Service + * + * Handles fetching and processing of GitHub user activities/events. + * + * @class ActivityService + */ + +import { GitHubConfig, Activity, FormattedActivity } from '../types'; + +declare class ActivityService { + /** + * Creates an ActivityService instance + * @param {GitHubConfig} config - Configuration object with GitHub credentials + */ + constructor(config: GitHubConfig); + + /** + * Raw activity data from GitHub API + * @type {Activity[]} + */ + activitiesData: Activity[]; + + /** + * Fetches user activities from GitHub API + * @param {number} [per_page=30] - Number of activities to fetch per request + * @returns {Promise} Resolves when activities are loaded + * @throws {Error} If API request fails + * @example + * await activityService.loadActivities(50); + */ + loadActivities(per_page?: number): Promise; + + /** + * Formats raw activity data for display + * @returns {FormattedActivity[]} Array of formatted activities + * @example + * const feedItems = activityService.renderActivities(); + */ + renderActivities(): FormattedActivity[]; +} + +export default ActivityService; \ No newline at end of file diff --git a/src/services/ActivityService.js b/src/services/ActivityService.js index 7d24bb2..551a829 100644 --- a/src/services/ActivityService.js +++ b/src/services/ActivityService.js @@ -1,3 +1,18 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ import axios from 'axios'; import { getAuthHeaders } from '../utils/helpers.js'; import UserService from '../services/UserService.js'; diff --git a/src/services/CommitService.d.ts b/src/services/CommitService.d.ts new file mode 100644 index 0000000..802807a --- /dev/null +++ b/src/services/CommitService.d.ts @@ -0,0 +1,73 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * Commit Service + * + * Handles fetching and processing of GitHub commit data across repositories. + * + * @class CommitService + */ + +import { GitHubConfig, Repository, Commit, FormattedCommit } from '../types'; + +declare class CommitService { + /** + * Creates a CommitService instance + * @param {GitHubConfig} config - Configuration object with GitHub credentials + */ + constructor(config: GitHubConfig); + + /** + * Aggregated commit statistics data + * @type {Record} + * @description Key-value pairs of repository names and commit counts + */ + commitsData: Record; + + /** + * Loads commit statistics for multiple repositories + * @param {Repository[]} reposData - Array of repository objects + * @param {number} [per_page=100] - Number of commits to fetch per repository + * @returns {Promise} Resolves when all commit data is loaded + * @throws {Error} If API requests fail + * @example + * await commitService.loadCommitsData(userRepositories); + */ + loadCommitsData(reposData: Repository[], per_page?: number): Promise; + + /** + * Loads formatted commits for a specific repository + * @param {string} repoName - Full repository name (owner/repo) + * @param {number} [page=1] - Page number for paginated results + * @param {number} [per_page=30] - Number of commits per page + * @returns {Promise} Array of formatted commits + * @example + * const commits = await commitService.loadRepoCommits('owner/repo'); + */ + loadRepoCommits(repoName: string, page?: number, per_page?: number): Promise; + + /** + * Loads detailed commit information + * @param {string} repoName - Full repository name (owner/repo) + * @param {string} sha - Commit SHA hash + * @returns {Promise} Detailed commit object + * @example + * const commit = await commitService.loadCommitDetails('owner/repo', 'abc123'); + */ + loadCommitDetails(repoName: string, sha: string): Promise; +} + +export default CommitService; \ No newline at end of file diff --git a/src/services/CommitService.js b/src/services/CommitService.js index 604f0ae..d32f7ce 100644 --- a/src/services/CommitService.js +++ b/src/services/CommitService.js @@ -1,3 +1,18 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ import axios from 'axios'; import { getAuthHeaders } from '../utils/helpers.js'; import UserService from '../services/UserService.js'; diff --git a/src/services/ContributionService.d.ts b/src/services/ContributionService.d.ts new file mode 100644 index 0000000..c56c48f --- /dev/null +++ b/src/services/ContributionService.d.ts @@ -0,0 +1,57 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * Contribution Service + * + * Handles fetching and processing of GitHub contribution data including commit calendars. + * + * @class ContributionService + */ + +import { GitHubConfig, ContributionCalendar } from '../types'; + +declare class ContributionService { + /** + * Creates a ContributionService instance + * @param {GitHubConfig} config - Configuration object with GitHub credentials + */ + constructor(config: GitHubConfig); + + /** + * Contribution calendar data + * @type {ContributionCalendar} + * @description Monthly contribution counts in the format: + * { + * Jan: number, + * Feb: number, + * ... + * Dec: number + * } + */ + contributionsData: ContributionCalendar; + + /** + * Loads contribution data for a specific year + * @param {number} [year=new Date().getFullYear()] - Year to fetch contributions for + * @returns {Promise} Resolves when contribution data is loaded + * @throws {Error} If API request fails + * @example + * await contributionService.loadContributionsData(2023); + */ + loadContributionsData(year?: number): Promise; +} + +export default ContributionService; \ No newline at end of file diff --git a/src/services/ContributionService.js b/src/services/ContributionService.js index bce7e06..cf918c4 100644 --- a/src/services/ContributionService.js +++ b/src/services/ContributionService.js @@ -1,3 +1,18 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ import axios from 'axios'; import { getAuthHeaders } from '../utils/helpers.js'; import UserService from '../services/UserService.js'; diff --git a/src/services/LanguageService.d.ts b/src/services/LanguageService.d.ts new file mode 100644 index 0000000..6c194cd --- /dev/null +++ b/src/services/LanguageService.d.ts @@ -0,0 +1,57 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * Language Analysis Service + * + * Handles fetching and processing of repository language statistics. + * + * @class LanguageService + */ + +import { GitHubConfig, LanguageStats, Repository } from '../types'; + +declare class LanguageService { + /** + * Creates a LanguageService instance + * @param {GitHubConfig} config - Configuration object with GitHub credentials + */ + constructor(config: GitHubConfig); + + /** + * Aggregated language statistics + * @type {LanguageStats} + * @description Key-value pairs of languages and their total bytes of code + * @example + * { + * "TypeScript": 24576, + * "JavaScript": 10240, + * "CSS": 5120 + * } + */ + languagesData: LanguageStats; + + /** + * Loads and aggregates language data for multiple repositories + * @param {Repository[]} reposData - Array of repository objects + * @returns {Promise} Resolves when all language data is loaded and aggregated + * @throws {Error} If API requests fail + * @example + * await languageService.loadLanguagesData(userRepositories); + */ + loadLanguagesData(reposData: Repository[]): Promise; +} + +export default LanguageService; \ No newline at end of file diff --git a/src/services/LanguageService.js b/src/services/LanguageService.js index 23118d6..e4019fb 100644 --- a/src/services/LanguageService.js +++ b/src/services/LanguageService.js @@ -1,3 +1,18 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ import axios from 'axios'; import { getAuthHeaders } from '../utils/helpers.js'; import UserService from '../services/UserService.js'; diff --git a/src/services/RepoService.d.ts b/src/services/RepoService.d.ts new file mode 100644 index 0000000..745dae4 --- /dev/null +++ b/src/services/RepoService.d.ts @@ -0,0 +1,87 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * Repository Service + * + * Handles fetching, processing, and managing GitHub repository data. + * + * @class RepoService + */ + +import { + GitHubConfig, + Repository, + FormattedRepo, + RepoContentItem, + FormattedContentItem +} from '../types'; + +declare class RepoService { + /** + * Creates a RepoService instance + * @param {GitHubConfig} config - Configuration object with GitHub credentials + */ + constructor(config: GitHubConfig); + + /** + * Raw repository data from GitHub API + * @type {Repository[]} + */ + reposData: Repository[]; + + /** + * Loads repository data from GitHub API + * @param {string} [sort='updated'] - Sort order ('updated', 'created', 'pushed', 'full_name') + * @param {number} [per_page=100] - Number of repositories to fetch + * @returns {Promise} Resolves when repositories are loaded + * @throws {Error} If API request fails + * @example + * await repoService.loadReposData('stars', 50); + */ + loadReposData(sort?: string, per_page?: number): Promise; + + /** + * Formats repository data for display + * @param {string} [sort='stars'] - Sort order ('stars', 'forks', 'updated', 'name') + * @returns {FormattedRepo[]} Array of formatted repositories + * @example + * const topRepos = repoService.renderRepos('stars'); + */ + renderRepos(sort?: string): FormattedRepo[]; + + /** + * Loads repository file/directory contents + * @param {string} repoName - Full repository name (owner/repo) + * @param {string} [path=''] - Path within repository + * @returns {Promise} Array of formatted content items + * @example + * const rootFiles = await repoService.loadRepoFiles('owner/repo'); + * const srcFiles = await repoService.loadRepoFiles('owner/repo', 'src'); + */ + loadRepoFiles(repoName: string, path?: string): Promise; + + /** + * Loads raw content of a file + * @param {string} repoName - Full repository name (owner/repo) + * @param {string} filePath - Path to file within repository + * @returns {Promise} File content as string + * @example + * const readme = await repoService.loadFileContent('owner/repo', 'README.md'); + */ + loadFileContent(repoName: string, filePath: string): Promise; +} + +export default RepoService; \ No newline at end of file diff --git a/src/services/RepoService.js b/src/services/RepoService.js index 10ed316..25fe687 100644 --- a/src/services/RepoService.js +++ b/src/services/RepoService.js @@ -1,3 +1,18 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ import axios from 'axios'; import { getAuthHeaders, formatFileSize } from '../utils/helpers.js'; import UserService from '../services/UserService.js'; diff --git a/src/services/UserService.d.ts b/src/services/UserService.d.ts new file mode 100644 index 0000000..e0471aa --- /dev/null +++ b/src/services/UserService.d.ts @@ -0,0 +1,83 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * User Profile Service + * + * Handles fetching and processing of GitHub user profile data. + * + * @class UserService + */ + +import { GitHubConfig } from '../types'; + +/** + * Raw user profile data from GitHub API + * @interface UserProfile + */ +interface UserProfile { + avatar_url: string; + name: string | null; + bio: string | null; + followers: number; + following: number; + public_repos: number; +} + +/** + * Formatted user profile data for display + * @interface RenderedProfile + */ +interface RenderedProfile { + avatarUrl: string; + name: string; + bio: string; + followers: number; + following: number; + publicRepos: number; +} + +declare class UserService { + /** + * Creates a UserService instance + * @param {GitHubConfig} config - Configuration object with GitHub credentials + */ + constructor(config: GitHubConfig); + + /** + * Raw user profile data + * @type {UserProfile} + */ + userData: UserProfile; + + /** + * Loads user profile data from GitHub API + * @returns {Promise} Resolves when profile data is loaded + * @throws {Error} If API request fails + * @example + * await userService.loadUserData(); + */ + loadUserData(): Promise; + + /** + * Formats raw profile data for display + * @returns {RenderedProfile} Formatted profile object + * @example + * const profile = userService.renderProfile(); + */ + renderProfile(): RenderedProfile; +} + +export default UserService; \ No newline at end of file diff --git a/src/services/UserService.js b/src/services/UserService.js index f006854..7092145 100644 --- a/src/services/UserService.js +++ b/src/services/UserService.js @@ -1,3 +1,18 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ import axios from 'axios'; import { getAuthHeaders } from '../utils/helpers.js'; diff --git a/src/types.d.ts b/src/types.d.ts new file mode 100644 index 0000000..cfa36ab --- /dev/null +++ b/src/types.d.ts @@ -0,0 +1,347 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * Core Type Definitions for GitHub Explorer Framework + * + * This module contains all TypeScript interfaces and type definitions + * used throughout the GitHub Explorer Framework. + * + * @module Types + */ + +/* ================ Core Configuration ================ */ + +/** + * Configuration interface for GitHub API access + * @interface GitHubConfig + * @property {string} githubUsername - Required GitHub username + * @property {string|null} [githubToken] - Optional personal access token for private data + */ +export interface GitHubConfig { + githubUsername: string; + githubToken?: string | null; +} + +/* ================ Repository Types ================ */ + +/** + * Raw repository data from GitHub API + * @interface Repository + */ +export interface Repository { + id: number; + name: string; + full_name: string; + html_url: string; + description: string | null; + url: string; + languages_url: string; + stargazers_count: number; + forks_count: number; + updated_at: string; + language: string | null; + private: boolean; + size: number; + default_branch: string; + [key: string]: any; // Additional API properties +} + +/** + * Formatted repository data for display + * @interface FormattedRepo + */ +export interface FormattedRepo { + name: string; + description: string; + language: string; + stars: number; + forks: number; + updatedAt: string; + url: string; +} + +/* ================ Activity Types ================ */ + +/** + * Type for GitHub activity event types + * @type ActivityType + */ +export type ActivityType = + | 'PushEvent' + | 'CreateEvent' + | 'PullRequestEvent' + | 'IssuesEvent' + | 'WatchEvent' + | 'ForkEvent' + | 'ReleaseEvent' + | 'DeleteEvent' + | string; + +/** + * Raw activity data from GitHub API + * @interface Activity + */ +export interface Activity { + id: string; + type: ActivityType; + actor: { + login: string; + avatar_url: string; + }; + repo: { + id: number; + name: string; + url: string; + }; + payload: { + ref?: string; + ref_type?: string; + action?: string; + [key: string]: any; + }; + public: boolean; + created_at: string; + [key: string]: any; +} + +/** + * Formatted activity data for display + * @interface FormattedActivity + */ +export interface FormattedActivity { + text: string; + icon: string; + date: string; +} + +/* ================ Language Statistics Types ================ */ + +/** + * Language usage statistics + * @interface LanguageStats + */ +export interface LanguageStats { + [language: string]: number; +} + +/* ================ Commit Types ================ */ + +/** + * Raw commit data from GitHub API + * @interface Commit + */ +export interface Commit { + sha: string; + commit: { + message: string; + author: { + name: string; + email: string; + date: string; + }; + committer: { + name: string; + email: string; + date: string; + }; + }; + html_url: string; + stats?: { + additions?: number; + deletions?: number; + total?: number; + }; + files?: CommitFile[]; + [key: string]: any; +} + +/** + * Commit file change information + * @interface CommitFile + */ +export interface CommitFile { + filename: string; + status: 'added' | 'removed' | 'modified' | 'renamed'; + additions: number; + deletions: number; + changes: number; + patch?: string; + blob_url: string; +} + +/** + * Formatted commit data for display + * @interface FormattedCommit + */ +export interface FormattedCommit { + sha: string; + message: string; + author: string; + date: Date; + url: string; + stats?: { + additions?: number; + deletions?: number; + total?: number; + }; +} + +/* ================ Contribution Types ================ */ + +/** + * Contribution calendar data by month + * @interface ContributionCalendar + */ +export interface ContributionCalendar { + Jan: number; + Feb: number; + Mar: number; + Apr: number; + May: number; + Jun: number; + Jul: number; + Aug: number; + Sep: number; + Oct: number; + Nov: number; + Dec: number; +} + +/* ================ Repository Content Types ================ */ + +/** + * File type classification + * @type FileType + */ +export type FileType = 'file' | 'dir' | 'symlink' | 'submodule'; + +/** + * Repository content item from GitHub API + * @interface RepoContentItem + */ +export interface RepoContentItem { + name: string; + type: FileType; + path: string; + size?: number; + html_url: string; + download_url?: string | null; + _links: { + self: string; + git: string; + html: string; + }; +} + +/** + * Formatted repository content item + * @interface FormattedContentItem + */ +export interface FormattedContentItem { + name: string; + type: FileType; + path: string; + size: string; + url: string; +} + +/* ================ User Profile Types ================ */ + +/** + * Raw user profile data from GitHub API + * @interface UserProfile + */ +export interface UserProfile { + login: string; + id: number; + avatar_url: string; + html_url: string; + name: string | null; + company: string | null; + blog: string | null; + location: string | null; + email: string | null; + bio: string | null; + twitter_username: string | null; + public_repos: number; + public_gists: number; + followers: number; + following: number; + created_at: string; + updated_at: string; + [key: string]: any; +} + +/** + * Formatted user profile data for display + * @interface FormattedProfile + */ +export interface FormattedProfile { + avatarUrl: string; + name: string; + bio: string; + followers: number; + following: number; + publicRepos: number; +} + +/* ================ Chart Data Types ================ */ + +/** + * Data structure for chart visualization + * @interface ChartData + */ +export interface ChartData { + labels: string[]; + data: number[]; + backgroundColor?: string[]; +} + +/* ================ API Response Types ================ */ + +/** + * Standardized API response format + * @interface GitHubAPIResponse + * @template T - Type of the response data + */ +export interface GitHubAPIResponse { + data: T; + status: number; + headers: Record; +} + +/* ================ Utility Function Types ================ */ + +/** + * Helper function signatures + * @interface Helpers + */ +export interface Helpers { + getAuthHeaders: (githubToken?: string | null) => Record; + formatFileSize: (bytes: number) => string; + formatDate: (date: string | Date) => string; + formatDateTime: (date: string | Date) => string; +} + +/** + * Data formatting function signatures + * @interface Formatters + */ +export interface Formatters { + formatDate: (date: string | Date) => string; + formatDateTime: (date: string | Date) => string; + formatCommitMessage: (message: string) => string; +} \ No newline at end of file diff --git a/src/types/index.d.ts b/src/types/index.d.ts new file mode 100644 index 0000000..30741b9 --- /dev/null +++ b/src/types/index.d.ts @@ -0,0 +1,115 @@ +/** + * @license + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +// Configuration type +interface GitHubConfig { + githubUsername: string; + githubToken?: string | null; +} + +// Repository type +interface Repository { + id: number; + name: string; + full_name: string; + html_url: string; + description: string | null; + url: string; + languages_url: string; + stargazers_count: number; + forks_count: number; + updated_at: string; + language: string | null; + // Add other repository properties as needed +} + +// Activity/Event types +type ActivityType = + | 'PushEvent' + | 'CreateEvent' + | 'PullRequestEvent' + | 'IssuesEvent' + | string; + +interface Activity { + type: ActivityType; + repo: { + name: string; + }; + payload: { + ref_type?: string; + action?: string; + }; + created_at: string; +} + +// Language statistics +interface LanguageStats { + [language: string]: number; +} + +// Commit types +interface Commit { + sha: string; + commit: { + message: string; + author: { + name: string; + date: string; + }; + }; + html_url: string; + stats?: { + additions?: number; + deletions?: number; + total?: number; + }; + files?: Array<{ + filename: string; + status: string; + additions: number; + deletions: number; + changes: number; + patch?: string; + }>; +} + +// Contribution types +interface ContributionCalendar { + [month: string]: number; +} + +// File/directory types +type FileType = 'file' | 'dir'; + +interface RepoContentItem { + name: string; + type: FileType; + path: string; + size?: number; + html_url: string; +} + +export { + GitHubConfig, + Repository, + Activity, + ActivityType, + LanguageStats, + Commit, + ContributionCalendar, + RepoContentItem, + FileType +}; \ No newline at end of file diff --git a/src/utils/formatters.d.ts b/src/utils/formatters.d.ts new file mode 100644 index 0000000..308ee68 --- /dev/null +++ b/src/utils/formatters.d.ts @@ -0,0 +1,49 @@ +/** + * Data Formatting Utilities + * + * This module provides standardized formatting functions for GitHub data + * to ensure consistent presentation across the application. + * + * @module Formatters + */ + +/** + * Formats a date string or Date object into a localized date string + * @param {string|Date} date - The date to format (ISO string or Date object) + * @returns {string} Formatted date string (e.g., "January 1, 2023") + * @example + * formatDate('2023-01-01T12:00:00Z') // Returns "January 1, 2023" + */ +export function formatDate(date: string | Date): string; + +/** + * Formats a date string or Date object into a localized date-time string + * @param {string|Date} date - The date to format (ISO string or Date object) + * @returns {string} Formatted date-time string (e.g., "January 1, 2023 at 12:00 PM") + * @example + * formatDateTime('2023-01-01T12:00:00Z') // Returns "January 1, 2023 at 12:00 PM" + */ +export function formatDateTime(date: string | Date): string; + +/** + * Formats a Git commit message by: + * 1. Trimming whitespace + * 2. Capitalizing first letter + * 3. Removing extra newlines + * @param {string} message - Raw commit message + * @returns {string} Formatted commit message + * @example + * formatCommitMessage(' fix: login issue\n\n') // Returns "Fix: login issue" + */ +export function formatCommitMessage(message: string): string; + +/** + * Default export containing all formatter functions + */ +declare const _default: { + formatDate: typeof formatDate; + formatDateTime: typeof formatDateTime; + formatCommitMessage: typeof formatCommitMessage; +}; + +export default _default; \ No newline at end of file diff --git a/src/utils/helpers.d.ts b/src/utils/helpers.d.ts new file mode 100644 index 0000000..2ec52c0 --- /dev/null +++ b/src/utils/helpers.d.ts @@ -0,0 +1,52 @@ +/** + * Core Helper Utilities + * + * Provides essential utility functions for GitHub API operations and data formatting. + * + * @module Helpers + */ + +/** + * Generates authentication headers for GitHub API requests + * @param {string|null} [githubToken] - Optional GitHub personal access token + * @returns {Record} Headers object with Authorization if token provided + * @example + * getAuthHeaders('ghp_abc123') // Returns { Authorization: 'Bearer ghp_abc123' } + * getAuthHeaders() // Returns {} + */ +export function getAuthHeaders(githubToken?: string | null): Record; + +/** + * Formats bytes into human-readable file size + * @param {number} bytes - File size in bytes + * @returns {string} Formatted size string (e.g., "1.5 MB") + * @example + * formatFileSize(1500000) // Returns "1.5 MB" + */ +export function formatFileSize(bytes: number): string; + +/** + * Formats a date string or Date object into localized date format + * @param {string|Date} date - Date to format + * @returns {string} Formatted date string (e.g., "January 1, 2023") + */ +export function formatDate(date: string | Date): string; + +/** + * Formats a date string or Date object into localized date-time format + * @param {string|Date} date - Date to format + * @returns {string} Formatted date-time string (e.g., "Jan 1, 2023, 12:00 PM") + */ +export function formatDateTime(date: string | Date): string; + +/** + * Default export containing all helper functions + */ +declare const _default: { + getAuthHeaders: typeof getAuthHeaders; + formatFileSize: typeof formatFileSize; + formatDate: typeof formatDate; + formatDateTime: typeof formatDateTime; +}; + +export default _default; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..f39ccb5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "ESNext", + "outDir": "./dist", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "baseUrl": "./src", + "paths": { + "@services/*": ["services/*"], + "@utils/*": ["utils/*"], + "@core/*": ["core/*"] + } + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "**/*.spec.ts"] +} \ No newline at end of file