@principal-ai/codebase-composition 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.
- package/README.md +67 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/DependencyLayerModule.d.ts +44 -0
- package/dist/modules/DependencyLayerModule.d.ts.map +1 -0
- package/dist/modules/DependencyLayerModule.js +286 -0
- package/dist/modules/DependencyLayerModule.js.map +1 -0
- package/dist/modules/FileSystemModule.d.ts +30 -0
- package/dist/modules/FileSystemModule.d.ts.map +1 -0
- package/dist/modules/FileSystemModule.js +46 -0
- package/dist/modules/FileSystemModule.js.map +1 -0
- package/dist/modules/FileTypeLayerModule.d.ts +34 -0
- package/dist/modules/FileTypeLayerModule.d.ts.map +1 -0
- package/dist/modules/FileTypeLayerModule.js +169 -0
- package/dist/modules/FileTypeLayerModule.js.map +1 -0
- package/dist/modules/FrameworkLayerModule.d.ts +22 -0
- package/dist/modules/FrameworkLayerModule.d.ts.map +1 -0
- package/dist/modules/FrameworkLayerModule.js +388 -0
- package/dist/modules/FrameworkLayerModule.js.map +1 -0
- package/dist/modules/PackageLayerModule.d.ts +23 -0
- package/dist/modules/PackageLayerModule.d.ts.map +1 -0
- package/dist/modules/PackageLayerModule.js +810 -0
- package/dist/modules/PackageLayerModule.js.map +1 -0
- package/dist/modules/TypeExtractionModule.d.ts +37 -0
- package/dist/modules/TypeExtractionModule.d.ts.map +1 -0
- package/dist/modules/TypeExtractionModule.js +180 -0
- package/dist/modules/TypeExtractionModule.js.map +1 -0
- package/dist/modules/VersionControlLayerModule.d.ts +10 -0
- package/dist/modules/VersionControlLayerModule.d.ts.map +1 -0
- package/dist/modules/VersionControlLayerModule.js +32 -0
- package/dist/modules/VersionControlLayerModule.js.map +1 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/index.d.ts +4 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/index.d.ts.map +1 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/index.js +7 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/index.js.map +1 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/models/category.d.ts +15 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/models/category.d.ts.map +1 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/models/category.js +3 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/models/category.js.map +1 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/models/product.d.ts +34 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/models/product.d.ts.map +1 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/models/product.js +23 -0
- package/dist/modules/__fixtures__/typescript-packages/complex-types/src/models/product.js.map +1 -0
- package/dist/modules/__fixtures__/typescript-packages/simple-types/index.d.ts +39 -0
- package/dist/modules/__fixtures__/typescript-packages/simple-types/index.d.ts.map +1 -0
- package/dist/modules/__fixtures__/typescript-packages/simple-types/index.js +39 -0
- package/dist/modules/__fixtures__/typescript-packages/simple-types/index.js.map +1 -0
- package/dist/modules/extractors/TypeScriptExtractor.d.ts +18 -0
- package/dist/modules/extractors/TypeScriptExtractor.d.ts.map +1 -0
- package/dist/modules/extractors/TypeScriptExtractor.js +361 -0
- package/dist/modules/extractors/TypeScriptExtractor.js.map +1 -0
- package/dist/modules/index.d.ts +13 -0
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/modules/index.js +21 -0
- package/dist/modules/index.js.map +1 -0
- package/dist/providers/GitVersionControlProvider.d.ts +108 -0
- package/dist/providers/GitVersionControlProvider.d.ts.map +1 -0
- package/dist/providers/GitVersionControlProvider.js +380 -0
- package/dist/providers/GitVersionControlProvider.js.map +1 -0
- package/dist/providers/PackageManagerApiProvider.d.ts +78 -0
- package/dist/providers/PackageManagerApiProvider.d.ts.map +1 -0
- package/dist/providers/PackageManagerApiProvider.js +14 -0
- package/dist/providers/PackageManagerApiProvider.js.map +1 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +10 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/services/FilesystemService.d.ts +59 -0
- package/dist/services/FilesystemService.d.ts.map +1 -0
- package/dist/services/FilesystemService.js +391 -0
- package/dist/services/FilesystemService.js.map +1 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +7 -0
- package/dist/services/index.js.map +1 -0
- package/dist/types/file-system.d.ts +7 -0
- package/dist/types/file-system.d.ts.map +1 -0
- package/dist/types/file-system.js +7 -0
- package/dist/types/file-system.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/layer-types.d.ts +187 -0
- package/dist/types/layer-types.d.ts.map +1 -0
- package/dist/types/layer-types.js +7 -0
- package/dist/types/layer-types.js.map +1 -0
- package/dist/types/version-control-layer.d.ts +53 -0
- package/dist/types/version-control-layer.d.ts.map +1 -0
- package/dist/types/version-control-layer.js +3 -0
- package/dist/types/version-control-layer.js.map +1 -0
- package/dist/types/workspace-boundaries.d.ts +17 -0
- package/dist/types/workspace-boundaries.d.ts.map +1 -0
- package/dist/types/workspace-boundaries.js +7 -0
- package/dist/types/workspace-boundaries.js.map +1 -0
- package/package.json +42 -0
- package/src/index.ts +62 -0
- package/src/modules/DependencyLayerModule.ts +329 -0
- package/src/modules/FileSystemModule.ts +65 -0
- package/src/modules/FileTypeLayerModule.ts +199 -0
- package/src/modules/FrameworkLayerModule.ts +437 -0
- package/src/modules/PackageLayerModule.ts +979 -0
- package/src/modules/TypeExtractionModule.test.ts +340 -0
- package/src/modules/TypeExtractionModule.ts +180 -0
- package/src/modules/VersionControlLayerModule.ts +31 -0
- package/src/modules/__fixtures__/typescript-packages/complex-types/package.json +6 -0
- package/src/modules/__fixtures__/typescript-packages/complex-types/src/index.ts +6 -0
- package/src/modules/__fixtures__/typescript-packages/complex-types/src/models/category.ts +15 -0
- package/src/modules/__fixtures__/typescript-packages/complex-types/src/models/product.ts +48 -0
- package/src/modules/__fixtures__/typescript-packages/javascript-only/index.js +18 -0
- package/src/modules/__fixtures__/typescript-packages/javascript-only/package.json +5 -0
- package/src/modules/__fixtures__/typescript-packages/simple-types/index.ts +53 -0
- package/src/modules/__fixtures__/typescript-packages/simple-types/package.json +6 -0
- package/src/modules/extractors/README.md +55 -0
- package/src/modules/extractors/TypeScriptExtractor.ts +409 -0
- package/src/modules/index.ts +13 -0
- package/src/providers/GitVersionControlProvider.ts +500 -0
- package/src/providers/PackageManagerApiProvider.ts +108 -0
- package/src/providers/README.md +88 -0
- package/src/providers/index.ts +17 -0
- package/src/services/FilesystemService.ts +530 -0
- package/src/services/index.ts +2 -0
- package/src/types/file-system.ts +11 -0
- package/src/types/index.ts +24 -0
- package/src/types/layer-types.ts +264 -0
- package/src/types/version-control-layer.ts +87 -0
- package/src/types/workspace-boundaries.ts +17 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User interface for testing
|
|
3
|
+
* @description Represents a user in the system
|
|
4
|
+
*/
|
|
5
|
+
export interface User {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
email: string;
|
|
9
|
+
age?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Status type for testing union types
|
|
14
|
+
*/
|
|
15
|
+
export type Status = 'active' | 'inactive' | 'pending';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* UserProfile class for testing class extraction
|
|
19
|
+
*/
|
|
20
|
+
export class UserProfile {
|
|
21
|
+
constructor(
|
|
22
|
+
public user: User,
|
|
23
|
+
public status: Status,
|
|
24
|
+
) {}
|
|
25
|
+
|
|
26
|
+
getDisplayName(): string {
|
|
27
|
+
return this.user.name;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
isActive(): boolean {
|
|
31
|
+
return this.status === 'active';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Action enum for testing enum extraction
|
|
37
|
+
*/
|
|
38
|
+
export enum Action {
|
|
39
|
+
CREATE = 'create',
|
|
40
|
+
UPDATE = 'update',
|
|
41
|
+
DELETE = 'delete',
|
|
42
|
+
READ = 'read',
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Utility function for testing function extraction
|
|
47
|
+
*/
|
|
48
|
+
export function formatUser(user: User): string {
|
|
49
|
+
return `${user.name} <${user.email}>`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Default export
|
|
53
|
+
export default UserProfile;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Type Extractors
|
|
2
|
+
|
|
3
|
+
This directory contains language-specific type extractors that implement the `TypeExtractor` interface.
|
|
4
|
+
|
|
5
|
+
## Current Extractors
|
|
6
|
+
|
|
7
|
+
### TypeScriptExtractor
|
|
8
|
+
|
|
9
|
+
- **Language**: TypeScript/JavaScript
|
|
10
|
+
- **File Extensions**: `.ts`, `.tsx`
|
|
11
|
+
- **Features**:
|
|
12
|
+
- Extracts interfaces, types, classes, enums, functions
|
|
13
|
+
- Supports JSDoc comments
|
|
14
|
+
- Handles default and named exports
|
|
15
|
+
- Generates TypeScript definition files
|
|
16
|
+
|
|
17
|
+
## Adding New Extractors
|
|
18
|
+
|
|
19
|
+
To add support for a new language, implement the `TypeExtractor` interface:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { TypeExtractor, PackageTypes } from '../../types/layer-types';
|
|
23
|
+
|
|
24
|
+
export class PythonExtractor implements TypeExtractor {
|
|
25
|
+
name = 'Python';
|
|
26
|
+
|
|
27
|
+
canHandle(packagePath: string, fileExtensions: string[]): boolean {
|
|
28
|
+
return fileExtensions.includes('.py');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async extractTypes(packagePath: string, options?: any): Promise<PackageTypes> {
|
|
32
|
+
// Use Python AST or tools like mypy to extract type information
|
|
33
|
+
// Return PackageTypes with extracted Python types
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async generateDefinitionFile?(packageTypes: PackageTypes): Promise<string> {
|
|
37
|
+
// Generate .pyi stub files
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Then register it with the TypeExtractionModule:
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
const extractor = new TypeExtractionModule();
|
|
46
|
+
extractor.registerExtractor(new PythonExtractor());
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Architecture Benefits
|
|
50
|
+
|
|
51
|
+
- **Language Agnostic**: Core system works with any language
|
|
52
|
+
- **Extensible**: Easy to add new languages
|
|
53
|
+
- **Consistent API**: All extractors provide the same interface
|
|
54
|
+
- **Registry Pattern**: Dynamic extractor discovery and registration
|
|
55
|
+
- **Future-Proof**: Ready for Go, Java, C#, etc.
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
|
|
4
|
+
import * as ts from 'typescript';
|
|
5
|
+
|
|
6
|
+
import { TypeExtractor, ExtractedType, PackageTypes } from '../../types/layer-types';
|
|
7
|
+
|
|
8
|
+
export interface TypeScriptExtractionOptions {
|
|
9
|
+
includeTests?: boolean;
|
|
10
|
+
includeInternal?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class TypeScriptExtractor implements TypeExtractor {
|
|
14
|
+
name = 'TypeScript';
|
|
15
|
+
|
|
16
|
+
canHandle(packagePath: string, fileExtensions: string[]): boolean {
|
|
17
|
+
// Check if package contains TypeScript files
|
|
18
|
+
return fileExtensions.some(ext => ['.ts', '.tsx'].includes(ext));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async extractTypes(
|
|
22
|
+
packagePath: string,
|
|
23
|
+
options: TypeScriptExtractionOptions = {},
|
|
24
|
+
): Promise<PackageTypes> {
|
|
25
|
+
console.log(`[TypeScriptExtractor] Extracting types from package path: ${packagePath}`);
|
|
26
|
+
|
|
27
|
+
// Verify package path exists
|
|
28
|
+
if (!fs.existsSync(packagePath)) {
|
|
29
|
+
throw new Error(`Package path does not exist: ${packagePath}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Read package.json to get package name
|
|
33
|
+
const packageJsonPath = path.join(packagePath, 'package.json');
|
|
34
|
+
let packageName = path.basename(packagePath);
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
38
|
+
packageName = packageJson.name || packageName;
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.log(`[TypeScriptExtractor] Could not read package.json: ${error}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Find all TypeScript files in the package
|
|
44
|
+
const tsFiles = this.findTypeScriptFiles(packagePath, options);
|
|
45
|
+
|
|
46
|
+
if (tsFiles.length === 0) {
|
|
47
|
+
return {
|
|
48
|
+
packagePath,
|
|
49
|
+
packageName,
|
|
50
|
+
types: [],
|
|
51
|
+
exports: { named: [] },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Create a TypeScript program
|
|
56
|
+
const compilerOptions: ts.CompilerOptions = {
|
|
57
|
+
target: ts.ScriptTarget.ES2020,
|
|
58
|
+
module: ts.ModuleKind.CommonJS,
|
|
59
|
+
lib: ['es2020'],
|
|
60
|
+
declaration: true,
|
|
61
|
+
emitDeclarationOnly: true,
|
|
62
|
+
skipLibCheck: true,
|
|
63
|
+
allowJs: false,
|
|
64
|
+
resolveJsonModule: true,
|
|
65
|
+
esModuleInterop: true,
|
|
66
|
+
strict: true,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const program = ts.createProgram(tsFiles, compilerOptions);
|
|
70
|
+
const checker = program.getTypeChecker();
|
|
71
|
+
const extractedTypes: ExtractedType[] = [];
|
|
72
|
+
const exportedNames = new Set<string>();
|
|
73
|
+
const defaultExport: { value?: string } = {};
|
|
74
|
+
|
|
75
|
+
// Process each source file
|
|
76
|
+
for (const sourceFile of program.getSourceFiles()) {
|
|
77
|
+
if (sourceFile.isDeclarationFile) continue;
|
|
78
|
+
if (!sourceFile.fileName.startsWith(packagePath)) continue;
|
|
79
|
+
|
|
80
|
+
// Visit each node in the source file
|
|
81
|
+
ts.forEachChild(sourceFile, node => {
|
|
82
|
+
this.visitNode(
|
|
83
|
+
node,
|
|
84
|
+
sourceFile,
|
|
85
|
+
checker,
|
|
86
|
+
extractedTypes,
|
|
87
|
+
exportedNames,
|
|
88
|
+
defaultExport,
|
|
89
|
+
packagePath,
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Sort types by kind and name
|
|
95
|
+
extractedTypes.sort((a, b) => {
|
|
96
|
+
const kindOrder = ['interface', 'type', 'class', 'enum', 'function'];
|
|
97
|
+
const aOrder = kindOrder.indexOf(a.kind);
|
|
98
|
+
const bOrder = kindOrder.indexOf(b.kind);
|
|
99
|
+
if (aOrder !== bOrder) return aOrder - bOrder;
|
|
100
|
+
return a.name.localeCompare(b.name);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
packagePath,
|
|
105
|
+
packageName,
|
|
106
|
+
types: extractedTypes,
|
|
107
|
+
exports: {
|
|
108
|
+
named: Array.from(exportedNames),
|
|
109
|
+
default: defaultExport.value,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async generateDefinitionFile(packageTypes: PackageTypes): Promise<string> {
|
|
115
|
+
const lines: string[] = [];
|
|
116
|
+
|
|
117
|
+
// Add header
|
|
118
|
+
lines.push(`// Type definitions for ${packageTypes.packageName}`);
|
|
119
|
+
lines.push(`// Generated from: ${packageTypes.packagePath}`);
|
|
120
|
+
lines.push(`// Generated on: ${new Date().toISOString()}`);
|
|
121
|
+
lines.push('');
|
|
122
|
+
|
|
123
|
+
// Group types by kind
|
|
124
|
+
const typesByKind = packageTypes.types.reduce(
|
|
125
|
+
(acc, type) => {
|
|
126
|
+
if (!acc[type.kind]) acc[type.kind] = [];
|
|
127
|
+
acc[type.kind].push(type);
|
|
128
|
+
return acc;
|
|
129
|
+
},
|
|
130
|
+
{} as Record<string, ExtractedType[]>,
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
// Add types in order
|
|
134
|
+
const kinds = ['interface', 'type', 'class', 'enum', 'function'] as const;
|
|
135
|
+
for (const kind of kinds) {
|
|
136
|
+
const types = typesByKind[kind];
|
|
137
|
+
if (!types || types.length === 0) continue;
|
|
138
|
+
|
|
139
|
+
lines.push(`// ${kind.charAt(0).toUpperCase() + kind.slice(1)}s`);
|
|
140
|
+
lines.push('');
|
|
141
|
+
|
|
142
|
+
for (const type of types) {
|
|
143
|
+
if (type.jsDoc) {
|
|
144
|
+
lines.push(`/** ${type.jsDoc} */`);
|
|
145
|
+
}
|
|
146
|
+
if (type.isExported) {
|
|
147
|
+
// Remove existing 'export' keyword if present to avoid duplication
|
|
148
|
+
const cleanText = type.text.replace(/^export\s+/, '');
|
|
149
|
+
lines.push(`export ${cleanText}`);
|
|
150
|
+
} else {
|
|
151
|
+
lines.push(type.text);
|
|
152
|
+
}
|
|
153
|
+
lines.push('');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return lines.join('\n');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private findTypeScriptFiles(dir: string, options: TypeScriptExtractionOptions = {}): string[] {
|
|
161
|
+
const files: string[] = [];
|
|
162
|
+
|
|
163
|
+
const walk = (currentDir: string) => {
|
|
164
|
+
try {
|
|
165
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
166
|
+
|
|
167
|
+
for (const entry of entries) {
|
|
168
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
169
|
+
|
|
170
|
+
if (entry.isDirectory()) {
|
|
171
|
+
// Skip node_modules and hidden directories
|
|
172
|
+
if (entry.name !== 'node_modules' && !entry.name.startsWith('.')) {
|
|
173
|
+
walk(fullPath);
|
|
174
|
+
}
|
|
175
|
+
} else if (entry.isFile()) {
|
|
176
|
+
if (entry.name.endsWith('.ts') || entry.name.endsWith('.tsx')) {
|
|
177
|
+
// Skip declaration files
|
|
178
|
+
if (entry.name.endsWith('.d.ts')) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Skip test files unless explicitly included
|
|
183
|
+
if (!options.includeTests) {
|
|
184
|
+
if (entry.name.includes('.test.') || entry.name.includes('.spec.')) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
files.push(fullPath);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
} catch (error) {
|
|
194
|
+
console.error(`[TypeScriptExtractor] Error reading directory ${currentDir}:`, error);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
walk(dir);
|
|
199
|
+
return files;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private visitNode(
|
|
203
|
+
node: ts.Node,
|
|
204
|
+
sourceFile: ts.SourceFile,
|
|
205
|
+
checker: ts.TypeChecker,
|
|
206
|
+
extractedTypes: ExtractedType[],
|
|
207
|
+
exportedNames: Set<string>,
|
|
208
|
+
defaultExport: { value?: string },
|
|
209
|
+
packagePath: string,
|
|
210
|
+
) {
|
|
211
|
+
const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined;
|
|
212
|
+
const isExported = modifiers?.some(m => m.kind === ts.SyntaxKind.ExportKeyword) || false;
|
|
213
|
+
const isDefaultExport = modifiers?.some(m => m.kind === ts.SyntaxKind.DefaultKeyword) || false;
|
|
214
|
+
|
|
215
|
+
// Extract JSDoc comments
|
|
216
|
+
const jsDoc = this.getJSDocComment(node, sourceFile);
|
|
217
|
+
|
|
218
|
+
// Get relative file path from package root
|
|
219
|
+
const getRelativeFileName = (): string => {
|
|
220
|
+
const relativePath = path.relative(packagePath, sourceFile.fileName);
|
|
221
|
+
return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
if (ts.isInterfaceDeclaration(node)) {
|
|
225
|
+
const name = node.name?.text || 'Anonymous';
|
|
226
|
+
const text = this.getNodeText(node, sourceFile);
|
|
227
|
+
|
|
228
|
+
// Only extract exported types
|
|
229
|
+
if (isExported) {
|
|
230
|
+
extractedTypes.push({
|
|
231
|
+
name,
|
|
232
|
+
kind: 'interface',
|
|
233
|
+
text,
|
|
234
|
+
fileName: getRelativeFileName(),
|
|
235
|
+
isExported,
|
|
236
|
+
jsDoc,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
exportedNames.add(name);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (isDefaultExport) {
|
|
243
|
+
defaultExport.value = name;
|
|
244
|
+
}
|
|
245
|
+
} else if (ts.isTypeAliasDeclaration(node)) {
|
|
246
|
+
const name = node.name?.text || 'Anonymous';
|
|
247
|
+
const text = this.getNodeText(node, sourceFile);
|
|
248
|
+
|
|
249
|
+
if (isExported) {
|
|
250
|
+
extractedTypes.push({
|
|
251
|
+
name,
|
|
252
|
+
kind: 'type',
|
|
253
|
+
text,
|
|
254
|
+
fileName: getRelativeFileName(),
|
|
255
|
+
isExported,
|
|
256
|
+
jsDoc,
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
exportedNames.add(name);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (isDefaultExport) {
|
|
263
|
+
defaultExport.value = name;
|
|
264
|
+
}
|
|
265
|
+
} else if (ts.isClassDeclaration(node)) {
|
|
266
|
+
const name = node.name?.text || 'Anonymous';
|
|
267
|
+
const text = this.getClassSignature(node, sourceFile, checker);
|
|
268
|
+
|
|
269
|
+
if (isExported) {
|
|
270
|
+
extractedTypes.push({
|
|
271
|
+
name,
|
|
272
|
+
kind: 'class',
|
|
273
|
+
text,
|
|
274
|
+
fileName: getRelativeFileName(),
|
|
275
|
+
isExported,
|
|
276
|
+
jsDoc,
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
exportedNames.add(name);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (isDefaultExport) {
|
|
283
|
+
defaultExport.value = name;
|
|
284
|
+
}
|
|
285
|
+
} else if (ts.isEnumDeclaration(node)) {
|
|
286
|
+
const name = node.name?.text || 'Anonymous';
|
|
287
|
+
const text = this.getNodeText(node, sourceFile);
|
|
288
|
+
|
|
289
|
+
if (isExported) {
|
|
290
|
+
extractedTypes.push({
|
|
291
|
+
name,
|
|
292
|
+
kind: 'enum',
|
|
293
|
+
text,
|
|
294
|
+
fileName: getRelativeFileName(),
|
|
295
|
+
isExported,
|
|
296
|
+
jsDoc,
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
exportedNames.add(name);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (isDefaultExport) {
|
|
303
|
+
defaultExport.value = name;
|
|
304
|
+
}
|
|
305
|
+
} else if (ts.isFunctionDeclaration(node) && node.name) {
|
|
306
|
+
const name = node.name.text;
|
|
307
|
+
const text = this.getFunctionSignature(node, sourceFile, checker);
|
|
308
|
+
|
|
309
|
+
if (isExported) {
|
|
310
|
+
extractedTypes.push({
|
|
311
|
+
name,
|
|
312
|
+
kind: 'function',
|
|
313
|
+
text,
|
|
314
|
+
fileName: getRelativeFileName(),
|
|
315
|
+
isExported,
|
|
316
|
+
jsDoc,
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
exportedNames.add(name);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (isDefaultExport) {
|
|
323
|
+
defaultExport.value = name;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Handle export default statements separately
|
|
328
|
+
if (ts.isExportAssignment(node) && !node.isExportEquals) {
|
|
329
|
+
// This is an "export default" statement
|
|
330
|
+
if (ts.isIdentifier(node.expression)) {
|
|
331
|
+
defaultExport.value = node.expression.text;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Continue visiting child nodes
|
|
336
|
+
ts.forEachChild(node, child => {
|
|
337
|
+
this.visitNode(
|
|
338
|
+
child,
|
|
339
|
+
sourceFile,
|
|
340
|
+
checker,
|
|
341
|
+
extractedTypes,
|
|
342
|
+
exportedNames,
|
|
343
|
+
defaultExport,
|
|
344
|
+
packagePath,
|
|
345
|
+
);
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
private getNodeText(node: ts.Node, sourceFile: ts.SourceFile): string {
|
|
350
|
+
return node.getText(sourceFile);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
private getJSDocComment(node: ts.Node, _sourceFile: ts.SourceFile): string | undefined {
|
|
354
|
+
// Get the full JSDoc comments including the main comment and tags
|
|
355
|
+
const jsDocComments = ts.getJSDocCommentsAndTags(node);
|
|
356
|
+
if (jsDocComments.length === 0) return undefined;
|
|
357
|
+
|
|
358
|
+
const comments: string[] = [];
|
|
359
|
+
|
|
360
|
+
jsDocComments.forEach(comment => {
|
|
361
|
+
if (ts.isJSDoc(comment)) {
|
|
362
|
+
// Get the main comment text
|
|
363
|
+
if (comment.comment) {
|
|
364
|
+
if (typeof comment.comment === 'string') {
|
|
365
|
+
comments.push(comment.comment);
|
|
366
|
+
} else if (Array.isArray(comment.comment)) {
|
|
367
|
+
comments.push(comment.comment.map(c => c.text).join(''));
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Get text from tags (like @description)
|
|
372
|
+
comment.tags?.forEach(tag => {
|
|
373
|
+
if (tag.comment) {
|
|
374
|
+
if (typeof tag.comment === 'string') {
|
|
375
|
+
comments.push(tag.comment);
|
|
376
|
+
} else if (Array.isArray(tag.comment)) {
|
|
377
|
+
comments.push(tag.comment.map(c => c.text).join(''));
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
return comments.length > 0 ? comments.join('\n') : undefined;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
private getClassSignature(
|
|
388
|
+
node: ts.ClassDeclaration,
|
|
389
|
+
sourceFile: ts.SourceFile,
|
|
390
|
+
_checker: ts.TypeChecker,
|
|
391
|
+
): string {
|
|
392
|
+
// For now, return the full class declaration
|
|
393
|
+
// In the future, we could extract just the public API
|
|
394
|
+
return this.getNodeText(node, sourceFile);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
private getFunctionSignature(
|
|
398
|
+
node: ts.FunctionDeclaration,
|
|
399
|
+
sourceFile: ts.SourceFile,
|
|
400
|
+
_checker: ts.TypeChecker,
|
|
401
|
+
): string {
|
|
402
|
+
// Get just the function signature without the body
|
|
403
|
+
const signature = node.name?.text || 'anonymous';
|
|
404
|
+
const params = node.parameters.map(p => p.getText(sourceFile)).join(', ');
|
|
405
|
+
const returnType = node.type ? `: ${node.type.getText(sourceFile)}` : '';
|
|
406
|
+
|
|
407
|
+
return `function ${signature}(${params})${returnType}`;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Export layer modules
|
|
2
|
+
export { FileTypeLayerModule } from './FileTypeLayerModule';
|
|
3
|
+
export type { FileTypeInfo } from './FileTypeLayerModule';
|
|
4
|
+
export { PackageLayerModule } from './PackageLayerModule';
|
|
5
|
+
export { VersionControlLayerFactory } from './VersionControlLayerModule';
|
|
6
|
+
export { DependencyLayerModule } from './DependencyLayerModule';
|
|
7
|
+
export { FrameworkLayerModule } from './FrameworkLayerModule';
|
|
8
|
+
export { FileSystemModule } from './FileSystemModule';
|
|
9
|
+
export type { FileSystemModuleConfig, FileSystemLoadResult } from './FileSystemModule';
|
|
10
|
+
export { TypeExtractionModule } from './TypeExtractionModule';
|
|
11
|
+
export type { TypeExtractionOptions } from './TypeExtractionModule';
|
|
12
|
+
export { TypeScriptExtractor } from './extractors/TypeScriptExtractor';
|
|
13
|
+
export type { TypeScriptExtractionOptions } from './extractors/TypeScriptExtractor';
|