clast-ai 0.1.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 (133) hide show
  1. package/.claude-plugin/plugin.json +22 -0
  2. package/.mcp.json +8 -0
  3. package/LICENSE +21 -0
  4. package/README.md +419 -0
  5. package/commands/clast-status.md +9 -0
  6. package/dist/config/defaults.d.ts +19 -0
  7. package/dist/config/defaults.d.ts.map +1 -0
  8. package/dist/config/defaults.js +44 -0
  9. package/dist/config/defaults.js.map +1 -0
  10. package/dist/config/index.d.ts +5 -0
  11. package/dist/config/index.d.ts.map +1 -0
  12. package/dist/config/index.js +48 -0
  13. package/dist/config/index.js.map +1 -0
  14. package/dist/db/index.d.ts +16 -0
  15. package/dist/db/index.d.ts.map +1 -0
  16. package/dist/db/index.js +54 -0
  17. package/dist/db/index.js.map +1 -0
  18. package/dist/db/queries.d.ts +44 -0
  19. package/dist/db/queries.d.ts.map +1 -0
  20. package/dist/db/queries.js +251 -0
  21. package/dist/db/queries.js.map +1 -0
  22. package/dist/db/schema.d.ts +3 -0
  23. package/dist/db/schema.d.ts.map +1 -0
  24. package/dist/db/schema.js +94 -0
  25. package/dist/db/schema.js.map +1 -0
  26. package/dist/db/types.d.ts +44 -0
  27. package/dist/db/types.d.ts.map +1 -0
  28. package/dist/db/types.js +2 -0
  29. package/dist/db/types.js.map +1 -0
  30. package/dist/llm/comment-generator.d.ts +26 -0
  31. package/dist/llm/comment-generator.d.ts.map +1 -0
  32. package/dist/llm/comment-generator.js +106 -0
  33. package/dist/llm/comment-generator.js.map +1 -0
  34. package/dist/llm/index.d.ts +24 -0
  35. package/dist/llm/index.d.ts.map +1 -0
  36. package/dist/llm/index.js +54 -0
  37. package/dist/llm/index.js.map +1 -0
  38. package/dist/llm/prompts.d.ts +9 -0
  39. package/dist/llm/prompts.d.ts.map +1 -0
  40. package/dist/llm/prompts.js +79 -0
  41. package/dist/llm/prompts.js.map +1 -0
  42. package/dist/parser/call-resolver.d.ts +15 -0
  43. package/dist/parser/call-resolver.d.ts.map +1 -0
  44. package/dist/parser/call-resolver.js +16 -0
  45. package/dist/parser/call-resolver.js.map +1 -0
  46. package/dist/parser/extractor.d.ts +17 -0
  47. package/dist/parser/extractor.d.ts.map +1 -0
  48. package/dist/parser/extractor.js +254 -0
  49. package/dist/parser/extractor.js.map +1 -0
  50. package/dist/parser/index.d.ts +24 -0
  51. package/dist/parser/index.d.ts.map +1 -0
  52. package/dist/parser/index.js +190 -0
  53. package/dist/parser/index.js.map +1 -0
  54. package/dist/parser/languages.d.ts +11 -0
  55. package/dist/parser/languages.d.ts.map +1 -0
  56. package/dist/parser/languages.js +74 -0
  57. package/dist/parser/languages.js.map +1 -0
  58. package/dist/server/index.d.ts +3 -0
  59. package/dist/server/index.d.ts.map +1 -0
  60. package/dist/server/index.js +88 -0
  61. package/dist/server/index.js.map +1 -0
  62. package/dist/server/register-tools.d.ts +7 -0
  63. package/dist/server/register-tools.d.ts.map +1 -0
  64. package/dist/server/register-tools.js +17 -0
  65. package/dist/server/register-tools.js.map +1 -0
  66. package/dist/server/tools/clast-call-graph.d.ts +4 -0
  67. package/dist/server/tools/clast-call-graph.d.ts.map +1 -0
  68. package/dist/server/tools/clast-call-graph.js +70 -0
  69. package/dist/server/tools/clast-call-graph.js.map +1 -0
  70. package/dist/server/tools/clast-comment.d.ts +5 -0
  71. package/dist/server/tools/clast-comment.d.ts.map +1 -0
  72. package/dist/server/tools/clast-comment.js +64 -0
  73. package/dist/server/tools/clast-comment.js.map +1 -0
  74. package/dist/server/tools/clast-file-summary.d.ts +4 -0
  75. package/dist/server/tools/clast-file-summary.d.ts.map +1 -0
  76. package/dist/server/tools/clast-file-summary.js +42 -0
  77. package/dist/server/tools/clast-file-summary.js.map +1 -0
  78. package/dist/server/tools/clast-get-context.d.ts +4 -0
  79. package/dist/server/tools/clast-get-context.d.ts.map +1 -0
  80. package/dist/server/tools/clast-get-context.js +80 -0
  81. package/dist/server/tools/clast-get-context.js.map +1 -0
  82. package/dist/server/tools/clast-reindex.d.ts +5 -0
  83. package/dist/server/tools/clast-reindex.d.ts.map +1 -0
  84. package/dist/server/tools/clast-reindex.js +36 -0
  85. package/dist/server/tools/clast-reindex.js.map +1 -0
  86. package/dist/server/tools/clast-search.d.ts +4 -0
  87. package/dist/server/tools/clast-search.d.ts.map +1 -0
  88. package/dist/server/tools/clast-search.js +29 -0
  89. package/dist/server/tools/clast-search.js.map +1 -0
  90. package/dist/server/tools/clast-status.d.ts +5 -0
  91. package/dist/server/tools/clast-status.d.ts.map +1 -0
  92. package/dist/server/tools/clast-status.js +23 -0
  93. package/dist/server/tools/clast-status.js.map +1 -0
  94. package/dist/types.d.ts +52 -0
  95. package/dist/types.d.ts.map +1 -0
  96. package/dist/types.js +2 -0
  97. package/dist/types.js.map +1 -0
  98. package/dist/watcher/gitignore.d.ts +9 -0
  99. package/dist/watcher/gitignore.d.ts.map +1 -0
  100. package/dist/watcher/gitignore.js +38 -0
  101. package/dist/watcher/gitignore.js.map +1 -0
  102. package/dist/watcher/index.d.ts +23 -0
  103. package/dist/watcher/index.d.ts.map +1 -0
  104. package/dist/watcher/index.js +111 -0
  105. package/dist/watcher/index.js.map +1 -0
  106. package/package.json +65 -0
  107. package/skills/clast-explore/SKILL.md +41 -0
  108. package/src/config/defaults.ts +61 -0
  109. package/src/config/index.ts +55 -0
  110. package/src/db/index.ts +63 -0
  111. package/src/db/queries.ts +332 -0
  112. package/src/db/schema.ts +106 -0
  113. package/src/db/types.ts +47 -0
  114. package/src/llm/comment-generator.ts +131 -0
  115. package/src/llm/index.ts +80 -0
  116. package/src/llm/prompts.ts +95 -0
  117. package/src/parser/call-resolver.ts +17 -0
  118. package/src/parser/extractor.ts +303 -0
  119. package/src/parser/index.ts +226 -0
  120. package/src/parser/languages.ts +86 -0
  121. package/src/server/index.ts +109 -0
  122. package/src/server/register-tools.ts +30 -0
  123. package/src/server/tools/clast-call-graph.ts +82 -0
  124. package/src/server/tools/clast-comment.ts +76 -0
  125. package/src/server/tools/clast-file-summary.ts +59 -0
  126. package/src/server/tools/clast-get-context.ts +97 -0
  127. package/src/server/tools/clast-reindex.ts +52 -0
  128. package/src/server/tools/clast-search.ts +38 -0
  129. package/src/server/tools/clast-status.ts +37 -0
  130. package/src/types.ts +69 -0
  131. package/src/watcher/gitignore.ts +42 -0
  132. package/src/watcher/index.ts +131 -0
  133. package/tsconfig.json +20 -0
