mirror of
https://github.com/safishamsi/graphify.git
synced 2026-08-28 17:26:48 +00:00
Merge PR #708: TypeScript interface/enum/type-alias/const/new_expression extraction
This commit is contained in:
@@ -4,6 +4,7 @@ Full release notes with details on each version: [GitHub Releases](https://githu
|
||||
|
||||
## 0.7.9 (unreleased)
|
||||
|
||||
- Feat: TypeScript extraction parity -- interface, enum, type alias, and module-level const nodes extracted; new_expression emits calls edges; parity with Java/C# class_types
|
||||
- Feat: Quarto (`.qmd`) file support -- routed through existing Markdown extractor; Quarto executable code blocks (` ```{python} `) extracted as code nodes
|
||||
- Feat: optional Google Workspace shortcut export for headless extraction -- `graphify extract ./docs --google-workspace` converts `.gdoc`, `.gsheet`, and `.gslides` files into Markdown sidecars with the `gws` CLI before semantic extraction; account email pseudonymized via SHA256 hash; `[google]` extra adds Sheets table rendering support
|
||||
- Feat: AWS Bedrock backend -- `graphify extract ./docs --backend bedrock`; credentials via standard AWS provider chain (AWS_PROFILE, AWS_REGION, IAM roles, SSO); model via GRAPHIFY_BEDROCK_MODEL (default anthropic.claude-3-5-sonnet-20241022-v2:0); `[bedrock]` extra adds boto3
|
||||
|
||||
+25
-8
@@ -778,16 +778,14 @@ def _require_imports_js(node, source: bytes, file_nid: str, stem: str, edges: li
|
||||
def _js_extra_walk(node, source: bytes, file_nid: str, stem: str, str_path: str,
|
||||
nodes: list, edges: list, seen_ids: set, function_bodies: list,
|
||||
parent_class_nid: str | None, add_node_fn, add_edge_fn) -> bool:
|
||||
"""Handle lexical_declaration (arrow functions, CJS requires) for JS/TS.
|
||||
|
||||
Returns True if handled (caller should not descend further).
|
||||
"""
|
||||
"""Handle lexical_declaration (arrow functions, CJS requires, module-level const literals) for JS/TS. Returns True if handled."""
|
||||
if node.type in ("lexical_declaration", "variable_declaration"):
|
||||
# CJS require imports — emit edges, do not block other lexical_declaration handling
|
||||
require_found = _require_imports_js(node, source, file_nid, stem, edges, str_path)
|
||||
|
||||
# Arrow function declarations (existing behavior, lexical_declaration only)
|
||||
# Arrow function declarations and module-level const literals (lexical_declaration only)
|
||||
arrow_found = False
|
||||
const_found = False
|
||||
if node.type == "lexical_declaration":
|
||||
for child in node.children:
|
||||
if child.type == "variable_declarator":
|
||||
@@ -804,8 +802,22 @@ def _js_extra_walk(node, source: bytes, file_nid: str, stem: str, str_path: str,
|
||||
if body:
|
||||
function_bodies.append((func_nid, body))
|
||||
arrow_found = True
|
||||
elif value and value.type in (
|
||||
"object", "array", "as_expression", "call_expression", "new_expression",
|
||||
):
|
||||
# Module-level const with literal/object/array/factory value
|
||||
name_node = child.child_by_field_name("name")
|
||||
if name_node:
|
||||
const_name = _read_text(name_node, source)
|
||||
line = child.start_point[0] + 1
|
||||
const_nid = _make_id(stem, const_name)
|
||||
add_node_fn(const_nid, const_name, line)
|
||||
add_edge_fn(file_nid, const_nid, "contains", line)
|
||||
const_found = True
|
||||
if arrow_found:
|
||||
return True
|
||||
if const_found:
|
||||
return True
|
||||
if require_found:
|
||||
return True
|
||||
return False
|
||||
@@ -872,7 +884,7 @@ _JS_CONFIG = LanguageConfig(
|
||||
class_types=frozenset({"class_declaration"}),
|
||||
function_types=frozenset({"function_declaration", "method_definition"}),
|
||||
import_types=frozenset({"import_statement"}),
|
||||
call_types=frozenset({"call_expression"}),
|
||||
call_types=frozenset({"call_expression", "new_expression"}),
|
||||
call_function_field="function",
|
||||
call_accessor_node_types=frozenset({"member_expression"}),
|
||||
call_accessor_field="property",
|
||||
@@ -883,10 +895,15 @@ _JS_CONFIG = LanguageConfig(
|
||||
_TS_CONFIG = LanguageConfig(
|
||||
ts_module="tree_sitter_typescript",
|
||||
ts_language_fn="language_typescript",
|
||||
class_types=frozenset({"class_declaration"}),
|
||||
class_types=frozenset({
|
||||
"class_declaration",
|
||||
"interface_declaration", # parity with Java/C#
|
||||
"enum_declaration", # named enums
|
||||
"type_alias_declaration", # named type aliases
|
||||
}),
|
||||
function_types=frozenset({"function_declaration", "method_definition"}),
|
||||
import_types=frozenset({"import_statement"}),
|
||||
call_types=frozenset({"call_expression"}),
|
||||
call_types=frozenset({"call_expression", "new_expression"}),
|
||||
call_function_field="function",
|
||||
call_accessor_node_types=frozenset({"member_expression"}),
|
||||
call_accessor_field="property",
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// Test fixture for upstream PR — exercises every new extraction path.
|
||||
//
|
||||
// Expected nodes after this PR:
|
||||
// - IUserRepository (interface)
|
||||
// - UserStatus (enum) + Active, Inactive (members)
|
||||
// - UserId (type_alias)
|
||||
// - USER_REPOSITORY (const, value=call_expression)
|
||||
// - DEFAULT_ROLES (const, value=array)
|
||||
// - USER_CONFIG (const, value=object)
|
||||
// - UserService (class — already extracted by current code)
|
||||
// - UserModule (class — already extracted)
|
||||
//
|
||||
// Expected edges after this PR:
|
||||
// - UserService.create() --instantiates--> User
|
||||
// - UserService.bulkCreate() --instantiates--> Array
|
||||
// - UserModule --provides--> UserService
|
||||
// - UserModule --provides--> USER_REPOSITORY (via { provide, useClass } detection — optional)
|
||||
// - UserModule --exports--> UserService
|
||||
|
||||
import { Module, Injectable } from '@nestjs/common';
|
||||
import type { User } from './user.entity';
|
||||
|
||||
export interface IUserRepository {
|
||||
findById(id: string): Promise<User | null>;
|
||||
save(user: User): Promise<void>;
|
||||
}
|
||||
|
||||
export enum UserStatus {
|
||||
Active = 'ACTIVE',
|
||||
Inactive = 'INACTIVE',
|
||||
Suspended = 'SUSPENDED',
|
||||
}
|
||||
|
||||
export type UserId = string;
|
||||
|
||||
export const USER_REPOSITORY = Symbol('USER_REPOSITORY');
|
||||
|
||||
export const DEFAULT_ROLES = ['admin', 'editor', 'user'] as const;
|
||||
|
||||
export const USER_CONFIG = {
|
||||
maxRetries: 3,
|
||||
timeoutMs: 5000,
|
||||
features: {
|
||||
twoFactor: true,
|
||||
sso: false,
|
||||
},
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
constructor(private repo: IUserRepository) {}
|
||||
|
||||
create(name: string): User {
|
||||
return new User(name);
|
||||
}
|
||||
|
||||
bulkCreate(names: string[]): User[] {
|
||||
return names.map((n) => new User(n));
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
providers: [
|
||||
UserService,
|
||||
{ provide: USER_REPOSITORY, useClass: PrismaUserRepository },
|
||||
],
|
||||
exports: [UserService],
|
||||
})
|
||||
export class UserModule {}
|
||||
Reference in New Issue
Block a user