@aida-dev/core 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +17 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -47,12 +47,20 @@ var CommitStream = z.object({
|
|
|
47
47
|
import { simpleGit as simpleGit2 } from "simple-git";
|
|
48
48
|
|
|
49
49
|
// src/tags/ai-tags.ts
|
|
50
|
-
var DEFAULT_PATTERNS = [
|
|
51
|
-
|
|
50
|
+
var DEFAULT_PATTERNS = [
|
|
51
|
+
"\\b(ai|copilot|cursor|windsurf|codeium|claude|chatgpt|gemini)\\b",
|
|
52
|
+
"\\[ai\\]"
|
|
53
|
+
];
|
|
54
|
+
var DEFAULT_TRAILER_PATTERNS = [
|
|
55
|
+
"^AI:\\s*true$",
|
|
56
|
+
"^X-AI:\\s*true$",
|
|
57
|
+
"^Co-authored-by:.*bot.*$",
|
|
58
|
+
"^Co-authored-by:.*\\b(anthropic|openai|github\\.com)\\b.*$"
|
|
59
|
+
];
|
|
52
60
|
function createAITagger(config = { patterns: [] }) {
|
|
53
61
|
const allPatterns = [...DEFAULT_PATTERNS, ...config.patterns];
|
|
54
62
|
const messageRegexes = allPatterns.map((pattern) => new RegExp(pattern, "im"));
|
|
55
|
-
const trailerRegexes = DEFAULT_TRAILER_PATTERNS.map((pattern) => new RegExp(pattern, "
|
|
63
|
+
const trailerRegexes = DEFAULT_TRAILER_PATTERNS.map((pattern) => new RegExp(pattern, "mi"));
|
|
56
64
|
return (message) => {
|
|
57
65
|
const sources = [];
|
|
58
66
|
let ai = false;
|
|
@@ -195,12 +203,12 @@ async function collectCommits(options) {
|
|
|
195
203
|
logger?.info(
|
|
196
204
|
`Collecting commits from ${sinceDate?.toISOString() || "beginning"} to ${untilDate.toISOString()}`
|
|
197
205
|
);
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
};
|
|
203
|
-
const logResult = await git.log(
|
|
206
|
+
const logArgs = [defaultBranch];
|
|
207
|
+
if (sinceDate) {
|
|
208
|
+
logArgs.push(`--after=${sinceDate.toISOString()}`);
|
|
209
|
+
}
|
|
210
|
+
logArgs.push(`--before=${untilDate.toISOString()}`);
|
|
211
|
+
const logResult = await git.log(logArgs);
|
|
204
212
|
logger?.info(`Found ${logResult.all.length} commits`);
|
|
205
213
|
const aiTagger = createAITagger({ patterns: aiPatterns });
|
|
206
214
|
const commits = [];
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schema/commit.ts","../src/git/collect.ts","../src/tags/ai-tags.ts","../src/git/diff.ts","../src/utils/dates.ts","../src/io/fs.ts","../src/utils/log.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const FileChange = z.object({\n path: z.string(),\n status: z.enum(['added', 'modified', 'deleted', 'renamed']).optional(), // best-effort\n additions: z.number().int().nonnegative(),\n deletions: z.number().int().nonnegative(),\n});\n\nexport const Commit = z.object({\n hash: z.string(),\n authorName: z.string(),\n authorEmail: z.string(),\n authorDate: z.string().datetime(), // ISO\n committerName: z.string(),\n committerEmail: z.string(),\n committerDate: z.string().datetime(),\n message: z.string(),\n parents: z.array(z.string()),\n branch: z.string().optional(), // best-effort if known\n inDefaultBranchAncestry: z.boolean(), // set during collect\n tags: z.object({\n ai: z.boolean(),\n sources: z.array(z.string()), // which heuristic matched\n }),\n stats: z.object({\n totalAdditions: z.number().int().nonnegative(),\n totalDeletions: z.number().int().nonnegative(),\n files: z.array(FileChange),\n }),\n});\n\nexport type Commit = z.infer<typeof Commit>;\n\nexport const CommitStream = z.object({\n repoPath: z.string(),\n defaultBranch: z.string(),\n generatedAt: z.string().datetime(),\n since: z.string().optional(),\n until: z.string().optional(),\n aiPatterns: z.array(z.string()),\n commits: z.array(Commit),\n});\n\nexport type CommitStream = z.infer<typeof CommitStream>;\n","import { simpleGit, SimpleGit } from 'simple-git';\nimport { Commit, CommitStream } from '../schema/commit.js';\nimport { createAITagger } from '../tags/ai-tags.js';\nimport { getDiffStats } from './diff.js';\nimport { parseRelativeDate, formatISODate } from '../utils/dates.js';\nimport { Logger } from '../utils/log.js';\n\nexport interface CollectOptions {\n repoPath: string;\n since?: string;\n until?: string;\n aiPatterns?: string[];\n defaultBranch?: string;\n logger?: Logger;\n}\n\nexport async function detectDefaultBranch(git: SimpleGit): Promise<string> {\n try {\n // Try to get the default branch from origin/HEAD\n const result = await git.raw(['symbolic-ref', 'refs/remotes/origin/HEAD']);\n const match = result.match(/refs\\/remotes\\/origin\\/(.+)/);\n if (match) {\n return match[1].trim();\n }\n } catch {\n // Fallback logic\n }\n\n // Fallback to common branch names\n const branches = await git.branch(['-r']);\n if (branches.all.includes('origin/main')) {\n return 'main';\n }\n if (branches.all.includes('origin/master')) {\n return 'master';\n }\n\n // Last resort: use current branch\n const current = await git.branch();\n return current.current || 'main';\n}\n\nexport async function collectCommits(options: CollectOptions): Promise<CommitStream> {\n const {\n repoPath,\n since,\n until,\n aiPatterns = [],\n defaultBranch: providedDefaultBranch,\n logger,\n } = options;\n\n const git = simpleGit(repoPath);\n\n // Detect default branch\n const defaultBranch = providedDefaultBranch || (await detectDefaultBranch(git));\n logger?.info(`Using default branch: ${defaultBranch}`);\n\n // Parse date range\n const sinceDate = since ? parseRelativeDate(since) : undefined;\n const untilDate = until ? parseRelativeDate(until) : new Date();\n\n logger?.info(\n `Collecting commits from ${sinceDate?.toISOString() || 'beginning'} to ${untilDate.toISOString()}`\n );\n\n // Build log options\n const logOptions: any = {\n from: defaultBranch,\n maxCount: 100, // Limit for demo\n };\n\n // Get commits\n const logResult = await git.log(logOptions);\n logger?.info(`Found ${logResult.all.length} commits`);\n\n // Create AI tagger\n const aiTagger = createAITagger({ patterns: aiPatterns });\n\n // Process commits\n const commits: Commit[] = [];\n for (const gitCommit of logResult.all) {\n logger?.debug(`Processing commit ${gitCommit.hash}`);\n\n // Get diff stats\n const stats = await getDiffStats(repoPath, gitCommit.hash);\n\n // Tag AI\n const aiTag = aiTagger(gitCommit.message);\n\n // Parse parents\n const parents = (gitCommit as any).parents\n ? (gitCommit as any).parents.split(' ').filter((p: string) => p)\n : [];\n\n const commit: Commit = {\n hash: gitCommit.hash,\n authorName: gitCommit.author_name,\n authorEmail: gitCommit.author_email,\n authorDate: new Date(gitCommit.date).toISOString(),\n committerName: gitCommit.author_name, // Simple-git doesn't separate these easily\n committerEmail: gitCommit.author_email,\n committerDate: new Date(gitCommit.date).toISOString(),\n message: gitCommit.message,\n parents,\n branch: defaultBranch,\n inDefaultBranchAncestry: true, // All commits are from default branch in MVP\n tags: aiTag,\n stats,\n };\n\n commits.push(commit);\n }\n\n return {\n repoPath,\n defaultBranch,\n generatedAt: formatISODate(new Date()),\n since,\n until,\n aiPatterns: [...aiPatterns],\n commits,\n };\n}\n","export interface AITagResult {\n ai: boolean;\n sources: string[];\n}\n\nexport interface AITagConfig {\n patterns: string[];\n}\n\nconst DEFAULT_PATTERNS = ['\\\\b(ai|copilot|cursor|windsurf|codeium)\\\\b', '\\\\[ai\\\\]'];\n\nconst DEFAULT_TRAILER_PATTERNS = ['^AI:\\\\s*true$', '^X-AI:\\\\s*true$', '^Co-authored-by:.*bot.*$'];\n\nexport function createAITagger(\n config: AITagConfig = { patterns: [] }\n): (message: string) => AITagResult {\n const allPatterns = [...DEFAULT_PATTERNS, ...config.patterns];\n const messageRegexes = allPatterns.map((pattern) => new RegExp(pattern, 'im'));\n const trailerRegexes = DEFAULT_TRAILER_PATTERNS.map((pattern) => new RegExp(pattern, 'm'));\n\n return (message: string): AITagResult => {\n const sources: string[] = [];\n let ai = false;\n\n // Check message patterns\n for (let i = 0; i < messageRegexes.length; i++) {\n if (messageRegexes[i].test(message)) {\n ai = true;\n sources.push(`message_pattern:${allPatterns[i]}`);\n }\n }\n\n // Check trailer patterns\n for (let i = 0; i < trailerRegexes.length; i++) {\n if (trailerRegexes[i].test(message)) {\n ai = true;\n sources.push(`trailer_pattern:${DEFAULT_TRAILER_PATTERNS[i]}`);\n }\n }\n\n return { ai, sources };\n };\n}\n","import { simpleGit } from 'simple-git';\nimport { FileChange } from '../schema/commit.js';\nimport type { z } from 'zod';\n\ntype FileChangeType = z.infer<typeof FileChange>;\n\nexport interface DiffStats {\n totalAdditions: number;\n totalDeletions: number;\n files: FileChangeType[];\n}\n\nexport async function getDiffStats(repoPath: string, commitHash: string): Promise<DiffStats> {\n const git = simpleGit(repoPath);\n\n try {\n // Get numstat for the commit\n const numstat = await git.raw(['show', '--numstat', '--format=', commitHash]);\n\n const files: FileChangeType[] = [];\n let totalAdditions = 0;\n let totalDeletions = 0;\n\n const lines = numstat\n .trim()\n .split('\\n')\n .filter((line) => line.trim());\n\n for (const line of lines) {\n const parts = line.split('\\t');\n if (parts.length >= 3) {\n const additions = parts[0] === '-' ? 0 : parseInt(parts[0], 10) || 0;\n const deletions = parts[1] === '-' ? 0 : parseInt(parts[1], 10) || 0;\n const path = parts[2];\n\n // Skip binary files (marked with -)\n if (parts[0] === '-' && parts[1] === '-') {\n continue;\n }\n\n totalAdditions += additions;\n totalDeletions += deletions;\n\n // Determine status (simplified)\n let status: FileChangeType['status'] = 'modified';\n if (additions > 0 && deletions === 0) {\n status = 'added';\n } else if (additions === 0 && deletions > 0) {\n status = 'deleted';\n }\n\n files.push({\n path,\n status,\n additions,\n deletions,\n });\n }\n }\n\n return {\n totalAdditions,\n totalDeletions,\n files,\n };\n } catch {\n // Return empty stats if diff fails\n return {\n totalAdditions: 0,\n totalDeletions: 0,\n files: [],\n };\n }\n}\n","export function parseRelativeDate(input: string): Date {\n const now = new Date();\n\n // Handle ISO dates\n if (input.includes('-') || input.includes('T')) {\n return new Date(input);\n }\n\n // Handle relative dates like \"90d\", \"30d\", etc.\n const match = input.match(/^(\\d+)([dwmy])$/);\n if (match) {\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n const result = new Date(now);\n\n switch (unit) {\n case 'd':\n result.setDate(result.getDate() - value);\n break;\n case 'w':\n result.setDate(result.getDate() - value * 7);\n break;\n case 'm':\n result.setMonth(result.getMonth() - value);\n break;\n case 'y':\n result.setFullYear(result.getFullYear() - value);\n break;\n }\n\n return result;\n }\n\n throw new Error(`Invalid date format: ${input}`);\n}\n\nexport function formatISODate(date: Date): string {\n return date.toISOString();\n}\n\nexport function daysBetween(start: Date, end: Date): number {\n const diffTime = Math.abs(end.getTime() - start.getTime());\n return Math.ceil(diffTime / (1000 * 60 * 60 * 24));\n}\n","import { promises as fs } from 'fs';\nimport { dirname } from 'path';\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n try {\n await fs.mkdir(dirPath, { recursive: true });\n } catch (error) {\n // Ignore if directory already exists\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') {\n throw error;\n }\n }\n}\n\nexport async function writeJSON(filePath: string, data: any): Promise<void> {\n await ensureDir(dirname(filePath));\n await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8');\n}\n\nexport async function readJSON<T>(filePath: string): Promise<T> {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content) as T;\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n","export interface Logger {\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n debug(message: string): void;\n}\n\nexport class ConsoleLogger implements Logger {\n constructor(private verbose: boolean = false) {}\n\n info(message: string): void {\n console.log(`[INFO] ${message}`);\n }\n\n warn(message: string): void {\n console.warn(`[WARN] ${message}`);\n }\n\n error(message: string): void {\n console.error(`[ERROR] ${message}`);\n }\n\n debug(message: string): void {\n if (this.verbose) {\n console.log(`[DEBUG] ${message}`);\n }\n }\n}\n\nexport const createLogger = (verbose: boolean = false): Logger => {\n return new ConsoleLogger(verbose);\n};\n"],"mappings":"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","names":["simpleGit","simpleGit"]}
|
|
1
|
+
{"version":3,"sources":["../src/schema/commit.ts","../src/git/collect.ts","../src/tags/ai-tags.ts","../src/git/diff.ts","../src/utils/dates.ts","../src/io/fs.ts","../src/utils/log.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const FileChange = z.object({\n path: z.string(),\n status: z.enum(['added', 'modified', 'deleted', 'renamed']).optional(), // best-effort\n additions: z.number().int().nonnegative(),\n deletions: z.number().int().nonnegative(),\n});\n\nexport const Commit = z.object({\n hash: z.string(),\n authorName: z.string(),\n authorEmail: z.string(),\n authorDate: z.string().datetime(), // ISO\n committerName: z.string(),\n committerEmail: z.string(),\n committerDate: z.string().datetime(),\n message: z.string(),\n parents: z.array(z.string()),\n branch: z.string().optional(), // best-effort if known\n inDefaultBranchAncestry: z.boolean(), // set during collect\n tags: z.object({\n ai: z.boolean(),\n sources: z.array(z.string()), // which heuristic matched\n }),\n stats: z.object({\n totalAdditions: z.number().int().nonnegative(),\n totalDeletions: z.number().int().nonnegative(),\n files: z.array(FileChange),\n }),\n});\n\nexport type Commit = z.infer<typeof Commit>;\n\nexport const CommitStream = z.object({\n repoPath: z.string(),\n defaultBranch: z.string(),\n generatedAt: z.string().datetime(),\n since: z.string().optional(),\n until: z.string().optional(),\n aiPatterns: z.array(z.string()),\n commits: z.array(Commit),\n});\n\nexport type CommitStream = z.infer<typeof CommitStream>;\n","import { simpleGit, SimpleGit } from 'simple-git';\nimport { Commit, CommitStream } from '../schema/commit.js';\nimport { createAITagger } from '../tags/ai-tags.js';\nimport { getDiffStats } from './diff.js';\nimport { parseRelativeDate, formatISODate } from '../utils/dates.js';\nimport { Logger } from '../utils/log.js';\n\nexport interface CollectOptions {\n repoPath: string;\n since?: string;\n until?: string;\n aiPatterns?: string[];\n defaultBranch?: string;\n logger?: Logger;\n}\n\nexport async function detectDefaultBranch(git: SimpleGit): Promise<string> {\n try {\n // Try to get the default branch from origin/HEAD\n const result = await git.raw(['symbolic-ref', 'refs/remotes/origin/HEAD']);\n const match = result.match(/refs\\/remotes\\/origin\\/(.+)/);\n if (match) {\n return match[1].trim();\n }\n } catch {\n // Fallback logic\n }\n\n // Fallback to common branch names\n const branches = await git.branch(['-r']);\n if (branches.all.includes('origin/main')) {\n return 'main';\n }\n if (branches.all.includes('origin/master')) {\n return 'master';\n }\n\n // Last resort: use current branch\n const current = await git.branch();\n return current.current || 'main';\n}\n\nexport async function collectCommits(options: CollectOptions): Promise<CommitStream> {\n const {\n repoPath,\n since,\n until,\n aiPatterns = [],\n defaultBranch: providedDefaultBranch,\n logger,\n } = options;\n\n const git = simpleGit(repoPath);\n\n // Detect default branch\n const defaultBranch = providedDefaultBranch || (await detectDefaultBranch(git));\n logger?.info(`Using default branch: ${defaultBranch}`);\n\n // Parse date range\n const sinceDate = since ? parseRelativeDate(since) : undefined;\n const untilDate = until ? parseRelativeDate(until) : new Date();\n\n logger?.info(\n `Collecting commits from ${sinceDate?.toISOString() || 'beginning'} to ${untilDate.toISOString()}`\n );\n\n // Build log arguments\n const logArgs: string[] = [defaultBranch];\n if (sinceDate) {\n logArgs.push(`--after=${sinceDate.toISOString()}`);\n }\n logArgs.push(`--before=${untilDate.toISOString()}`);\n\n // Get commits\n const logResult = await git.log(logArgs);\n logger?.info(`Found ${logResult.all.length} commits`);\n\n // Create AI tagger\n const aiTagger = createAITagger({ patterns: aiPatterns });\n\n // Process commits\n const commits: Commit[] = [];\n for (const gitCommit of logResult.all) {\n logger?.debug(`Processing commit ${gitCommit.hash}`);\n\n // Get diff stats\n const stats = await getDiffStats(repoPath, gitCommit.hash);\n\n // Tag AI\n const aiTag = aiTagger(gitCommit.message);\n\n // Parse parents\n const parents = (gitCommit as any).parents\n ? (gitCommit as any).parents.split(' ').filter((p: string) => p)\n : [];\n\n const commit: Commit = {\n hash: gitCommit.hash,\n authorName: gitCommit.author_name,\n authorEmail: gitCommit.author_email,\n authorDate: new Date(gitCommit.date).toISOString(),\n committerName: gitCommit.author_name, // Simple-git doesn't separate these easily\n committerEmail: gitCommit.author_email,\n committerDate: new Date(gitCommit.date).toISOString(),\n message: gitCommit.message,\n parents,\n branch: defaultBranch,\n inDefaultBranchAncestry: true, // All commits are from default branch in MVP\n tags: aiTag,\n stats,\n };\n\n commits.push(commit);\n }\n\n return {\n repoPath,\n defaultBranch,\n generatedAt: formatISODate(new Date()),\n since,\n until,\n aiPatterns: [...aiPatterns],\n commits,\n };\n}\n","export interface AITagResult {\n ai: boolean;\n sources: string[];\n}\n\nexport interface AITagConfig {\n patterns: string[];\n}\n\nconst DEFAULT_PATTERNS = [\n '\\\\b(ai|copilot|cursor|windsurf|codeium|claude|chatgpt|gemini)\\\\b',\n '\\\\[ai\\\\]',\n];\n\nconst DEFAULT_TRAILER_PATTERNS = [\n '^AI:\\\\s*true$',\n '^X-AI:\\\\s*true$',\n '^Co-authored-by:.*bot.*$',\n '^Co-authored-by:.*\\\\b(anthropic|openai|github\\\\.com)\\\\b.*$',\n];\n\nexport function createAITagger(\n config: AITagConfig = { patterns: [] }\n): (message: string) => AITagResult {\n const allPatterns = [...DEFAULT_PATTERNS, ...config.patterns];\n const messageRegexes = allPatterns.map((pattern) => new RegExp(pattern, 'im'));\n const trailerRegexes = DEFAULT_TRAILER_PATTERNS.map((pattern) => new RegExp(pattern, 'mi'));\n\n return (message: string): AITagResult => {\n const sources: string[] = [];\n let ai = false;\n\n // Check message patterns\n for (let i = 0; i < messageRegexes.length; i++) {\n if (messageRegexes[i].test(message)) {\n ai = true;\n sources.push(`message_pattern:${allPatterns[i]}`);\n }\n }\n\n // Check trailer patterns\n for (let i = 0; i < trailerRegexes.length; i++) {\n if (trailerRegexes[i].test(message)) {\n ai = true;\n sources.push(`trailer_pattern:${DEFAULT_TRAILER_PATTERNS[i]}`);\n }\n }\n\n return { ai, sources };\n };\n}\n","import { simpleGit } from 'simple-git';\nimport { FileChange } from '../schema/commit.js';\nimport type { z } from 'zod';\n\ntype FileChangeType = z.infer<typeof FileChange>;\n\nexport interface DiffStats {\n totalAdditions: number;\n totalDeletions: number;\n files: FileChangeType[];\n}\n\nexport async function getDiffStats(repoPath: string, commitHash: string): Promise<DiffStats> {\n const git = simpleGit(repoPath);\n\n try {\n // Get numstat for the commit\n const numstat = await git.raw(['show', '--numstat', '--format=', commitHash]);\n\n const files: FileChangeType[] = [];\n let totalAdditions = 0;\n let totalDeletions = 0;\n\n const lines = numstat\n .trim()\n .split('\\n')\n .filter((line) => line.trim());\n\n for (const line of lines) {\n const parts = line.split('\\t');\n if (parts.length >= 3) {\n const additions = parts[0] === '-' ? 0 : parseInt(parts[0], 10) || 0;\n const deletions = parts[1] === '-' ? 0 : parseInt(parts[1], 10) || 0;\n const path = parts[2];\n\n // Skip binary files (marked with -)\n if (parts[0] === '-' && parts[1] === '-') {\n continue;\n }\n\n totalAdditions += additions;\n totalDeletions += deletions;\n\n // Determine status (simplified)\n let status: FileChangeType['status'] = 'modified';\n if (additions > 0 && deletions === 0) {\n status = 'added';\n } else if (additions === 0 && deletions > 0) {\n status = 'deleted';\n }\n\n files.push({\n path,\n status,\n additions,\n deletions,\n });\n }\n }\n\n return {\n totalAdditions,\n totalDeletions,\n files,\n };\n } catch {\n // Return empty stats if diff fails\n return {\n totalAdditions: 0,\n totalDeletions: 0,\n files: [],\n };\n }\n}\n","export function parseRelativeDate(input: string): Date {\n const now = new Date();\n\n // Handle ISO dates\n if (input.includes('-') || input.includes('T')) {\n return new Date(input);\n }\n\n // Handle relative dates like \"90d\", \"30d\", etc.\n const match = input.match(/^(\\d+)([dwmy])$/);\n if (match) {\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n const result = new Date(now);\n\n switch (unit) {\n case 'd':\n result.setDate(result.getDate() - value);\n break;\n case 'w':\n result.setDate(result.getDate() - value * 7);\n break;\n case 'm':\n result.setMonth(result.getMonth() - value);\n break;\n case 'y':\n result.setFullYear(result.getFullYear() - value);\n break;\n }\n\n return result;\n }\n\n throw new Error(`Invalid date format: ${input}`);\n}\n\nexport function formatISODate(date: Date): string {\n return date.toISOString();\n}\n\nexport function daysBetween(start: Date, end: Date): number {\n const diffTime = Math.abs(end.getTime() - start.getTime());\n return Math.ceil(diffTime / (1000 * 60 * 60 * 24));\n}\n","import { promises as fs } from 'fs';\nimport { dirname } from 'path';\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n try {\n await fs.mkdir(dirPath, { recursive: true });\n } catch (error) {\n // Ignore if directory already exists\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') {\n throw error;\n }\n }\n}\n\nexport async function writeJSON(filePath: string, data: any): Promise<void> {\n await ensureDir(dirname(filePath));\n await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8');\n}\n\nexport async function readJSON<T>(filePath: string): Promise<T> {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content) as T;\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n","export interface Logger {\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n debug(message: string): void;\n}\n\nexport class ConsoleLogger implements Logger {\n constructor(private verbose: boolean = false) {}\n\n info(message: string): void {\n console.log(`[INFO] ${message}`);\n }\n\n warn(message: string): void {\n console.warn(`[WARN] ${message}`);\n }\n\n error(message: string): void {\n console.error(`[ERROR] ${message}`);\n }\n\n debug(message: string): void {\n if (this.verbose) {\n console.log(`[DEBUG] ${message}`);\n }\n }\n}\n\nexport const createLogger = (verbose: boolean = false): Logger => {\n return new ConsoleLogger(verbose);\n};\n"],"mappings":"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","names":["simpleGit","simpleGit"]}
|