@ksw8954/git-ai-commit 1.0.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.
Files changed (77) hide show
  1. package/AGENTS.md +38 -0
  2. package/CRUSH.md +28 -0
  3. package/Makefile +32 -0
  4. package/README.md +145 -0
  5. package/dist/commands/ai.d.ts +35 -0
  6. package/dist/commands/ai.d.ts.map +1 -0
  7. package/dist/commands/ai.js +206 -0
  8. package/dist/commands/ai.js.map +1 -0
  9. package/dist/commands/commit.d.ts +17 -0
  10. package/dist/commands/commit.d.ts.map +1 -0
  11. package/dist/commands/commit.js +126 -0
  12. package/dist/commands/commit.js.map +1 -0
  13. package/dist/commands/config.d.ts +33 -0
  14. package/dist/commands/config.d.ts.map +1 -0
  15. package/dist/commands/config.js +141 -0
  16. package/dist/commands/config.js.map +1 -0
  17. package/dist/commands/configCommand.d.ts +20 -0
  18. package/dist/commands/configCommand.d.ts.map +1 -0
  19. package/dist/commands/configCommand.js +108 -0
  20. package/dist/commands/configCommand.js.map +1 -0
  21. package/dist/commands/git.d.ts +26 -0
  22. package/dist/commands/git.d.ts.map +1 -0
  23. package/dist/commands/git.js +150 -0
  24. package/dist/commands/git.js.map +1 -0
  25. package/dist/commands/loadEnv.d.ts +2 -0
  26. package/dist/commands/loadEnv.d.ts.map +1 -0
  27. package/dist/commands/loadEnv.js +11 -0
  28. package/dist/commands/loadEnv.js.map +1 -0
  29. package/dist/commands/prCommand.d.ts +16 -0
  30. package/dist/commands/prCommand.d.ts.map +1 -0
  31. package/dist/commands/prCommand.js +61 -0
  32. package/dist/commands/prCommand.js.map +1 -0
  33. package/dist/commands/tag.d.ts +17 -0
  34. package/dist/commands/tag.d.ts.map +1 -0
  35. package/dist/commands/tag.js +127 -0
  36. package/dist/commands/tag.js.map +1 -0
  37. package/dist/index.d.ts +3 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +23 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/prompts/commit.d.ts +3 -0
  42. package/dist/prompts/commit.d.ts.map +1 -0
  43. package/dist/prompts/commit.js +101 -0
  44. package/dist/prompts/commit.js.map +1 -0
  45. package/dist/prompts/pr.d.ts +3 -0
  46. package/dist/prompts/pr.d.ts.map +1 -0
  47. package/dist/prompts/pr.js +58 -0
  48. package/dist/prompts/pr.js.map +1 -0
  49. package/dist/prompts/tag.d.ts +3 -0
  50. package/dist/prompts/tag.d.ts.map +1 -0
  51. package/dist/prompts/tag.js +42 -0
  52. package/dist/prompts/tag.js.map +1 -0
  53. package/eslint.config.js +35 -0
  54. package/jest.config.js +16 -0
  55. package/package.json +51 -0
  56. package/src/__tests__/ai.test.ts +185 -0
  57. package/src/__tests__/commitCommand.test.ts +155 -0
  58. package/src/__tests__/config.test.ts +238 -0
  59. package/src/__tests__/git.test.ts +88 -0
  60. package/src/__tests__/integration.test.ts +138 -0
  61. package/src/__tests__/prCommand.test.ts +121 -0
  62. package/src/__tests__/tagCommand.test.ts +197 -0
  63. package/src/commands/ai.ts +266 -0
  64. package/src/commands/commit.ts +215 -0
  65. package/src/commands/config.ts +182 -0
  66. package/src/commands/configCommand.ts +139 -0
  67. package/src/commands/git.ts +174 -0
  68. package/src/commands/history.ts +82 -0
  69. package/src/commands/loadEnv.ts +5 -0
  70. package/src/commands/log.ts +71 -0
  71. package/src/commands/prCommand.ts +108 -0
  72. package/src/commands/tag.ts +230 -0
  73. package/src/index.ts +29 -0
  74. package/src/prompts/commit.ts +105 -0
  75. package/src/prompts/pr.ts +64 -0
  76. package/src/prompts/tag.ts +48 -0
  77. package/tsconfig.json +19 -0
