{"id":36500771,"url":"https://github.com/octoreport/core","last_synced_at":"2026-01-12T02:20:58.241Z","repository":{"id":304494552,"uuid":"1011212708","full_name":"octoreport/core","owner":"octoreport","description":"A modern, timezone-aware GitHub PR/issue analytics core library🐙📊","archived":false,"fork":false,"pushed_at":"2025-08-12T04:56:37.000Z","size":624,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-30T12:43:10.265Z","etag":null,"topics":["github","kpi","pull-request","report"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@octoreport/core","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/octoreport.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-30T13:24:19.000Z","updated_at":"2025-08-12T04:56:37.000Z","dependencies_parsed_at":"2025-07-18T17:30:36.246Z","dependency_job_id":"dbd7e3eb-80cb-4ecf-a01e-d7943c809a83","html_url":"https://github.com/octoreport/core","commit_stats":null,"previous_names":["nvrtmd/octoreport","octoreport/core"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/octoreport/core","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/octoreport%2Fcore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/octoreport%2Fcore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/octoreport%2Fcore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/octoreport%2Fcore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/octoreport","download_url":"https://codeload.github.com/octoreport/core/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/octoreport%2Fcore/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28332010,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T00:36:25.062Z","status":"online","status_checked_at":"2026-01-12T02:00:08.677Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["github","kpi","pull-request","report"],"created_at":"2026-01-12T02:20:57.202Z","updated_at":"2026-01-12T02:20:58.224Z","avatar_url":"https://github.com/octoreport.png","language":"TypeScript","readme":"# @octoreport/core\n\n\u003ch1 align=\"center\"\u003e\n\t\u003cimg width=\"500px\" src=\"media/logo.png\" alt=\"octoreport\"\u003e\n\u003c/h1\u003e\n\n\u003e A modern, timezone-aware analytics core library for GitHub pull requests and issues. It provides the foundational logic for retrieving, filtering, and analyzing PR data with flexible conditions and precise participation tracking.\n\n## Features\n\n🔒 **GitHub API Integration**: Seamlessly integrates with both GitHub GraphQL and REST APIs\n\n📊 **PR Analytics**: Offers advanced query and reporting features with flexible filtering\n\n⏰ **Participation Tracking**: Accurately tracks user participation time and engagement patterns\n\n🌏 **Timezone-Aware**: Built on Luxon for reliable timezone handling and date normalization\n\n⚡ **Fast \u0026 Modern**: Developed in TypeScript for robust type safety and performance\n\n🧪 **Test Coverage**: Includes comprehensive test suites using Vitest\n\n🛠️ **Modular Design**: Clean, extensible structure with isolated analytics modules\n\n🔐 **Authentication Agnostic**: Compatible with any GitHub token (PAT, OAuth, etc.)\n\n## Installation\n\n```bash\nnpm install @octoreport/core\n```\n\n### Prerequisites\n\n- Node.js \u003e= 18\n- npm or yarn\n- GitHub token (OAuth token, Personal Access Token, etc.)\n\n## Quick Start\n\n```typescript\nimport { getUserPRListByCreationAndParticipation } from '@octoreport/core';\n\n// Get both user created and participated(by comment or review) PRs\nconst results = await getUserPRListByCreationAndParticipation({\n  username: 'octocat',\n  repository: 'octoreport/core',\n  period: {\n    startDate: '2025-07-01',\n    endDate: '2025-07-20',\n  },\n  targetBranch: 'main',\n  githubToken: 'YOUR_GITHUB_TOKEN',\n});\n\nconsole.log('🐙📊 User Created PRs:\\n', results.created);\nconsole.log('🐙📊 User Participated PRs:\\n', results.participated);\n```\n\n## API Reference\n\n### Core Functions\n\n```typescript\nimport {\n  getUserPRListByCreationAndParticipation,\n  getUserCreatedPRListInPeriod,\n  getUserParticipatedPRListInPeriod,\n  getUserCreatedPRCountInPeriod,\n  getUserCreatedPRListInPeriodByLabel,\n  getUserPRCountByLabelInPeriod,\n  separatePRListByUserParticipation,\n  getUserPRRatio,\n  getAllPRListInPeriod,\n} from '@octoreport/core';\n//Each function provides fine-grained access to user-created and participated PRs with various filtering options, label breakdowns, and statistical ratios.\n\n// Get both user created and participated PRs\nconst totalPRActivities = await getUserPRListByCreationAndParticipation({\n  username: 'octocat',\n  repository: 'octoreport/core',\n  period: {\n    startDate: '2025-07-01',\n    endDate: '2025-07-20',\n  },\n  githubToken: 'YOUR_GITHUB_TOKEN',\n});\n\n// Get only user created PRs\nconst createdPRs = await getUserCreatedPRListInPeriod({\n  username: 'octocat',\n  repository: 'octoreport/core',\n  period: {\n    startDate: '2025-07-01',\n    endDate: '2025-07-20',\n  },\n  githubToken: 'YOUR_GITHUB_TOKEN',\n});\n\n// Get only user participated PRs\nconst participatedPRs = await getUserParticipatedPRListInPeriod({\n  username: 'octocat',\n  repository: 'octoreport/core',\n  period: {\n    startDate: '2025-07-01',\n    endDate: '2025-07-20',\n  },\n  githubToken: 'YOUR_GITHUB_TOKEN',\n});\n\n// Get all PRs in period (including those without detail data)\nconst allPRs = await getAllPRListInPeriod({\n  username: 'octocat',\n  repository: 'octoreport/core',\n  period: {\n    startDate: '2025-07-01',\n    endDate: '2025-07-20',\n  },\n  githubToken: 'YOUR_GITHUB_TOKEN',\n});\n\n// Separate PRs by user participation\nconst { created, participated } = separatePRListByUserParticipation(allPRs, 'octocat');\n\n// Get user PR ratio (created vs total)\nconst userRatio = getUserPRRatio(allPRs, 'octocat');\n// Returns: 0.25 (25% of PRs were created by the user)\n\n// Get count of created PRs\nconst prCount = getUserCreatedPRCountInPeriod(createdPRs);\n\n// Filter PRs by labels\nconst bugPRs = getUserCreatedPRListInPeriodByLabel(createdPRs, ['enhancement', 'bugfix']);\n\n// Get label statistics\nconst labelStats = await getUserPRCountByLabelInPeriod(createdPRs);\n// Returns: { 'bug': 5, 'feature': 3, 'docs': 2 }\n```\n\n### Analytics Functions\n\n```typescript\nimport {\n  calculateUserPRStatistics,\n  calculateUserReviewStatistics,\n  getFirstParticipationTime,\n} from '@octoreport/core';\n\n// Get comprehensive user PR statistics\nconst userStats = calculateUserPRStatistics(allPRs, 'octocat');\n// Returns detailed statistics including counts, ratios, and breakdowns\n\n// Get user review statistics\nconst reviewStats = calculateUserReviewStatistics(allPRs, 'octocat');\n// Returns review participation statistics\n\n// Get first participation time for a user\nconst firstParticipation = getFirstParticipationTime(participationData, 'octocat');\n// Returns: '2025-07-15T10:30:00Z' or null if no participation\n```\n\n- Use these functions to compute:\n  - Participation breakdowns\n  - Review contribution stats\n  - First-time engagement timestamps\n\n### GitHub API Functions\n\n```typescript\nimport { fetchGitHubUserInfo, fetchAllPRListInPeriod } from '@octoreport/core';\n\n// Get user information\nconst userInfo = await fetchGitHubUserInfo('YOUR_GITHUB_TOKEN');\n// Returns: { login: 'octocat', id: 'MDQ6VXNlcjc5OTk1', scopeList: ['read:user', 'repo'] }\n\n// Get all PRs in a period\nconst allPRs = await fetchAllPRListInPeriod({\n  repository: 'octoreport/core',\n  period: {\n    startDate: '2025-07-01',\n    endDate: '2025-07-20',\n  },\n  githubToken: 'YOUR_GITHUB_TOKEN',\n});\n```\n\n- Provides lightweight wrappers for GitHub GraphQL and REST API operations.\n\n## Data Structure\n\nAll PRs follow the same normalized structure:\n\n```typescript\ninterface PR {\n  // Basic PR information (always available)\n  number: number;\n  title: string;\n  url: string;\n  createdAt: string;\n  user: string | null;\n\n  // Detailed information (may be null if API access is limited)\n  targetBranch?: string;\n  assignees?: string[];\n  state?: 'OPEN' | 'CLOSED' | 'MERGED';\n  merged?: boolean;\n  isDraft?: boolean;\n  mergeable?: 'MERGEABLE' | 'CONFLICTING' | 'UNKNOWN';\n  labels?: string[] | null;\n  author?: string | null;\n  reviewers?: string[] | null;\n  commenters?: string[] | null;\n  reviewDecision?: 'CHANGES_REQUESTED' | 'APPROVED' | 'REVIEW_REQUIRED' | null;\n  mergedAt?: string | null;\n  requestedReviewers?: string[] | null;\n\n  // Participation data\n  reviews?: (ReviewsRaw | null)[] | null;\n  comments?: CommentsRaw[] | null;\n}\n\ninterface Participation {\n  author?: { login: string };\n  createdAt?: string;\n  submittedAt?: string;\n}\n```\n\n## Architecture\n\nThe library is organized into modular components for better maintainability:\n\n```\nsrc/core/pr/\n├── analytics/          # Analytics and statistics functions\n│   ├── counts.ts      # Counting functions\n│   ├── groups.ts      # Grouping functions\n│   ├── statistics.ts  # Statistical calculations\n│   ├── participations.ts # Participation tracking\n│   └── types.ts       # Analytics-specific types\n├── filters.ts         # PR filtering functions\n├── queries.ts         # Data retrieval functions\n└── normalize.ts       # Data normalization\n```\n\n## Security\n\nThis library does not store tokens or credentials.\nIt is authentication agnostic and accepts any valid GitHub token.\n\n**Required scopes:**\n\n- `repo` (private repo access)\n- `read:user`\n\n## Development\n\n### Setup\n\n```bash\ngit clone https://github.com/octoreport/core.git\ncd core\nnpm install\n```\n\n### Scripts\n\n```bash\nnpm run build         # Build the library\nnpm test              # Run all tests\nnpm run lint          # Lint source\nnpm run lint:fix      # Fix lint issues\nnpm run format        # Format code\n```\n\n### Testing\n\n```bash\nnpm test              # Run all tests\nnpm run dev:test      # Run tests in watch mode\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n**Security Note**: This repo uses detect-secrets in pre-commit and CI.\nAll contributors must have detect-secrets installed and an up-to-date `.secrets.baseline`.\n\nQuick start:\n\n```bash\nbrew install pipx\npipx install detect-secrets\ndetect-secrets scan \u003e .secrets.baseline\ngit add .secrets.baseline\n```\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Acknowledgements\n\n- [luxon](https://moment.github.io/luxon/) for timezone handling\n- [@octokit/rest](https://github.com/octokit/rest.js) for GitHub API integration patterns\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foctoreport%2Fcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foctoreport%2Fcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foctoreport%2Fcore/lists"}