11import { execSync } from "node:child_process" ;
2- import { writeFileSync , mkdirSync } from "node:fs" ;
2+ import { writeFileSync , mkdirSync , statSync } from "node:fs" ;
33import { dirname , resolve } from "node:path" ;
44import { fileURLToPath } from "node:url" ;
55import picomatch from "picomatch" ;
@@ -19,6 +19,15 @@ export interface ContributorMappingOptions {
1919 * @example "DuendeSoftware/docs.duendesoftware.com"
2020 */
2121 repo : string ;
22+
23+ /**
24+ * Maximum age (in days) of an existing contributors.json before it is
25+ * regenerated. If the file exists and is younger than this, the plugin
26+ * short-circuits and skips the expensive git + API work.
27+ * Set to 0 to always regenerate.
28+ * @default 0
29+ */
30+ maxAgeDays ?: number ;
2231}
2332
2433/**
@@ -36,13 +45,13 @@ export interface ContributorMappingOptions {
3645export default function contributorMapping (
3746 options : ContributorMappingOptions
3847) : AstroIntegration {
39- const { include, repo } = options ;
48+ const { include, repo, maxAgeDays = 0 } = options ;
4049
4150 return {
4251 name : "contributor-mapping" ,
4352 hooks : {
4453 "astro:config:setup" : async ( { logger } ) => {
45- await generateContributors ( include , repo , logger ) ;
54+ await generateContributors ( include , repo , maxAgeDays , logger ) ;
4655 } ,
4756 } ,
4857 } ;
@@ -384,8 +393,26 @@ function buildPerFileContributors(
384393async function generateContributors (
385394 include : string [ ] ,
386395 repo : string ,
396+ maxAgeDays : number ,
387397 logger : Logger
388398) {
399+ // Short-circuit if the mapping file is fresh enough
400+ if ( maxAgeDays > 0 ) {
401+ try {
402+ const stat = statSync ( outPath ) ;
403+ const ageDays =
404+ ( Date . now ( ) - stat . mtimeMs ) / ( 1000 * 60 * 60 * 24 ) ;
405+ if ( ageDays < maxAgeDays ) {
406+ logger . info (
407+ `contributors.json is ${ ageDays . toFixed ( 1 ) } days old (< ${ maxAgeDays } ) — skipping regeneration`
408+ ) ;
409+ return ;
410+ }
411+ } catch {
412+ // File doesn't exist yet — continue to generate
413+ }
414+ }
415+
389416 const gitPrefix = getGitPrefix ( ) ;
390417 const isMatch = picomatch ( include ) ;
391418
0 commit comments