@@ -0,0 +1,230 @@
1
+ import { Command } from 'commander';
2
+ import readline from 'readline';
3
+ import { AIService, AIServiceConfig } from './ai';
4
+ import { ConfigService } from './config';
5
+ import { GitService } from './git';
6
+ import { LogService } from './log';
7
+
8
+ export interface TagOptions {
9
+ apiKey?: string;
10
+ baseUrl?: string;
11
+ model?: string;
12
+ message?: string;
13
+ baseTag?: string;
14
+ prompt?: string;
15
+ }
16
+
17
+ export class TagCommand {
18
+ private program: Command;
19
+
20
+ constructor() {
21
+ this.program = new Command('tag')
22
+ .description('Create an annotated git tag with optional AI-generated notes')
23
+ .argument('<name>', 'Tag name to create')
24
+ .option('-k, --api-key <key>', 'OpenAI API key (overrides env var)')
25
+ .option('--base-url <url>', 'Custom API base URL (overrides env var)')
26
+ .option('-m, --model <model>', 'Model to use (overrides env var)')
27
+ .option('--message <message>', 'Tag message to use directly (skips AI generation)')
28
+ .option('-t, --base-tag <tag>', 'Existing tag to diff against when generating notes')
29
+ .option('--prompt <text>', 'Additional instructions to append to the AI prompt for this tag')
30
+ .action(async (tagName: string, options: TagOptions) => {
31
+ await this.handleTag(tagName, options);
32
+ });
33
+ }
34
+
35
+ private resolveAIConfig(options: TagOptions): AIServiceConfig {
36
+ const storedConfig = ConfigService.getConfig();
37
+
38
+ const mergedApiKey = options.apiKey || storedConfig.apiKey;
39
+ const mergedBaseURL = options.baseUrl || storedConfig.baseURL;
40
+ const mergedModel = options.model || storedConfig.model;
41
+
42
+ ConfigService.validateConfig({
43
+ apiKey: mergedApiKey,
44
+ language: storedConfig.language
45
+ });
46
+
47
+ return {
48
+ apiKey: mergedApiKey!,
49
+ baseURL: mergedBaseURL,
50
+ model: mergedModel,
51
+ language: storedConfig.language
52
+ };
53
+ }
54
+
55
+ private async handleTag(tagName: string, options: TagOptions): Promise<void> {
56
+ const trimmedName = tagName?.trim();
57
+
58
+ if (!trimmedName) {
59
+ console.error('Tag name is required.');
60
+ await LogService.append({
61
+ command: 'tag',
62
+ args: { name: tagName, ...options, apiKey: options.apiKey ? '***' : undefined },
63
+ status: 'failure',
64
+ details: 'missing tag name'
65
+ });
66
+ process.exit(1);
67
+ return;
68
+ }
69
+
70
+ let tagMessage = options.message?.trim();
71
+
72
+ if (!tagMessage) {
73
+ console.log('Collecting commit history for tag notes...');
74
+
75
+ let baseTag = options.baseTag?.trim();
76
+ if (!baseTag) {
77
+ const latestTagResult = await GitService.getLatestTag();
78
+ if (latestTagResult.success && latestTagResult.tag) {
79
+ baseTag = latestTagResult.tag;
80
+ console.log(`Using latest tag ${baseTag} as base.`);
81
+ } else {
82
+ console.log('No existing tag found; using entire commit history.');
83
+ }
84
+ }
85
+
86
+ const historyResult = await GitService.getCommitSummariesSince(baseTag);
87
+ if (!historyResult.success || !historyResult.log) {
88
+ console.error('Error:', historyResult.error ?? 'Unable to read commit history.');
89
+ await LogService.append({
90
+ command: 'tag',
91
+ args: { name: trimmedName, ...options, apiKey: options.apiKey ? '***' : undefined },
92
+ status: 'failure',
93
+ details: historyResult.error ?? 'Unable to read commit history.'
94
+ });
95
+ process.exit(1);
96
+ return;
97
+ }
98
+
99
+ let aiConfig: AIServiceConfig;
100
+
101
+ try {
102
+ aiConfig = this.resolveAIConfig(options);
103
+ } catch (error) {
104
+ const message = error instanceof Error ? error.message : String(error);
105
+ console.error('Error:', message);
106
+ await LogService.append({
107
+ command: 'tag',
108
+ args: { name: trimmedName, ...options, apiKey: options.apiKey ? '***' : undefined },
109
+ status: 'failure',
110
+ details: message
111
+ });
112
+ process.exit(1);
113
+ return;
114
+ }
115
+
116
+ const aiService = new AIService(aiConfig);
117
+ const aiResult = await aiService.generateTagNotes(trimmedName, historyResult.log, options.prompt);
118
+
119
+ if (!aiResult.success || !aiResult.notes) {
120
+ console.error('Error:', aiResult.error ?? 'Failed to generate tag notes.');
121
+ await LogService.append({
122
+ command: 'tag',
123
+ args: { name: trimmedName, ...options, apiKey: options.apiKey ? '***' : undefined },
124
+ status: 'failure',
125
+ details: aiResult.error ?? 'Failed to generate tag notes.'
126
+ });
127
+ process.exit(1);
128
+ return;
129
+ }
130
+
131
+ tagMessage = aiResult.notes;
132
+ }
133
+
134
+ // Show preview and confirm before creating the tag
135
+ console.log('\nTag message preview:\n');
136
+ console.log(tagMessage);
137
+
138
+ const shouldCreate = await this.confirmTagCreate(trimmedName);
139
+
140
+ if (!shouldCreate) {
141
+ console.log('Tag creation cancelled by user.');
142
+ await LogService.append({
143
+ command: 'tag',
144
+ args: { name: trimmedName, ...options, apiKey: options.apiKey ? '***' : undefined },
145
+ status: 'cancelled',
146
+ details: 'user declined tag creation'
147
+ });
148
+ return;
149
+ }
150
+
151
+ console.log(`Creating annotated tag ${trimmedName}...`);
152
+ const created = await GitService.createAnnotatedTag(trimmedName, tagMessage);
153
+
154
+ if (!created) {
155
+ console.error('❌ Failed to create tag');
156
+ await LogService.append({
157
+ command: 'tag',
158
+ args: { name: trimmedName, ...options, apiKey: options.apiKey ? '***' : undefined },
159
+ status: 'failure',
160
+ details: 'git tag creation failed'
161
+ });
162
+ process.exit(1);
163
+ return;
164
+ }
165
+
166
+ console.log(`✅ Tag ${trimmedName} created successfully!`);
167
+
168
+ const shouldPush = await this.confirmTagPush(trimmedName);
169
+
170
+ if (shouldPush) {
171
+ console.log(`Pushing tag ${trimmedName} to remote...`);
172
+ const pushSuccess = await GitService.pushTag(trimmedName);
173
+
174
+ if (pushSuccess) {
175
+ console.log(`✅ Tag ${trimmedName} pushed successfully!`);
176
+ } else {
177
+ console.error('❌ Failed to push tag to remote');
178
+ await LogService.append({
179
+ command: 'tag',
180
+ args: { name: trimmedName, ...options, apiKey: options.apiKey ? '***' : undefined },
181
+ status: 'failure',
182
+ details: 'tag push failed'
183
+ });
184
+ process.exit(1);
185
+ }
186
+ }
187
+
188
+ await LogService.append({
189
+ command: 'tag',
190
+ args: { name: trimmedName, ...options, apiKey: options.apiKey ? '***' : undefined },
191
+ status: 'success'
192
+ });
193
+ }
194
+
195
+ private async confirmTagPush(tagName: string): Promise<boolean> {
196
+ const rl = readline.createInterface({
197
+ input: process.stdin,
198
+ output: process.stdout
199
+ });
200
+
201
+ const answer: string = await new Promise(resolve => {
202
+ rl.question(`Push tag ${tagName} to remote? (y/n): `, resolve);
203
+ });
204
+
205
+ rl.close();
206
+
207
+ const normalized = answer.trim().toLowerCase();
208
+ return normalized === 'y' || normalized === 'yes';
209
+ }
210
+
211
+ private async confirmTagCreate(tagName: string): Promise<boolean> {
212
+ const rl = readline.createInterface({
213
+ input: process.stdin,
214
+ output: process.stdout
215
+ });
216
+
217
+ const answer: string = await new Promise(resolve => {
218
+ rl.question(`Create annotated tag ${tagName}? (y/n): `, resolve);
219
+ });
220
+
221
+ rl.close();
222
+
223
+ const normalized = answer.trim().toLowerCase();
224
+ return normalized === 'y' || normalized === 'yes';
225
+ }
226
+
227
+ getCommand(): Command {
228
+ return this.program;
229
+ }
230
+ }
package/src/index.ts ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import { CommitCommand } from './commands/commit';
5
+ import { ConfigCommand } from './commands/configCommand';
6
+ import { PullRequestCommand } from './commands/prCommand';
7
+ import { TagCommand } from './commands/tag';
8
+ import { HistoryCommand } from './commands/history';
9
+
10
+ const program = new Command();
11
+
12
+ program
13
+ .name('git-ai-commit')
14
+ .description('AI-powered git commit message generator')
15
+ .version('1.0.0');
16
+
17
+ const commitCommand = new CommitCommand();
18
+ const configCommand = new ConfigCommand();
19
+ const pullRequestCommand = new PullRequestCommand();
20
+ const tagCommand = new TagCommand();
21
+ const historyCommand = new HistoryCommand();
22
+
23
+ program.addCommand(commitCommand.getCommand());
24
+ program.addCommand(configCommand.getCommand());
25
+ program.addCommand(pullRequestCommand.getCommand());
26
+ program.addCommand(tagCommand.getCommand());
27
+ program.addCommand(historyCommand.getCommand());
28
+
29
+ program.parse();
@@ -0,0 +1,105 @@
1
+ export type CommitPromptLanguage = 'ko' | 'en';
2
+
3
+ export const generateCommitPrompt = (
4
+ gitContext: string,
5
+ customInstructions = '',
6
+ language: CommitPromptLanguage = 'ko'
7
+ ): string => {
8
+ const languageRequirement = language === 'ko'
9
+ ? `## Korean Language Requirement
10
+ - All commit messages MUST be written in Korean (한글)
11
+ - Description, body, and footer text must use Korean
12
+ - Keep Korean messages concise`
13
+ : `## English Language Requirement
14
+ - All commit messages MUST be written in English
15
+ - Description, body, and footer text must use English
16
+ - Keep the tone concise and professional`;
17
+
18
+ const bodyGuidelines = language === 'ko'
19
+ ? `### Body Guidelines (Optional)
20
+ - Insert one blank line after the description and express additional details as
21
+ markdown bullet points (\`- \`) written in Korean.
22
+ - Each bullet should explain the "what" and "why", not the "how".
23
+ - Wrap at 72 characters per line and keep bullets concise.
24
+ - Use the bullet body only for complex changes that need clarification; omit it
25
+ when the summary line is sufficient.`
26
+ : `### Body Guidelines (Optional)
27
+ - Insert one blank line after the description and use markdown bullet points (\`- \`) in English.
28
+ - Each bullet should explain the "what" and "why", not the "how".
29
+ - Wrap at 72 characters per line and keep bullets concise.
30
+ - Include a body only for complex changes that need clarification.`;
31
+
32
+ const footerGuidelines = language === 'ko'
33
+ ? `### Footer Guidelines (Optional)
34
+ - Start one blank line after body
35
+ - **Breaking Changes**: \`BREAKING CHANGE: description\``
36
+ : `### Footer Guidelines (Optional)
37
+ - Start one blank line after the body
38
+ - **Breaking Changes**: \`BREAKING CHANGE: description\``;
39
+
40
+ return `# Conventional Commit Message Generator
41
+ ## System Instructions
42
+ You are an expert Git commit message generator that creates conventional commit messages based on staged changes. Analyze the provided git diff output and generate appropriate conventional commit messages following the specification.
43
+
44
+ ${customInstructions}
45
+
46
+ ## CRITICAL: Commit Message Output Rules
47
+ - DO NOT include any memory bank status indicators like "[Memory Bank: Active]" or "[Memory Bank: Missing]"
48
+ - DO NOT include any task-specific formatting or artifacts from other rules
49
+ - ONLY Generate a clean conventional commit message as specified below
50
+
51
+ ${gitContext}
52
+
53
+ ## Conventional Commits Format
54
+ Generate commit messages following this exact structure:
55
+ \n<type>[optional scope]: <description>
56
+ [optional body]
57
+ [optional footer(s)]
58
+
59
+ ### Core Types (Required)
60
+ - **feat**: New feature or functionality (MINOR version bump)
61
+ - **fix**: Bug fix or error correction (PATCH version bump)
62
+
63
+ ### Additional Types (Extended)
64
+ - **docs**: Documentation changes only
65
+ - **style**: Code style changes (whitespace, formatting, semicolons, etc.)
66
+ - **refactor**: Code refactoring without feature changes or bug fixes
67
+ - **perf**: Performance improvements
68
+ - **test**: Adding or fixing tests
69
+ - **build**: Build system or external dependency changes
70
+ - **ci**: CI/CD configuration changes
71
+ - **chore**: Maintenance tasks, tooling changes
72
+ - **revert**: Reverting previous commits
73
+
74
+ ### Scope Guidelines
75
+ - Use parentheses: \`feat(api):\`, \`fix(ui):\`
76
+ - Common scopes: \`api\`, \`ui\`, \`auth\`, \`db\`, \`config\`, \`deps\`, \`docs\`
77
+ - For monorepos: package or module names
78
+ - Keep scope concise and lowercase
79
+
80
+ ### Description Rules
81
+ - Use imperative mood ("add" not "added" or "adds")
82
+ - Start with lowercase letter
83
+ - No period at the end
84
+ - Be concise but descriptive
85
+ - Must be written as a single line without line breaks
86
+
87
+ ${languageRequirement}
88
+
89
+ ${bodyGuidelines}
90
+
91
+ ${footerGuidelines}
92
+
93
+ ## Analysis Instructions
94
+ When analyzing staged changes:
95
+ 1. Determine Primary Type based on the nature of changes
96
+ 2. Identify Scope from modified directories or modules
97
+ 3. Craft Description focusing on the most significant change
98
+ 4. Determine if there are Breaking Changes
99
+ 5. For complex changes, include a detailed body explaining what and why
100
+ 6. Add appropriate footers for issue references or breaking changes
101
+
102
+ For significant changes, include a detailed body explaining the changes.
103
+
104
+ Return ONLY the commit message in the conventional format, nothing else.`;
105
+ };
@@ -0,0 +1,64 @@
1
+ export type PullRequestPromptLanguage = 'ko' | 'en';
2
+
3
+ export const generatePullRequestPrompt = (
4
+ baseBranch: string,
5
+ compareBranch: string,
6
+ customInstructions = '',
7
+ language: PullRequestPromptLanguage = 'ko'
8
+ ): string => {
9
+ const languageRequirement = language === 'ko'
10
+ ? 'Write the entire pull request title and body in Korean.'
11
+ : 'Write the entire pull request title and body in English.';
12
+
13
+ const titleGuidelines = language === 'ko'
14
+ ? `### 제목 작성 규칙
15
+ - 한 줄짜리 명령형 문장으로 작성합니다 (예: "Refactor validator 로직 정리").
16
+ - 접두사는 사용하지 않습니다 (예: "Feat:" 금지).
17
+ - 72자를 넘지 않도록 합니다.`
18
+ : `### Title Guidelines
19
+ - Use a single imperative sentence (e.g., "Refactor validator handling").
20
+ - Do not prefix with labels like "Feat:".
21
+ - Keep the title under 72 characters.`;
22
+
23
+ const summaryGuidelines = language === 'ko'
24
+ ? `### 본문 구성
25
+ - "## Summary" 헤딩 아래에 핵심 변경 사항을 강조하는 불릿 리스트를 작성합니다.
26
+ - 각 불릿은 "무엇을"과 "왜"를 포함하고, 한국어로 1줄 내로 작성합니다.
27
+ - 영향이 큰 변경은 별도의 불릿으로 구분합니다.`
28
+ : `### Body Structure
29
+ - Under a "## Summary" heading, add bullet points that explain what changed and why.
30
+ - Keep each bullet to a single concise English sentence.
31
+ - Separate large areas of impact into individual bullets.`;
32
+
33
+ const testingGuidelines = language === 'ko'
34
+ ? `### 테스트 정보
35
+ - "## Testing" 헤딩 아래에 검증 방법을 불릿으로 정리합니다.
36
+ - 수동 테스트, 자동 테스트, 혹은 "테스트 필요 없음"을 명시합니다.`
37
+ : `### Testing Details
38
+ - Under a "## Testing" heading, list how the changes were verified.
39
+ - Call out manual steps, automated checks, or "Not tested" when applicable.`;
40
+
41
+ return `You are an expert software engineer preparing a pull request description.
42
+ Compare the git history and code changes between the base branch "${baseBranch}" and the compare branch "${compareBranch}" and summarise the meaningful differences in a PR-friendly format.
43
+
44
+ ${customInstructions}
45
+
46
+ ## Output Contract
47
+ - Return ONLY markdown suitable for pasting into a pull request form.
48
+ - First line MUST be the pull request title, adhering to the title guidelines below.
49
+ - After one blank line, include the sections exactly as shown:
50
+ - "## Summary"
51
+ - "## Testing"
52
+ - If a section has no content, provide a single bullet: "- 없음" in Korean or "- None" in English (use language-appropriate wording).
53
+ - Do not invent changes that are not present in the provided diff.
54
+
55
+ ${languageRequirement}
56
+
57
+ ${titleGuidelines}
58
+
59
+ ${summaryGuidelines}
60
+
61
+ ${testingGuidelines}
62
+
63
+ Focus on user-facing impact, breaking changes, and notable refactors. Avoid raw diff dumps.`;
64
+ };
@@ -0,0 +1,48 @@
1
+ export type TagPromptLanguage = 'ko' | 'en';
2
+
3
+ export const generateTagPrompt = (
4
+ tagName: string,
5
+ customInstructions = '',
6
+ language: TagPromptLanguage = 'ko'
7
+ ): string => {
8
+ const summaryInstruction = language === 'ko'
9
+ ? 'Begin with a short summary sentence (in Korean) that captures the overall impact of the release.'
10
+ : 'Begin with a short summary sentence (in English) that captures the overall impact of the release.';
11
+
12
+ const listInstruction = language === 'ko'
13
+ ? 'After the summary, list every change as a markdown bullet (-) grouped by category: 사용자 기능, 버그 수정, 유지 보수.'
14
+ : 'After the summary, list every change as a markdown bullet (-) grouped by category: User Features, Bug Fixes, Maintenance.';
15
+
16
+ const emptyCategoryInstruction = language === 'ko'
17
+ ? 'If a category has no changes, include a bullet stating - 해당 사항 없음.'
18
+ : 'If a category has no changes, include a bullet stating - None.';
19
+
20
+ const noChangesInstruction = language === 'ko'
21
+ ? 'If no changes exist at all, state "변경 사항 없음" plainly.'
22
+ : 'If no changes exist at all, state "No changes to report." plainly.';
23
+
24
+ const outputLanguageLine = language === 'ko'
25
+ ? 'Write the release notes in Korean using concise markdown.'
26
+ : 'Write the release notes in English using concise markdown.';
27
+
28
+ return `You are an experienced release manager. Produce clear, user-facing release notes that describe the differences between the previous tag and ${tagName}.
29
+
30
+ ## Objective
31
+ Summarize the meaningful changes that occurred between the prior release tag and ${tagName}. Treat the commit log provided by the user message as the complete history of changes since the previous tag.
32
+
33
+ ## Input Context
34
+ - Target tag to publish: ${tagName}
35
+ - Commit history between the previous tag and ${tagName} will be supplied in the user message (most recent first).
36
+
37
+ ${customInstructions}
38
+
39
+ ## Output Requirements
40
+ - ${outputLanguageLine}
41
+ - ${summaryInstruction}
42
+ - ${listInstruction}
43
+ - Use short phrases for each bullet and include scope/component names when helpful, without copying commit messages verbatim.
44
+ - ${emptyCategoryInstruction}
45
+ - ${noChangesInstruction}
46
+ - Do not invent work beyond what appears in the commit log.
47
+ - Return only the release notes content with no surrounding commentary.`;
48
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "lib": ["ES2020"],
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "declaration": true,
13
+ "declarationMap": true,
14
+ "sourceMap": true,
15
+ "resolveJsonModule": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
19
+ }