@@ -0,0 +1,97 @@
1
+ import { z } from 'zod';
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import type { ClastDatabase } from '../../db/index.js';
4
+
5
+ export function registerGetContextTool(server: McpServer, db: ClastDatabase): void {
6
+ server.tool(
7
+ 'clast_get_context',
8
+ 'Get full context for a symbol: its definition, comments/documentation, callers, callees, and parent class (if method). This is the primary tool for understanding a symbol before editing — use instead of reading the whole file.',
9
+ {
10
+ name: z.string().describe('Symbol name to look up'),
11
+ includeBody: z.boolean().default(false).describe('Include the full function/class body text'),
12
+ },
13
+ async ({ name, includeBody }) => {
14
+ const ctx = db.queries.getNodeWithContext(name);
15
+
16
+ if (ctx.nodes.length === 0) {
17
+ return {
18
+ content: [{
19
+ type: 'text' as const,
20
+ text: JSON.stringify({ error: `No symbol found with name "${name}"` }),
21
+ }],
22
+ };
23
+ }
24
+
25
+ const result = ctx.nodes.map(node => {
26
+ const nodeComments = ctx.comments.filter(c => c.node_id === node.id);
27
+ const entry: Record<string, unknown> = {
28
+ name: node.name,
29
+ type: node.type,
30
+ filePath: node.file_path,
31
+ location: `${node.file_path}:${node.start_line}-${node.end_line}`,
32
+ signature: node.signature,
33
+ language: node.language,
34
+ };
35
+
36
+ if (includeBody) {
37
+ entry.body = node.body_text;
38
+ }
39
+
40
+ // Comments: prioritize original, also show generated
41
+ const originalComment = nodeComments.find(c => c.source === 'original');
42
+ const generatedComment = nodeComments.find(c => c.source === 'generated');
43
+
44
+ if (originalComment) {
45
+ entry.comment = originalComment.text;
46
+ entry.commentSource = 'original';
47
+ }
48
+ if (generatedComment) {
49
+ entry.generatedDescription = generatedComment.text;
50
+ }
51
+
52
+ // Parent (for methods inside classes)
53
+ if (node.parent_id) {
54
+ const parent = db.queries.getNodeById(node.parent_id);
55
+ if (parent) {
56
+ entry.parentClass = {
57
+ name: parent.name,
58
+ type: parent.type,
59
+ filePath: parent.file_path,
60
+ startLine: parent.start_line,
61
+ };
62
+ }
63
+ }
64
+
65
+ return entry;
66
+ });
67
+
68
+ // Callers and callees (deduplicated across all matching nodes)
69
+ const callers = ctx.callers.map(n => ({
70
+ name: n.name,
71
+ type: n.type,
72
+ filePath: n.file_path,
73
+ startLine: n.start_line,
74
+ signature: n.signature,
75
+ }));
76
+
77
+ const callees = ctx.callees.map(n => ({
78
+ name: n.name,
79
+ type: n.type,
80
+ filePath: n.file_path,
81
+ startLine: n.start_line,
82
+ signature: n.signature,
83
+ }));
84
+
85
+ return {
86
+ content: [{
87
+ type: 'text' as const,
88
+ text: JSON.stringify({
89
+ definitions: result,
90
+ callers,
91
+ callees,
92
+ }, null, 2),
93
+ }],
94
+ };
95
+ }
96
+ );
97
+ }
@@ -0,0 +1,52 @@
1
+ import { z } from 'zod';
2
+ import { join } from 'node:path';
3
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+ import type { ClastDatabase } from '../../db/index.js';
5
+ import type { ParserManager } from '../../parser/index.js';
6
+
7
+ export function registerReindexTool(
8
+ server: McpServer,
9
+ db: ClastDatabase,
10
+ parser: ParserManager,
11
+ projectRoot: string
12
+ ): void {
13
+ server.tool(
14
+ 'clast_reindex',
15
+ 'Force re-index a specific file or the entire repository. Use when the index seems stale or after large changes.',
16
+ {
17
+ filePath: z.string().optional().describe('Specific file to reindex (relative path). Omit to reindex the entire repo.'),
18
+ },
19
+ async ({ filePath }) => {
20
+ if (filePath) {
21
+ const absPath = join(projectRoot, filePath);
22
+ const parsed = await parser.incrementalUpdate(absPath, projectRoot, db);
23
+
24
+ return {
25
+ content: [{
26
+ type: 'text' as const,
27
+ text: JSON.stringify({
28
+ file: filePath,
29
+ reindexed: parsed,
30
+ message: parsed ? 'File reindexed successfully' : 'File unchanged or unsupported',
31
+ }),
32
+ }],
33
+ };
34
+ }
35
+
36
+ const result = await parser.fullIndex(projectRoot, db);
37
+
38
+ return {
39
+ content: [{
40
+ type: 'text' as const,
41
+ text: JSON.stringify({
42
+ filesProcessed: result.filesProcessed,
43
+ nodesFound: result.nodesFound,
44
+ edgesResolved: result.edgesResolved,
45
+ durationMs: result.durationMs,
46
+ message: `Full reindex completed in ${result.durationMs}ms`,
47
+ }),
48
+ }],
49
+ };
50
+ }
51
+ );
52
+ }
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import type { ClastDatabase } from '../../db/index.js';
4
+
5
+ export function registerSearchTool(server: McpServer, db: ClastDatabase): void {
6
+ server.tool(
7
+ 'clast_search',
8
+ 'Search AST nodes (functions, classes, methods, etc.) by name pattern and optional type filter. Returns matching symbols with file locations and signatures.',
9
+ {
10
+ query: z.string().describe('Search pattern (matches against symbol names, supports partial matches)'),
11
+ type: z.enum([
12
+ 'function', 'method', 'class', 'interface', 'enum',
13
+ 'import', 'export', 'variable', 'type_alias', 'struct', 'trait', 'module',
14
+ ]).optional().describe('Filter by symbol type'),
15
+ limit: z.number().int().min(1).max(100).default(20).describe('Maximum results to return'),
16
+ },
17
+ async ({ query, type, limit }) => {
18
+ const results = db.queries.searchNodes(query, type, limit);
19
+
20
+ const formatted = results.map(n => ({
21
+ name: n.name,
22
+ type: n.type,
23
+ filePath: n.file_path,
24
+ startLine: n.start_line,
25
+ endLine: n.end_line,
26
+ signature: n.signature,
27
+ language: n.language,
28
+ }));
29
+
30
+ return {
31
+ content: [{
32
+ type: 'text' as const,
33
+ text: JSON.stringify(formatted, null, 2),
34
+ }],
35
+ };
36
+ }
37
+ );
38
+ }
@@ -0,0 +1,37 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { ClastDatabase } from '../../db/index.js';
3
+ import type { FileWatcher } from '../../watcher/index.js';
4
+
5
+ export function registerStatusTool(
6
+ server: McpServer,
7
+ db: ClastDatabase,
8
+ watcher: FileWatcher
9
+ ): void {
10
+ server.tool(
11
+ 'clast_status',
12
+ 'Show the current indexing status: files indexed, total symbols, total call edges, watcher state, and pending updates.',
13
+ {},
14
+ async () => {
15
+ const status = db.queries.getStatus();
16
+
17
+ const result = {
18
+ filesIndexed: status.files_indexed,
19
+ totalNodes: status.total_nodes,
20
+ totalEdges: status.total_edges,
21
+ totalComments: status.total_comments,
22
+ lastIndexed: status.last_indexed
23
+ ? new Date(status.last_indexed).toISOString()
24
+ : null,
25
+ watcherActive: watcher.isActive,
26
+ pendingFiles: watcher.pendingCount,
27
+ };
28
+
29
+ return {
30
+ content: [{
31
+ type: 'text' as const,
32
+ text: JSON.stringify(result, null, 2),
33
+ }],
34
+ };
35
+ }
36
+ );
37
+ }
package/src/types.ts ADDED
@@ -0,0 +1,69 @@
1
+ export type AstNodeType =
2
+ | 'function'
3
+ | 'method'
4
+ | 'class'
5
+ | 'interface'
6
+ | 'enum'
7
+ | 'import'
8
+ | 'export'
9
+ | 'variable'
10
+ | 'type_alias'
11
+ | 'struct'
12
+ | 'trait'
13
+ | 'module';
14
+
15
+ export interface AstNode {
16
+ id?: number;
17
+ filePath: string;
18
+ name: string;
19
+ type: AstNodeType;
20
+ signature: string;
21
+ startLine: number;
22
+ endLine: number;
23
+ startCol: number;
24
+ endCol: number;
25
+ parentId: number | null;
26
+ language: string;
27
+ bodyText: string;
28
+ }
29
+
30
+ export interface CallEdge {
31
+ id?: number;
32
+ callerId: number;
33
+ calleeId: number | null;
34
+ calleeName: string;
35
+ filePath: string;
36
+ line: number;
37
+ }
38
+
39
+ export interface FileInfo {
40
+ filePath: string;
41
+ hash: string;
42
+ language: string;
43
+ lastIndexed: number;
44
+ nodeCount: number;
45
+ }
46
+
47
+ export interface CommentInfo {
48
+ id?: number;
49
+ nodeId: number;
50
+ text: string;
51
+ source: 'original' | 'generated';
52
+ generatedAt: number | null;
53
+ }
54
+
55
+ export interface ParseResult {
56
+ nodes: AstNode[];
57
+ edges: CallEdge[];
58
+ comments: CommentInfo[];
59
+ }
60
+
61
+ export interface IndexStatus {
62
+ filesIndexed: number;
63
+ totalNodes: number;
64
+ totalEdges: number;
65
+ totalComments: number;
66
+ lastIndexed: number | null;
67
+ watcherActive: boolean;
68
+ pendingFiles: number;
69
+ }
@@ -0,0 +1,42 @@
1
+ import { readFileSync, existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+
4
+ /**
5
+ * Parse .gitignore files into glob patterns suitable for chokidar's `ignored` option.
6
+ */
7
+ export function loadGitignorePatterns(projectRoot: string): string[] {
8
+ const patterns: string[] = [];
9
+ const gitignorePath = join(projectRoot, '.gitignore');
10
+
11
+ if (!existsSync(gitignorePath)) return patterns;
12
+
13
+ try {
14
+ const content = readFileSync(gitignorePath, 'utf-8');
15
+ for (const line of content.split('\n')) {
16
+ const trimmed = line.trim();
17
+ // Skip comments and empty lines
18
+ if (!trimmed || trimmed.startsWith('#')) continue;
19
+ // Negation patterns are not supported by chokidar's simple ignored
20
+ if (trimmed.startsWith('!')) continue;
21
+
22
+ patterns.push(trimmed);
23
+ }
24
+ } catch {
25
+ // Silently ignore read errors
26
+ }
27
+
28
+ return patterns;
29
+ }
30
+
31
+ /**
32
+ * Build the full ignored patterns list combining .gitignore and config.
33
+ */
34
+ export function buildIgnorePatterns(
35
+ projectRoot: string,
36
+ configIgnored: string[]
37
+ ): string[] {
38
+ const gitignorePatterns = loadGitignorePatterns(projectRoot);
39
+ // Deduplicate
40
+ const all = new Set([...configIgnored, ...gitignorePatterns]);
41
+ return Array.from(all);
42
+ }
@@ -0,0 +1,131 @@
1
+ import { watch, type FSWatcher } from 'chokidar';
2
+ import { extname } from 'node:path';
3
+ import { EventEmitter } from 'node:events';
4
+ import { getSupportedExtensions } from '../parser/languages.js';
5
+ import { buildIgnorePatterns } from './gitignore.js';
6
+ import type { ParserManager } from '../parser/index.js';
7
+ import type { ClastDatabase } from '../db/index.js';
8
+ import type { ClastConfig } from '../config/index.js';
9
+
10
+ export class FileWatcher extends EventEmitter {
11
+ private watcher: FSWatcher | null = null;
12
+ private projectRoot: string;
13
+ private config: ClastConfig;
14
+ private db: ClastDatabase;
15
+ private parser: ParserManager;
16
+ private debounceTimers = new Map<string, ReturnType<typeof setTimeout>>();
17
+ private _pendingCount = 0;
18
+ private supportedExts: Set<string>;
19
+
20
+ constructor(
21
+ projectRoot: string,
22
+ config: ClastConfig,
23
+ db: ClastDatabase,
24
+ parser: ParserManager
25
+ ) {
26
+ super();
27
+ this.projectRoot = projectRoot;
28
+ this.config = config;
29
+ this.db = db;
30
+ this.parser = parser;
31
+ this.supportedExts = new Set(getSupportedExtensions(config.languages));
32
+ }
33
+
34
+ get isActive(): boolean {
35
+ return this.watcher !== null;
36
+ }
37
+
38
+ get pendingCount(): number {
39
+ return this._pendingCount;
40
+ }
41
+
42
+ start(): void {
43
+ if (this.watcher) return;
44
+ if (!this.config.watch.enabled) return;
45
+
46
+ const ignoredPatterns = buildIgnorePatterns(this.projectRoot, this.config.ignoredPaths);
47
+
48
+ this.watcher = watch(this.projectRoot, {
49
+ ignored: [
50
+ /(^|[/\\])\./,
51
+ ...ignoredPatterns.map(p => {
52
+ if (!p.includes('*') && !p.includes('/')) {
53
+ return `**/${p}/**`;
54
+ }
55
+ return p;
56
+ }),
57
+ ],
58
+ persistent: true,
59
+ ignoreInitial: true,
60
+ });
61
+
62
+ this.watcher.on('add', path => this.handleFileChange(path));
63
+ this.watcher.on('change', path => this.handleFileChange(path));
64
+ this.watcher.on('unlink', path => this.handleFileDelete(path));
65
+ this.watcher.on('error', err => {
66
+ console.error('[clast] Watcher error:', err);
67
+ });
68
+ }
69
+
70
+ stop(): void {
71
+ if (!this.watcher) return;
72
+
73
+ for (const timer of this.debounceTimers.values()) {
74
+ clearTimeout(timer);
75
+ }
76
+ this.debounceTimers.clear();
77
+
78
+ this.watcher.close();
79
+ this.watcher = null;
80
+ }
81
+
82
+ private handleFileChange(filePath: string): void {
83
+ const ext = extname(filePath);
84
+ if (!this.supportedExts.has(ext)) return;
85
+
86
+ const existing = this.debounceTimers.get(filePath);
87
+ if (existing) clearTimeout(existing);
88
+
89
+ this._pendingCount++;
90
+ this.debounceTimers.set(
91
+ filePath,
92
+ setTimeout(() => {
93
+ this.debounceTimers.delete(filePath);
94
+ this._pendingCount--;
95
+ this.processFile(filePath);
96
+ }, this.config.watch.debounceMs)
97
+ );
98
+ }
99
+
100
+ private handleFileDelete(filePath: string): void {
101
+ const ext = extname(filePath);
102
+ if (!this.supportedExts.has(ext)) return;
103
+
104
+ const existing = this.debounceTimers.get(filePath);
105
+ if (existing) {
106
+ clearTimeout(existing);
107
+ this.debounceTimers.delete(filePath);
108
+ this._pendingCount--;
109
+ }
110
+
111
+ try {
112
+ this.parser.removeFile(filePath, this.projectRoot, this.db);
113
+ this.emit('deleted', { filePath });
114
+ } catch (err) {
115
+ this.emit('error', { filePath, error: err as Error });
116
+ }
117
+ }
118
+
119
+ private async processFile(filePath: string): Promise<void> {
120
+ try {
121
+ const parsed = await this.parser.incrementalUpdate(filePath, this.projectRoot, this.db);
122
+ if (parsed) {
123
+ const relPath = filePath.replace(/\\/g, '/');
124
+ const nodes = this.db.queries.getNodesByFile(relPath);
125
+ this.emit('indexed', { filePath, nodesFound: nodes.length });
126
+ }
127
+ } catch (err) {
128
+ this.emit('error', { filePath, error: err as Error });
129
+ }
130
+ }
131
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true
17
+ },
18
+ "include": ["src/**/*.ts"],
19
+ "exclude": ["node_modules", "dist", "test"]
20
+ }