This is page 7 of 18. Use http://codebase.md/shashankss1205/codegraphcontext?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .github
│ └── workflows
│ ├── e2e-tests.yml
│ ├── post_discord_invite.yml
│ ├── test.yml
│ └── update-contributors.yml
├── .gitignore
├── CONTRIBUTING.md
├── contributors.md
├── docs
│ ├── docs
│ │ ├── architecture.md
│ │ ├── cli.md
│ │ ├── contributing_languages.md
│ │ ├── contributing.md
│ │ ├── cookbook.md
│ │ ├── core.md
│ │ ├── future_work.md
│ │ ├── images
│ │ │ ├── 1.png
│ │ │ ├── 11.png
│ │ │ ├── 12.png
│ │ │ ├── 13.png
│ │ │ ├── 14.png
│ │ │ ├── 16.png
│ │ │ ├── 19.png
│ │ │ ├── 2.png
│ │ │ ├── 20.png
│ │ │ ├── 21.png
│ │ │ ├── 22.png
│ │ │ ├── 23.png
│ │ │ ├── 24.png
│ │ │ ├── 26.png
│ │ │ ├── 28.png
│ │ │ ├── 29.png
│ │ │ ├── 3.png
│ │ │ ├── 30.png
│ │ │ ├── 31.png
│ │ │ ├── 32.png
│ │ │ ├── 33.png
│ │ │ ├── 34.png
│ │ │ ├── 35.png
│ │ │ ├── 36.png
│ │ │ ├── 38.png
│ │ │ ├── 39.png
│ │ │ ├── 4.png
│ │ │ ├── 40.png
│ │ │ ├── 41.png
│ │ │ ├── 42.png
│ │ │ ├── 43.png
│ │ │ ├── 44.png
│ │ │ ├── 5.png
│ │ │ ├── 6.png
│ │ │ ├── 7.png
│ │ │ ├── 8.png
│ │ │ ├── 9.png
│ │ │ ├── Indexing.gif
│ │ │ ├── tool_images
│ │ │ │ ├── 1.png
│ │ │ │ ├── 2.png
│ │ │ │ └── 3.png
│ │ │ └── Usecase.gif
│ │ ├── index.md
│ │ ├── installation.md
│ │ ├── license.md
│ │ ├── server.md
│ │ ├── tools.md
│ │ ├── troubleshooting.md
│ │ └── use_cases.md
│ ├── mkdocs.yml
│ └── site
│ ├── 404.html
│ ├── architecture
│ │ └── index.html
│ ├── assets
│ │ ├── images
│ │ │ └── favicon.png
│ │ ├── javascripts
│ │ │ ├── bundle.f55a23d4.min.js
│ │ │ ├── bundle.f55a23d4.min.js.map
│ │ │ ├── lunr
│ │ │ │ ├── min
│ │ │ │ │ ├── lunr.ar.min.js
│ │ │ │ │ ├── lunr.da.min.js
│ │ │ │ │ ├── lunr.de.min.js
│ │ │ │ │ ├── lunr.du.min.js
│ │ │ │ │ ├── lunr.el.min.js
│ │ │ │ │ ├── lunr.es.min.js
│ │ │ │ │ ├── lunr.fi.min.js
│ │ │ │ │ ├── lunr.fr.min.js
│ │ │ │ │ ├── lunr.he.min.js
│ │ │ │ │ ├── lunr.hi.min.js
│ │ │ │ │ ├── lunr.hu.min.js
│ │ │ │ │ ├── lunr.hy.min.js
│ │ │ │ │ ├── lunr.it.min.js
│ │ │ │ │ ├── lunr.ja.min.js
│ │ │ │ │ ├── lunr.jp.min.js
│ │ │ │ │ ├── lunr.kn.min.js
│ │ │ │ │ ├── lunr.ko.min.js
│ │ │ │ │ ├── lunr.multi.min.js
│ │ │ │ │ ├── lunr.nl.min.js
│ │ │ │ │ ├── lunr.no.min.js
│ │ │ │ │ ├── lunr.pt.min.js
│ │ │ │ │ ├── lunr.ro.min.js
│ │ │ │ │ ├── lunr.ru.min.js
│ │ │ │ │ ├── lunr.sa.min.js
│ │ │ │ │ ├── lunr.stemmer.support.min.js
│ │ │ │ │ ├── lunr.sv.min.js
│ │ │ │ │ ├── lunr.ta.min.js
│ │ │ │ │ ├── lunr.te.min.js
│ │ │ │ │ ├── lunr.th.min.js
│ │ │ │ │ ├── lunr.tr.min.js
│ │ │ │ │ ├── lunr.vi.min.js
│ │ │ │ │ └── lunr.zh.min.js
│ │ │ │ ├── tinyseg.js
│ │ │ │ └── wordcut.js
│ │ │ └── workers
│ │ │ ├── search.973d3a69.min.js
│ │ │ └── search.973d3a69.min.js.map
│ │ └── stylesheets
│ │ ├── main.2a3383ac.min.css
│ │ ├── main.2a3383ac.min.css.map
│ │ ├── palette.06af60db.min.css
│ │ └── palette.06af60db.min.css.map
│ ├── cli
│ │ └── index.html
│ ├── contributing
│ │ └── index.html
│ ├── contributing_languages
│ │ └── index.html
│ ├── cookbook
│ │ └── index.html
│ ├── core
│ │ └── index.html
│ ├── future_work
│ │ └── index.html
│ ├── images
│ │ ├── 1.png
│ │ ├── 11.png
│ │ ├── 12.png
│ │ ├── 13.png
│ │ ├── 14.png
│ │ ├── 16.png
│ │ ├── 19.png
│ │ ├── 2.png
│ │ ├── 20.png
│ │ ├── 21.png
│ │ ├── 22.png
│ │ ├── 23.png
│ │ ├── 24.png
│ │ ├── 26.png
│ │ ├── 28.png
│ │ ├── 29.png
│ │ ├── 3.png
│ │ ├── 30.png
│ │ ├── 31.png
│ │ ├── 32.png
│ │ ├── 33.png
│ │ ├── 34.png
│ │ ├── 35.png
│ │ ├── 36.png
│ │ ├── 38.png
│ │ ├── 39.png
│ │ ├── 4.png
│ │ ├── 40.png
│ │ ├── 41.png
│ │ ├── 42.png
│ │ ├── 43.png
│ │ ├── 44.png
│ │ ├── 5.png
│ │ ├── 6.png
│ │ ├── 7.png
│ │ ├── 8.png
│ │ ├── 9.png
│ │ ├── Indexing.gif
│ │ ├── tool_images
│ │ │ ├── 1.png
│ │ │ ├── 2.png
│ │ │ └── 3.png
│ │ └── Usecase.gif
│ ├── index.html
│ ├── installation
│ │ └── index.html
│ ├── license
│ │ └── index.html
│ ├── search
│ │ └── search_index.json
│ ├── server
│ │ └── index.html
│ ├── sitemap.xml
│ ├── sitemap.xml.gz
│ ├── tools
│ │ └── index.html
│ ├── troubleshooting
│ │ └── index.html
│ └── use_cases
│ └── index.html
├── images
│ ├── 1.png
│ ├── 11.png
│ ├── 12.png
│ ├── 13.png
│ ├── 14.png
│ ├── 16.png
│ ├── 19.png
│ ├── 2.png
│ ├── 20.png
│ ├── 21.png
│ ├── 22.png
│ ├── 23.png
│ ├── 24.png
│ ├── 26.png
│ ├── 28.png
│ ├── 29.png
│ ├── 3.png
│ ├── 30.png
│ ├── 31.png
│ ├── 32.png
│ ├── 33.png
│ ├── 34.png
│ ├── 35.png
│ ├── 36.png
│ ├── 38.png
│ ├── 39.png
│ ├── 4.png
│ ├── 40.png
│ ├── 41.png
│ ├── 42.png
│ ├── 43.png
│ ├── 44.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── 8.png
│ ├── 9.png
│ ├── Indexing.gif
│ ├── tool_images
│ │ ├── 1.png
│ │ ├── 2.png
│ │ └── 3.png
│ └── Usecase.gif
├── LICENSE
├── MANIFEST.in
├── organizer
│ ├── CONTRIBUTING_LANGUAGES.md
│ ├── cookbook.md
│ ├── docs.md
│ ├── language_specific_nodes.md
│ ├── Tools_Exploration.md
│ └── troubleshoot.md
├── package-lock.json
├── pyproject.toml
├── README.md
├── scripts
│ ├── generate_lang_contributors.py
│ └── post_install_fix.sh
├── SECURITY.md
├── src
│ └── codegraphcontext
│ ├── __init__.py
│ ├── __main__.py
│ ├── cli
│ │ ├── __init__.py
│ │ ├── cli_helpers.py
│ │ ├── main.py
│ │ ├── setup_macos.py
│ │ └── setup_wizard.py
│ ├── core
│ │ ├── __init__.py
│ │ ├── database.py
│ │ ├── jobs.py
│ │ └── watcher.py
│ ├── prompts.py
│ ├── server.py
│ ├── tools
│ │ ├── __init__.py
│ │ ├── advanced_language_query_tool.py
│ │ ├── code_finder.py
│ │ ├── graph_builder.py
│ │ ├── languages
│ │ │ ├── c.py
│ │ │ ├── cpp.py
│ │ │ ├── go.py
│ │ │ ├── java.py
│ │ │ ├── javascript.py
│ │ │ ├── python.py
│ │ │ ├── ruby.py
│ │ │ ├── rust.py
│ │ │ └── typescript.py
│ │ ├── package_resolver.py
│ │ ├── query_tool_languages
│ │ │ ├── c_toolkit.py
│ │ │ ├── cpp_toolkit.py
│ │ │ ├── go_toolkit.py
│ │ │ ├── java_toolkit.py
│ │ │ ├── javascript_toolkit.py
│ │ │ ├── python_toolkit.py
│ │ │ ├── ruby_toolkit.py
│ │ │ ├── rust_toolkit.py
│ │ │ └── typescript_toolkit.py
│ │ └── system.py
│ └── utils
│ └── debug_log.py
├── tests
│ ├── __init__.py
│ ├── conftest.py
│ ├── sample_project
│ │ ├── advanced_calls.py
│ │ ├── advanced_classes.py
│ │ ├── advanced_classes2.py
│ │ ├── advanced_functions.py
│ │ ├── advanced_imports.py
│ │ ├── async_features.py
│ │ ├── callbacks_decorators.py
│ │ ├── circular1.py
│ │ ├── circular2.py
│ │ ├── class_instantiation.py
│ │ ├── cli_and_dunder.py
│ │ ├── complex_classes.py
│ │ ├── comprehensions_generators.py
│ │ ├── context_managers.py
│ │ ├── control_flow.py
│ │ ├── datatypes.py
│ │ ├── dynamic_dispatch.py
│ │ ├── dynamic_imports.py
│ │ ├── edge_cases
│ │ │ ├── comments_only.py
│ │ │ ├── docstring_only.py
│ │ │ ├── empty.py
│ │ │ ├── hardcoded_secrets.py
│ │ │ ├── long_functions.py
│ │ │ └── syntax_error.py
│ │ ├── function_chains.py
│ │ ├── generators.py
│ │ ├── import_reexports.py
│ │ ├── mapping_calls.py
│ │ ├── module_a.py
│ │ ├── module_b.py
│ │ ├── module_c
│ │ │ ├── __init__.py
│ │ │ ├── submodule1.py
│ │ │ └── submodule2.py
│ │ ├── namespace_pkg
│ │ │ └── ns_module.py
│ │ ├── pattern_matching.py
│ │ └── typing_examples.py
│ ├── sample_project_c
│ │ ├── cgc_sample
│ │ ├── include
│ │ │ ├── config.h
│ │ │ ├── math
│ │ │ │ └── vec.h
│ │ │ ├── module.h
│ │ │ ├── platform.h
│ │ │ └── util.h
│ │ ├── Makefile
│ │ ├── README.md
│ │ └── src
│ │ ├── main.c
│ │ ├── math
│ │ │ └── vec.c
│ │ ├── module.c
│ │ └── util.c
│ ├── sample_project_cpp
│ │ ├── class_features.cpp
│ │ ├── classes.cpp
│ │ ├── control_flow.cpp
│ │ ├── edge_cases.cpp
│ │ ├── enum_struct_union.cpp
│ │ ├── exceptions.cpp
│ │ ├── file_io.cpp
│ │ ├── function_chain.cpp
│ │ ├── function_chain.h
│ │ ├── function_types.cpp
│ │ ├── main.cpp
│ │ ├── main.exe
│ │ ├── namespaces.cpp
│ │ ├── raii_example.cpp
│ │ ├── README.md
│ │ ├── sample_project.exe
│ │ ├── stl_usage.cpp
│ │ ├── templates.cpp
│ │ └── types_variable_assignments.cpp
│ ├── sample_project_go
│ │ ├── advanced_types.go
│ │ ├── basic_functions.go
│ │ ├── embedded_composition.go
│ │ ├── error_handling.go
│ │ ├── generics.go
│ │ ├── go.mod
│ │ ├── goroutines_channels.go
│ │ ├── interfaces.go
│ │ ├── packages_imports.go
│ │ ├── README.md
│ │ ├── structs_methods.go
│ │ └── util
│ │ └── helpers.go
│ ├── sample_project_java
│ │ ├── out
│ │ │ └── com
│ │ │ └── example
│ │ │ └── app
│ │ │ ├── annotations
│ │ │ │ └── Logged.class
│ │ │ ├── Main.class
│ │ │ ├── misc
│ │ │ │ ├── Outer.class
│ │ │ │ └── Outer$Inner.class
│ │ │ ├── model
│ │ │ │ ├── Role.class
│ │ │ │ └── User.class
│ │ │ ├── service
│ │ │ │ ├── AbstractGreeter.class
│ │ │ │ ├── GreetingService.class
│ │ │ │ └── impl
│ │ │ │ └── GreetingServiceImpl.class
│ │ │ └── util
│ │ │ ├── CollectionUtils.class
│ │ │ └── IOHelper.class
│ │ ├── README.md
│ │ ├── sources.txt
│ │ └── src
│ │ └── com
│ │ └── example
│ │ └── app
│ │ ├── annotations
│ │ │ └── Logged.java
│ │ ├── Main.java
│ │ ├── misc
│ │ │ └── Outer.java
│ │ ├── model
│ │ │ ├── Role.java
│ │ │ └── User.java
│ │ ├── service
│ │ │ ├── AbstractGreeter.java
│ │ │ ├── GreetingService.java
│ │ │ └── impl
│ │ │ └── GreetingServiceImpl.java
│ │ └── util
│ │ ├── CollectionUtils.java
│ │ └── IOHelper.java
│ ├── sample_project_javascript
│ │ ├── arrays.js
│ │ ├── asyncAwait.js
│ │ ├── classes.js
│ │ ├── dom.js
│ │ ├── errorHandling.js
│ │ ├── events.js
│ │ ├── exporter.js
│ │ ├── fetchAPI.js
│ │ ├── fixtures
│ │ │ └── js
│ │ │ └── accessors.js
│ │ ├── functions.js
│ │ ├── importer.js
│ │ ├── objects.js
│ │ ├── promises.js
│ │ ├── README.md
│ │ └── variables.js
│ ├── sample_project_misc
│ │ ├── index.html
│ │ ├── README.md
│ │ ├── styles.css
│ │ ├── tables.css
│ │ └── tables.html
│ ├── sample_project_php
│ │ ├── classes_objects.php
│ │ ├── database.php
│ │ ├── edgecases.php
│ │ ├── error_handling.php
│ │ ├── file_handling.php
│ │ ├── functions.php
│ │ ├── generators_iterators.php
│ │ ├── globals_superglobals.php
│ │ ├── Inheritance.php
│ │ ├── interface_traits.php
│ │ └── README.md
│ ├── sample_project_ruby
│ │ ├── class_example.rb
│ │ ├── enumerables.rb
│ │ ├── error_handling.rb
│ │ ├── file_io.rb
│ │ ├── inheritance_example.rb
│ │ ├── main.rb
│ │ ├── metaprogramming.rb
│ │ ├── mixins_example.rb
│ │ ├── module_example.rb
│ │ └── tests
│ │ ├── test_mixins.py
│ │ └── test_sample.rb
│ ├── sample_project_rust
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ └── src
│ │ ├── basic_functions.rs
│ │ ├── concurrency.rs
│ │ ├── error_handling.rs
│ │ ├── generics.rs
│ │ ├── iterators_closures.rs
│ │ ├── lib.rs
│ │ ├── lifetimes_references.rs
│ │ ├── modules.rs
│ │ ├── smart_pointers.rs
│ │ ├── structs_enums.rs
│ │ └── traits.rs
│ ├── sample_project_typescript
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── src
│ │ │ ├── advanced-types.ts
│ │ │ ├── async-promises.ts
│ │ │ ├── classes-inheritance.ts
│ │ │ ├── decorators-metadata.ts
│ │ │ ├── error-validation.ts
│ │ │ ├── functions-generics.ts
│ │ │ ├── index.ts
│ │ │ ├── modules-namespaces.ts
│ │ │ ├── types-interfaces.ts
│ │ │ └── utilities-helpers.ts
│ │ └── tsconfig.json
│ ├── test_cpp_parser.py
│ ├── test_database_validation.py
│ ├── test_end_to_end.py
│ ├── test_graph_indexing_js.py
│ ├── test_graph_indexing.py
│ ├── test_tree_sitter
│ │ ├── __init__.py
│ │ ├── class_instantiation.py
│ │ ├── complex_classes.py
│ │ └── test_file.py
│ └── test_typescript_parser.py
└── website
├── .example.env
├── .gitignore
├── api
│ └── pypi.ts
├── bun.lockb
├── components.json
├── eslint.config.js
├── index.html
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│ ├── favicon.ico
│ ├── placeholder.svg
│ └── robots.txt
├── README.md
├── src
│ ├── App.css
│ ├── App.tsx
│ ├── assets
│ │ ├── function-calls.png
│ │ ├── graph-total.png
│ │ ├── hero-graph.jpg
│ │ └── hierarchy.png
│ ├── components
│ │ ├── ComparisonTable.tsx
│ │ ├── CookbookSection.tsx
│ │ ├── DemoSection.tsx
│ │ ├── ExamplesSection.tsx
│ │ ├── FeaturesSection.tsx
│ │ ├── Footer.tsx
│ │ ├── HeroSection.tsx
│ │ ├── InstallationSection.tsx
│ │ ├── MoveToTop.tsx
│ │ ├── ShowDownloads.tsx
│ │ ├── ShowStarGraph.tsx
│ │ ├── TestimonialSection.tsx
│ │ ├── ThemeProvider.tsx
│ │ ├── ThemeToggle.tsx
│ │ └── ui
│ │ ├── accordion.tsx
│ │ ├── alert-dialog.tsx
│ │ ├── alert.tsx
│ │ ├── aspect-ratio.tsx
│ │ ├── avatar.tsx
│ │ ├── badge.tsx
│ │ ├── breadcrumb.tsx
│ │ ├── button.tsx
│ │ ├── calendar.tsx
│ │ ├── card.tsx
│ │ ├── carousel.tsx
│ │ ├── chart.tsx
│ │ ├── checkbox.tsx
│ │ ├── collapsible.tsx
│ │ ├── command.tsx
│ │ ├── context-menu.tsx
│ │ ├── dialog.tsx
│ │ ├── drawer.tsx
│ │ ├── dropdown-menu.tsx
│ │ ├── form.tsx
│ │ ├── hover-card.tsx
│ │ ├── input-otp.tsx
│ │ ├── input.tsx
│ │ ├── label.tsx
│ │ ├── menubar.tsx
│ │ ├── navigation-menu.tsx
│ │ ├── orbiting-circles.tsx
│ │ ├── pagination.tsx
│ │ ├── popover.tsx
│ │ ├── progress.tsx
│ │ ├── radio-group.tsx
│ │ ├── resizable.tsx
│ │ ├── scroll-area.tsx
│ │ ├── select.tsx
│ │ ├── separator.tsx
│ │ ├── sheet.tsx
│ │ ├── sidebar.tsx
│ │ ├── skeleton.tsx
│ │ ├── slider.tsx
│ │ ├── sonner.tsx
│ │ ├── switch.tsx
│ │ ├── table.tsx
│ │ ├── tabs.tsx
│ │ ├── textarea.tsx
│ │ ├── toast.tsx
│ │ ├── toaster.tsx
│ │ ├── toggle-group.tsx
│ │ ├── toggle.tsx
│ │ ├── tooltip.tsx
│ │ └── use-toast.ts
│ ├── hooks
│ │ ├── use-mobile.tsx
│ │ └── use-toast.ts
│ ├── index.css
│ ├── lib
│ │ └── utils.ts
│ ├── main.tsx
│ ├── pages
│ │ ├── Index.tsx
│ │ └── NotFound.tsx
│ └── vite-env.d.ts
├── tailwind.config.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
├── vercel.json
└── vite.config.ts
```
# Files
--------------------------------------------------------------------------------
/tests/sample_project_typescript/src/advanced-types.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Advanced Types
3 | * Demonstrates TypeScript's advanced type system including mapped types,
4 | * conditional types, template literal types, type manipulation, and complex patterns
5 | */
6 |
7 | // ========== Mapped Types ==========
8 | export type Optional<T> = {
9 | [K in keyof T]?: T[K];
10 | };
11 |
12 | export type Required<T> = {
13 | [K in keyof T]-?: T[K];
14 | };
15 |
16 | export type Readonly<T> = {
17 | readonly [K in keyof T]: T[K];
18 | };
19 |
20 | export type Mutable<T> = {
21 | -readonly [K in keyof T]: T[K];
22 | };
23 |
24 | // Custom mapped type with transformation
25 | export type Stringify<T> = {
26 | [K in keyof T]: string;
27 | };
28 |
29 | export type Nullify<T> = {
30 | [K in keyof T]: T[K] | null;
31 | };
32 |
33 | // Mapped type with key transformation
34 | export type Getters<T> = {
35 | [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
36 | };
37 |
38 | export type Setters<T> = {
39 | [K in keyof T as `set${Capitalize<string & K>}`]: (value: T[K]) => void;
40 | };
41 |
42 | // ========== Conditional Types ==========
43 | export type NonNullable<T> = T extends null | undefined ? never : T;
44 |
45 | export type IsArray<T> = T extends any[] ? true : false;
46 |
47 | export type ArrayElementType<T> = T extends (infer U)[] ? U : never;
48 |
49 | export type ReturnTypeOf<T> = T extends (...args: any[]) => infer R ? R : never;
50 |
51 | export type ParametersOf<T> = T extends (...args: infer P) => any ? P : never;
52 |
53 | // Complex conditional type
54 | export type DeepReadonly<T> = T extends (infer U)[]
55 | ? DeepReadonlyArray<U>
56 | : T extends object
57 | ? DeepReadonlyObject<T>
58 | : T;
59 |
60 | interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}
61 |
62 | type DeepReadonlyObject<T> = {
63 | readonly [K in keyof T]: DeepReadonly<T[K]>;
64 | };
65 |
66 | // Conditional type with multiple conditions
67 | export type TypeName<T> = T extends string
68 | ? "string"
69 | : T extends number
70 | ? "number"
71 | : T extends boolean
72 | ? "boolean"
73 | : T extends undefined
74 | ? "undefined"
75 | : T extends Function
76 | ? "function"
77 | : "object";
78 |
79 | // ========== Template Literal Types ==========
80 | export type EventNames<T extends string> = `${T}Changed` | `${T}Updated` | `before${Capitalize<T>}`;
81 |
82 | export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
83 | export type ApiEndpoint<T extends string> = `api/${T}`;
84 | export type ApiUrl<T extends string, M extends HttpMethod> = `${M} /${ApiEndpoint<T>}`;
85 |
86 | // CSS-in-JS style types
87 | export type CSSProperty = `--${string}` | keyof CSSStyleDeclaration;
88 | export type PixelValue<T extends number> = `${T}px`;
89 | export type PercentValue<T extends number> = `${T}%`;
90 |
91 | // Path-like template literals
92 | export type Join<K, P> = K extends string | number
93 | ? P extends string | number
94 | ? `${K}${"" extends P ? "" : "."}${P}`
95 | : never
96 | : never;
97 |
98 | export type Paths<T, D extends number = 10> = [D] extends [never]
99 | ? never
100 | : T extends object
101 | ? {
102 | [K in keyof T]-?: K extends string | number
103 | ? `${K}` | Join<K, Paths<T[K], Prev[D]>>
104 | : never;
105 | }[keyof T]
106 | : "";
107 |
108 | type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...0[]];
109 |
110 | // ========== Utility Types and Type Manipulation ==========
111 | export type PickByType<T, U> = Pick<T, { [K in keyof T]: T[K] extends U ? K : never }[keyof T]>;
112 |
113 | export type OmitByType<T, U> = Omit<T, { [K in keyof T]: T[K] extends U ? K : never }[keyof T]>;
114 |
115 | export type ExcludeKeys<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
116 |
117 | export type KeysOfType<T, U> = { [K in keyof T]: T[K] extends U ? K : never }[keyof T];
118 |
119 | // Deep pick utility
120 | export type DeepPick<T, K extends Paths<T>> = K extends `${infer Key}.${infer Rest}`
121 | ? Key extends keyof T
122 | ? { [P in Key]: DeepPick<T[P], Rest> }
123 | : never
124 | : K extends keyof T
125 | ? { [P in K]: T[P] }
126 | : never;
127 |
128 | // Function type utilities
129 | export type Promisify<T> = T extends (...args: infer A) => infer R
130 | ? (...args: A) => Promise<R>
131 | : never;
132 |
133 | export type Curry<T> = T extends (...args: infer A) => infer R
134 | ? A extends [infer First, ...infer Rest]
135 | ? (arg: First) => Rest extends []
136 | ? R
137 | : Curry<(...args: Rest) => R>
138 | : () => R
139 | : never;
140 |
141 | // ========== Recursive Types ==========
142 | export type DeepPartial<T> = T extends object
143 | ? {
144 | [P in keyof T]?: DeepPartial<T[P]>;
145 | }
146 | : T;
147 |
148 | export type DeepRequired<T> = T extends object
149 | ? {
150 | [P in keyof T]-?: DeepRequired<T[P]>;
151 | }
152 | : T;
153 |
154 | // JSON type
155 | export type JSONValue = string | number | boolean | null | JSONObject | JSONArray;
156 | interface JSONObject {
157 | [key: string]: JSONValue;
158 | }
159 | interface JSONArray extends Array<JSONValue> {}
160 |
161 | // ========== Branded Types ==========
162 | declare const __brand: unique symbol;
163 | type Brand<T, TBrand extends string> = T & { [__brand]: TBrand };
164 |
165 | export type UserId = Brand<number, "UserId">;
166 | export type Email = Brand<string, "Email">;
167 | export type Timestamp = Brand<number, "Timestamp">;
168 |
169 | // Brand creation utilities
170 | export const createUserId = (id: number): UserId => id as UserId;
171 | export const createEmail = (email: string): Email => {
172 | if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
173 | throw new Error("Invalid email format");
174 | }
175 | return email as Email;
176 | };
177 |
178 | // ========== Tuple Utilities ==========
179 | export type Head<T extends readonly any[]> = T extends readonly [infer H, ...any[]] ? H : never;
180 | export type Tail<T extends readonly any[]> = T extends readonly [any, ...infer Rest] ? Rest : [];
181 | export type Last<T extends readonly any[]> = T extends readonly [...any[], infer L] ? L : never;
182 | export type Length<T extends readonly any[]> = T["length"];
183 |
184 | export type Reverse<T extends any[]> = T extends [...infer Rest, infer Last]
185 | ? [Last, ...Reverse<Rest>]
186 | : [];
187 |
188 | // ========== String Manipulation Types ==========
189 | export type Uppercase<S extends string> = intrinsic;
190 | export type Lowercase<S extends string> = intrinsic;
191 | export type Capitalize<S extends string> = intrinsic;
192 | export type Uncapitalize<S extends string> = intrinsic;
193 |
194 | export type Split<S extends string, D extends string> = string extends S
195 | ? string[]
196 | : S extends ""
197 | ? []
198 | : S extends `${infer T}${D}${infer U}`
199 | ? [T, ...Split<U, D>]
200 | : [S];
201 |
202 | export type Join<T extends string[], D extends string> = T extends [
203 | infer First,
204 | ...infer Rest
205 | ]
206 | ? First extends string
207 | ? Rest extends string[]
208 | ? Rest["length"] extends 0
209 | ? First
210 | : `${First}${D}${Join<Rest, D>}`
211 | : never
212 | : never
213 | : "";
214 |
215 | // ========== Advanced Pattern Matching ==========
216 | export type ExtractRouteParams<T extends string> = T extends `${string}:${infer Param}/${infer Rest}`
217 | ? { [K in Param]: string } & ExtractRouteParams<Rest>
218 | : T extends `${string}:${infer Param}`
219 | ? { [K in Param]: string }
220 | : {};
221 |
222 | export type ParseQueryString<T extends string> = T extends `${infer Key}=${infer Value}&${infer Rest}`
223 | ? { [K in Key]: Value } & ParseQueryString<Rest>
224 | : T extends `${infer Key}=${infer Value}`
225 | ? { [K in Key]: Value }
226 | : {};
227 |
228 | // ========== Type Predicates and Guards ==========
229 | export type IsUnion<T, U = T> = T extends U ? ([U] extends [T] ? false : true) : false;
230 | export type IsNever<T> = [T] extends [never] ? true : false;
231 | export type IsAny<T> = 0 extends 1 & T ? true : false;
232 | export type IsUnknown<T> = IsAny<T> extends true ? false : unknown extends T ? true : false;
233 |
234 | // ========== Higher-Kinded Types Simulation ==========
235 | export interface Functor<F> {
236 | map<A, B>(fn: (a: A) => B): <T extends F>(fa: T) => T extends HKT<F, A> ? HKT<F, B> : never;
237 | }
238 |
239 | export interface HKT<F, A> {
240 | _F: F;
241 | _A: A;
242 | }
243 |
244 | // Array functor instance
245 | export type ArrayHKT = "Array";
246 | export interface ArrayF<A> extends HKT<ArrayHKT, A> {
247 | _tag: A[];
248 | }
249 |
250 | // ========== Example Usage Types ==========
251 | interface User {
252 | id: number;
253 | name: string;
254 | email: string;
255 | age: number;
256 | address: {
257 | street: string;
258 | city: string;
259 | country: string;
260 | };
261 | preferences: {
262 | theme: "light" | "dark";
263 | notifications: boolean;
264 | };
265 | }
266 |
267 | // Applied utility types
268 | export type Examples = {
269 | // Mapped types
270 | optionalUser: Optional<User>;
271 | readonlyUser: Readonly<User>;
272 | stringifiedUser: Stringify<User>;
273 |
274 | // Conditional types
275 | userIsArray: IsArray<User>;
276 | userArrayElement: ArrayElementType<User[]>;
277 | nonNullableString: NonNullable<string | null>;
278 |
279 | // Template literals
280 | userEventNames: EventNames<"user">;
281 | apiEndpoints: ApiUrl<"users", "GET"> | ApiUrl<"posts", "POST">;
282 |
283 | // Utility combinations
284 | userOnlyStrings: PickByType<User, string>;
285 | userWithoutStrings: OmitByType<User, string>;
286 | userPaths: Paths<User>;
287 |
288 | // Branded types
289 | userId: UserId;
290 | userEmail: Email;
291 |
292 | // Advanced patterns
293 | routeParams: ExtractRouteParams<"/users/:id/posts/:postId">;
294 | queryParams: ParseQueryString<"search=typescript&sort=date&limit=10">;
295 | };
296 |
297 | // ========== Complex Type Challenges ==========
298 | // Function composition types
299 | export type Compose<F extends any[], T = any> = F extends [
300 | (...args: any[]) => infer R
301 | ]
302 | ? (arg: T) => R
303 | : F extends [(...args: any[]) => infer R, ...infer Rest]
304 | ? (arg: T) => Compose<Rest, R>
305 | : never;
306 |
307 | // Object path access
308 | export type Get<T, K> = K extends `${infer Key}.${infer Rest}`
309 | ? Key extends keyof T
310 | ? Get<T[Key], Rest>
311 | : never
312 | : K extends keyof T
313 | ? T[K]
314 | : never;
315 |
316 | // Type-safe SQL-like operations
317 | export type Select<T, K extends keyof T> = Pick<T, K>;
318 | export type Where<T, K extends keyof T, V> = T[K] extends V ? T : never;
319 | export type OrderBy<T, K extends keyof T> = T; // Simplified for demo
320 |
321 | // State machine types
322 | export type StateMachine<States extends string, Events extends string> = {
323 | [S in States]: {
324 | [E in Events]?: States;
325 | };
326 | };
327 |
328 | export type UserStateMachine = StateMachine<
329 | "idle" | "loading" | "success" | "error",
330 | "fetch" | "success" | "error" | "reset"
331 | >;
332 |
333 | // ========== Type-Level Arithmetic (Basic) ==========
334 | export type Add<A extends number, B extends number> = [...Tuple<A>, ...Tuple<B>]["length"];
335 | export type Tuple<T extends number> = T extends T ? (T extends 0 ? [] : [...Tuple<Subtract<T, 1>>, any]) : never;
336 | export type Subtract<A extends number, B extends number> = Tuple<A> extends [...infer U, ...Tuple<B>] ? U["length"] : never;
337 |
338 | // ========== Usage Examples ==========
339 | export const advancedTypesExamples = {
340 | // Branded types usage
341 | userId: createUserId(123),
342 | userEmail: createEmail("[email protected]"),
343 |
344 | // Template literal types
345 | apiUrl: "GET /api/users" as ApiUrl<"users", "GET">,
346 |
347 | // Complex type transformations
348 | userPaths: ["id", "name", "email", "address.street", "preferences.theme"] as Paths<User>[],
349 |
350 | // Type predicates
351 | isUnion: false as IsUnion<string | number>,
352 | isNever: false as IsNever<never>,
353 | isAny: false as IsAny<any>,
354 | };
355 |
356 | // Example of using advanced types in practice
357 | export function createTypeSafeGetter<T>() {
358 | return function get<K extends Paths<T>>(obj: T, path: K): Get<T, K> {
359 | const keys = path.split('.') as string[];
360 | let result: any = obj;
361 |
362 | for (const key of keys) {
363 | result = result?.[key];
364 | }
365 |
366 | return result as Get<T, K>;
367 | };
368 | }
369 |
370 | // Usage of the type-safe getter
371 | const userGetter = createTypeSafeGetter<User>();
372 | export const getExample = {
373 | userName: userGetter({} as User, "name"), // Type is string
374 | userCity: userGetter({} as User, "address.city"), // Type is string
375 | userTheme: userGetter({} as User, "preferences.theme"), // Type is "light" | "dark"
376 | };
```
--------------------------------------------------------------------------------
/docs/docs/index.md:
--------------------------------------------------------------------------------
```markdown
1 | # Welcome to CodeGraphContext
2 |
3 | This is the official documentation for CodeGraphContext.
4 |
5 | ---
6 |
7 | # CodeGraphContext
8 |
9 | <!-- ====== Project stats ====== -->
10 | [](https://github.com/Shashankss1205/CodeGraphContext/stargazers)
11 | [](https://github.com/Shashankss1205/CodeGraphContext/network/members)
12 | [](https://github.com/Shashankss1205/CodeGraphContext/issues)
13 | [](https://github.com/Shashankss1205/CodeGraphContext/pulls)
14 | [](https://github.com/Shashankss1205/CodeGraphContext/pulls?q=is%3Apr+is%3Aclosed)
15 | [](https://github.com/Shashankss1205/CodeGraphContext/graphs/contributors)
16 | [](https://github.com/Shashankss1205/CodeGraphContext)
17 | [](https://github.com/Shashankss1205/CodeGraphContext/actions/workflows/test.yml)
18 | [](https://github.com/Shashankss1205/CodeGraphContext/actions/workflows/e2e-tests.yml)
19 | [](https://pypi.org/project/codegraphcontext/)
20 | [](https://pypi.org/project/codegraphcontext/)
21 | [](license.md)
22 | [](http://codegraphcontext.vercel.app/)
23 | [](https://youtu.be/KYYSdxhg1xU)
24 | [](https://discord.gg/dR4QY32uYQ)
25 |
26 |
27 |
28 | An MCP server that indexes local code into a graph database to provide context to AI assistants.
29 |
30 | ### Indexing a codebase
31 | 
32 |
33 | ### Using the MCP server
34 | 
35 |
36 | ## Project Details
37 | - **Version:** 0.1.15
38 | - **Authors:** Shashank Shekhar Singh <[email protected]>
39 | - **License:** MIT License (See [LICENSE](license.md) for details)
40 | - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
41 |
42 | ## Star History
43 | [](https://www.star-history.com/#Shashankss1205/CodeGraphContext&Date)
44 |
45 | ## Features
46 |
47 | - **Code Indexing:** Analyzes code and builds a knowledge graph of its components.
48 | - **Relationship Analysis:** Query for callers, callees, class hierarchies, call chains and more.
49 | - **Live Updates:** Watches local files for changes and automatically updates the graph.
50 | - **Interactive Setup:** A user-friendly command-line wizard for easy setup.
51 | - **File Exclusion:** Supports `.cgcignore` files to exclude specific files and directories from indexing.
52 |
53 | ## Used By
54 |
55 | CodeGraphContext is already being explored by developers and projects for:
56 |
57 | - **Static code analysis in AI assistants**
58 | - **Graph-based visualization of projects**
59 | - **Dead code and complexity detection**
60 |
61 | If you’re using CodeGraphContext in your project, feel free to open a PR and add it here! 🚀
62 |
63 | ## Dependencies
64 |
65 | - `neo4j>=5.15.0`
66 | - `watchdog>=3.0.0`
67 | - `requests>=2.31.0`
68 | - `stdlibs>=2023.11.18`
69 | - `typer[all]>=0.9.0`
70 | - `rich>=13.7.0`
71 | - `inquirerpy>=0.3.4`
72 | - `python-dotenv>=1.0.0`
73 | - `tree-sitter==0.20.4`
74 | - `tree-sitter-languages==1.10.2`
75 |
76 | ## Getting Started
77 |
78 | 1. **Install:** `pip install codegraphcontext`
79 | 2. **Configure Your Environment:**
80 | Run the interactive setup wizard to connect to your database and configure your IDE:
81 | ```bash
82 | cgc setup
83 | ```
84 | The wizard helps you with:
85 | - **Database Connection:**
86 | - **Docker (Recommended):** Automatically sets up a local Neo4j instance.
87 | - **Linux Binary:** Installs Neo4j directly on Debian-based systems.
88 | - **Hosted:** Connects to a remote Neo4j database like AuraDB.
89 | - **IDE Integration:**
90 | - Automatically configures tools like VS Code, Cursor, Gemini CLI, and more.
91 | - Generates the necessary `mcp.json` and `.env` files for you.
92 |
93 | 3. **Start:** `cgc start`
94 |
95 | ## MCP Client Configuration
96 |
97 | The `cgc setup` command attempts to automatically configure your IDE/CLI. If you choose not to use the automatic setup, or if your tool is not supported, you can configure it manually.
98 |
99 | Add the following server configuration to your client's settings file (e.g., VS Code's `settings.json` or `.claude.json`):
100 |
101 | ```json
102 | {
103 | "mcpServers": {
104 | "CodeGraphContext": {
105 | "command": "cgc",
106 | "args": [
107 | "start"
108 | ],
109 | "env": {
110 | "NEO4J_URI": "YOUR_NEO4J_URI",
111 | "NEO4J_USERNAME": "YOUR_NEO4J_USERNAME",
112 | "NEO4J_PASSWORD": "YOUR_NEO4J_PASSWORD"
113 | },
114 | "tools": {
115 | "alwaysAllow": [
116 | "add_code_to_graph",
117 | "add_package_to_graph",
118 | "check_job_status",
119 | "list_jobs",
120 | "find_code",
121 | "analyze_code_relationships",
122 | "watch_directory",
123 | "find_dead_code",
124 | "execute_cypher_query",
125 | "calculate_cyclomatic_complexity",
126 | "find_most_complex_functions",
127 | "list_indexed_repositories",
128 | "delete_repository",
129 | "visualize_graph_query",
130 | "list_watched_paths",
131 | "unwatch_directory"
132 | ],
133 | "disabled": false
134 | },
135 | "disabled": false,
136 | "alwaysAllow": []
137 | }
138 | }
139 | }
140 | ```
141 |
142 | ## Natural Language Interaction Examples
143 |
144 | Once the server is running, you can interact with it through your AI assistant using plain English. Here are some examples of what you can say:
145 |
146 | ### Indexing and Watching Files
147 |
148 | - **To index a new project:**
149 | - "Please index the code in the `/path/to/my-project` directory."
150 | OR
151 | - "Add the project at `~/dev/my-other-project` to the code graph."
152 |
153 |
154 | - **To start watching a directory for live changes:**
155 | - "Watch the `/path/to/my-active-project` directory for changes."
156 | OR
157 | - "Keep the code graph updated for the project I'm working on at `~/dev/main-app`."
158 |
159 | When you ask to watch a directory, the system performs two actions at once:
160 | 1. It kicks off a full scan to index all the code in that directory. This process runs in the background, and you'll receive a `job_id` to track its progress.
161 | 2. It begins watching the directory for any file changes to keep the graph updated in real-time.
162 |
163 | This means you can start by simply telling the system to watch a directory, and it will handle both the initial indexing and the continuous updates automatically.
164 |
165 | ### Querying and Understanding Code
166 |
167 | - **Finding where code is defined:**
168 | - "Where is the `process_payment` function?"
169 | - "Find the `User` class for me."
170 | - "Show me any code related to 'database connection'."
171 |
172 | - **Analyzing relationships and impact:**
173 | - "What other functions call the `get_user_by_id` function?"
174 | - "If I change the `calculate_tax` function, what other parts of the code will be affected?"
175 | - "Show me the inheritance hierarchy for the `BaseController` class."
176 | - "What methods does the `Order` class have?"
177 |
178 | - **Exploring dependencies:**
179 | - "Which files import the `requests` library?"
180 | - "Find all implementations of the `render` method."
181 |
182 | - **Advanced Call Chain and Dependency Tracking (Spanning Hundreds of Files):**
183 | The CodeGraphContext excels at tracing complex execution flows and dependencies across vast codebases. Leveraging the power of graph databases, it can identify direct and indirect callers and callees, even when a function is called through multiple layers of abstraction or across numerous files. This is invaluable for:
184 | - **Impact Analysis:** Understand the full ripple effect of a change to a core function.
185 | - **Debugging:** Trace the path of execution from an entry point to a specific bug.
186 | - **Code Comprehension:** Grasp how different parts of a large system interact.
187 |
188 | - "Show me the full call chain from the `main` function to `process_data`."
189 | - "Find all functions that directly or indirectly call `validate_input`."
190 | - "What are all the functions that `initialize_system` eventually calls?"
191 | - "Trace the dependencies of the `DatabaseManager` module."
192 |
193 | - **Code Quality and Maintenance:**
194 | - "Is there any dead or unused code in this project?"
195 | - "Calculate the cyclomatic complexity of the `process_data` function in `src/utils.py`."
196 | - "Find the 5 most complex functions in the codebase."
197 |
198 | - **Repository Management:**
199 | - "List all currently indexed repositories."
200 | - "Delete the indexed repository at `/path/to/old-project`."
201 |
202 | ## Social Coverage
203 |
204 | - **Youtube:** [https://www.youtube.com/watch?v=KYYSdxhg1xU](https://www.youtube.com/watch?v=KYYSdxhg1xU)
205 | - **Blog:** [https://medium.com/@shashankshekharsingh1205/building-codegraphcontext-my-end-term-journey-in-summer-of-bitcoin-2025-422c9a4dc87e](https://medium.com/@shashankshekharsingh1205/building-codegraphcontext-my-end-term-journey-in-summer-of-bitcoin-2025-422c9a4dc87e)
206 | - **Twitter:** [https://x.com/braidpool/status/1968683721625637203](https://x.com/braidpool/status/1968683721625637203)
207 | - **PulseMCP:** [https://www.pulsemcp.com/servers/codegraphcontext](https://www.pulsemcp.com/servers/codegraphcontext)
208 | - **MCPMarket:** [https://mcpmarket.com/server/codegraphcontext](https://mcpmarket.com/server/codegraphcontext)
209 | - **Playbooks:** [https://playbooks.com/mcp/codegraphcontext](https://playbooks.com/mcp/codegraphcontext)
210 | - **MCPHunt:** [https://mcp-hunt.com/mcp/server/codegraphcontext](https://mcp-hunt.com/mcp/server/codegraphcontext)
211 | - **StackerNews:** [https://stacker.news/items/1227191](https://stacker.news/items/1227191)
212 | - **Glama.ai:** [https://glama.ai/mcp/servers/@Shashankss1205/CodeGraphContext/blob/a346d340d8f705ce93626b4b322dd0e2823ba46b/src/codegraphcontext/core/jobs.py](https://glama.ai/mcp/servers/@Shashankss1205/CodeGraphContext/blob/a346d340d8f705ce93626b4b322dd0e2823ba46b/src/codegraphcontext/core/jobs.py)
213 |
214 | ## Contributing
215 |
216 | Contributions are welcome! 🎉
217 | Please see our [CONTRIBUTING.md](contributing.md) for detailed guidelines.
218 | If you have ideas for new features, integrations, or improvements, open an [issue](https://github.com/Shashankss1205/CodeGraphContext/issues) or submit a Pull Request.
219 |
220 | Join discussions and help shape the future of CodeGraphContext.
221 |
```
--------------------------------------------------------------------------------
/tests/sample_project_typescript/src/async-promises.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Async and Promises
3 | * Demonstrates TypeScript's asynchronous programming features including
4 | * promises, async/await, error handling, concurrent operations, and patterns
5 | */
6 |
7 | // ========== Basic Promises ==========
8 | export function createPromise<T>(value: T, delay: number = 100): Promise<T> {
9 | return new Promise((resolve) => {
10 | setTimeout(() => resolve(value), delay);
11 | });
12 | }
13 |
14 | export function createRejectedPromise(error: string, delay: number = 100): Promise<never> {
15 | return new Promise((_, reject) => {
16 | setTimeout(() => reject(new Error(error)), delay);
17 | });
18 | }
19 |
20 | // ========== Async Functions ==========
21 | export async function fetchUserData(id: number): Promise<{ id: number; name: string; email: string }> {
22 | // Simulate API call
23 | await new Promise(resolve => setTimeout(resolve, 200));
24 |
25 | if (id <= 0) {
26 | throw new Error("Invalid user ID");
27 | }
28 |
29 | return {
30 | id,
31 | name: `User ${id}`,
32 | email: `user${id}@example.com`
33 | };
34 | }
35 |
36 | export async function fetchUserPosts(userId: number): Promise<{ id: number; title: string; content: string }[]> {
37 | await new Promise(resolve => setTimeout(resolve, 150));
38 |
39 | return Array.from({ length: 3 }, (_, index) => ({
40 | id: index + 1,
41 | title: `Post ${index + 1} by User ${userId}`,
42 | content: `This is the content of post ${index + 1}`
43 | }));
44 | }
45 |
46 | // ========== Error Handling with Async/Await ==========
47 | export async function safeAsyncOperation<T>(
48 | operation: () => Promise<T>
49 | ): Promise<{ success: true; data: T } | { success: false; error: string }> {
50 | try {
51 | const data = await operation();
52 | return { success: true, data };
53 | } catch (error) {
54 | return {
55 | success: false,
56 | error: error instanceof Error ? error.message : "Unknown error"
57 | };
58 | }
59 | }
60 |
61 | export async function retryOperation<T>(
62 | operation: () => Promise<T>,
63 | maxRetries: number = 3,
64 | delay: number = 1000
65 | ): Promise<T> {
66 | let lastError: Error;
67 |
68 | for (let attempt = 1; attempt <= maxRetries; attempt++) {
69 | try {
70 | return await operation();
71 | } catch (error) {
72 | lastError = error instanceof Error ? error : new Error(String(error));
73 |
74 | if (attempt === maxRetries) {
75 | throw lastError;
76 | }
77 |
78 | // Exponential backoff
79 | await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, attempt - 1)));
80 | }
81 | }
82 |
83 | throw lastError!;
84 | }
85 |
86 | // ========== Promise Combinators ==========
87 | export async function processInParallel<T>(
88 | items: T[],
89 | processor: (item: T) => Promise<any>,
90 | concurrency: number = 3
91 | ): Promise<any[]> {
92 | const results: any[] = [];
93 | const chunks: T[][] = [];
94 |
95 | // Split into chunks
96 | for (let i = 0; i < items.length; i += concurrency) {
97 | chunks.push(items.slice(i, i + concurrency));
98 | }
99 |
100 | // Process chunks sequentially, items within chunks in parallel
101 | for (const chunk of chunks) {
102 | const chunkResults = await Promise.all(chunk.map(processor));
103 | results.push(...chunkResults);
104 | }
105 |
106 | return results;
107 | }
108 |
109 | export async function raceWithTimeout<T>(
110 | promise: Promise<T>,
111 | timeoutMs: number
112 | ): Promise<T> {
113 | const timeoutPromise = new Promise<never>((_, reject) => {
114 | setTimeout(() => reject(new Error(`Operation timed out after ${timeoutMs}ms`)), timeoutMs);
115 | });
116 |
117 | return Promise.race([promise, timeoutPromise]);
118 | }
119 |
120 | // ========== Async Iterators and Generators ==========
121 | export async function* asyncGenerator(count: number): AsyncGenerator<number, void, unknown> {
122 | for (let i = 0; i < count; i++) {
123 | await new Promise(resolve => setTimeout(resolve, 100));
124 | yield i;
125 | }
126 | }
127 |
128 | export async function* fetchDataStream(urls: string[]): AsyncGenerator<string, void, unknown> {
129 | for (const url of urls) {
130 | // Simulate fetching data
131 | await new Promise(resolve => setTimeout(resolve, 200));
132 | yield `Data from ${url}`;
133 | }
134 | }
135 |
136 | export async function consumeAsyncGenerator<T>(generator: AsyncGenerator<T>): Promise<T[]> {
137 | const results: T[] = [];
138 | for await (const item of generator) {
139 | results.push(item);
140 | }
141 | return results;
142 | }
143 |
144 | // ========== Observable Pattern ==========
145 | export class EventEmitter<T> {
146 | private listeners: ((data: T) => void)[] = [];
147 | private asyncListeners: ((data: T) => Promise<void>)[] = [];
148 |
149 | subscribe(callback: (data: T) => void): () => void {
150 | this.listeners.push(callback);
151 | return () => {
152 | const index = this.listeners.indexOf(callback);
153 | if (index > -1) {
154 | this.listeners.splice(index, 1);
155 | }
156 | };
157 | }
158 |
159 | subscribeAsync(callback: (data: T) => Promise<void>): () => void {
160 | this.asyncListeners.push(callback);
161 | return () => {
162 | const index = this.asyncListeners.indexOf(callback);
163 | if (index > -1) {
164 | this.asyncListeners.splice(index, 1);
165 | }
166 | };
167 | }
168 |
169 | emit(data: T): void {
170 | this.listeners.forEach(callback => callback(data));
171 | // Fire async listeners but don't wait
172 | this.asyncListeners.forEach(callback => callback(data).catch(console.error));
173 | }
174 |
175 | async emitAsync(data: T): Promise<void> {
176 | this.listeners.forEach(callback => callback(data));
177 | await Promise.all(this.asyncListeners.map(callback => callback(data)));
178 | }
179 | }
180 |
181 | // ========== Promise Pool ==========
182 | export class PromisePool<T, R> {
183 | private concurrency: number;
184 | private tasks: (() => Promise<R>)[] = [];
185 | private running: number = 0;
186 | private results: R[] = [];
187 | private errors: Error[] = [];
188 |
189 | constructor(concurrency: number = 5) {
190 | this.concurrency = concurrency;
191 | }
192 |
193 | add(task: () => Promise<R>): void {
194 | this.tasks.push(task);
195 | }
196 |
197 | async execute(): Promise<{ results: R[]; errors: Error[] }> {
198 | return new Promise((resolve) => {
199 | const executeNext = () => {
200 | if (this.tasks.length === 0 && this.running === 0) {
201 | resolve({ results: this.results, errors: this.errors });
202 | return;
203 | }
204 |
205 | while (this.running < this.concurrency && this.tasks.length > 0) {
206 | const task = this.tasks.shift()!;
207 | this.running++;
208 |
209 | task()
210 | .then(result => {
211 | this.results.push(result);
212 | })
213 | .catch(error => {
214 | this.errors.push(error instanceof Error ? error : new Error(String(error)));
215 | })
216 | .finally(() => {
217 | this.running--;
218 | executeNext();
219 | });
220 | }
221 | };
222 |
223 | executeNext();
224 | });
225 | }
226 | }
227 |
228 | // ========== Async Cache ==========
229 | export class AsyncCache<K, V> {
230 | private cache = new Map<K, Promise<V>>();
231 | private ttl: number;
232 |
233 | constructor(ttlMs: number = 60000) {
234 | this.ttl = ttlMs;
235 | }
236 |
237 | async get(key: K, factory: () => Promise<V>): Promise<V> {
238 | if (this.cache.has(key)) {
239 | try {
240 | return await this.cache.get(key)!;
241 | } catch (error) {
242 | // Remove failed promise from cache
243 | this.cache.delete(key);
244 | throw error;
245 | }
246 | }
247 |
248 | const promise = factory();
249 | this.cache.set(key, promise);
250 |
251 | // Set TTL
252 | setTimeout(() => {
253 | this.cache.delete(key);
254 | }, this.ttl);
255 |
256 | return promise;
257 | }
258 |
259 | clear(): void {
260 | this.cache.clear();
261 | }
262 |
263 | has(key: K): boolean {
264 | return this.cache.has(key);
265 | }
266 | }
267 |
268 | // ========== Async Semaphore ==========
269 | export class Semaphore {
270 | private permits: number;
271 | private waiting: (() => void)[] = [];
272 |
273 | constructor(permits: number) {
274 | this.permits = permits;
275 | }
276 |
277 | async acquire(): Promise<void> {
278 | if (this.permits > 0) {
279 | this.permits--;
280 | return;
281 | }
282 |
283 | return new Promise<void>((resolve) => {
284 | this.waiting.push(resolve);
285 | });
286 | }
287 |
288 | release(): void {
289 | if (this.waiting.length > 0) {
290 | const next = this.waiting.shift()!;
291 | next();
292 | } else {
293 | this.permits++;
294 | }
295 | }
296 |
297 | async execute<T>(fn: () => Promise<T>): Promise<T> {
298 | await this.acquire();
299 | try {
300 | return await fn();
301 | } finally {
302 | this.release();
303 | }
304 | }
305 | }
306 |
307 | // ========== Worker Pattern ==========
308 | export class TaskQueue<T> {
309 | private queue: T[] = [];
310 | private processing = false;
311 | private processor: (item: T) => Promise<void>;
312 |
313 | constructor(processor: (item: T) => Promise<void>) {
314 | this.processor = processor;
315 | }
316 |
317 | enqueue(item: T): void {
318 | this.queue.push(item);
319 | if (!this.processing) {
320 | this.processQueue();
321 | }
322 | }
323 |
324 | private async processQueue(): Promise<void> {
325 | this.processing = true;
326 |
327 | while (this.queue.length > 0) {
328 | const item = this.queue.shift()!;
329 | try {
330 | await this.processor(item);
331 | } catch (error) {
332 | console.error("Error processing queue item:", error);
333 | }
334 | }
335 |
336 | this.processing = false;
337 | }
338 |
339 | get length(): number {
340 | return this.queue.length;
341 | }
342 |
343 | get isProcessing(): boolean {
344 | return this.processing;
345 | }
346 | }
347 |
348 | // ========== Stream Processing ==========
349 | export async function processStream<T, R>(
350 | items: T[],
351 | transformer: (item: T) => Promise<R>,
352 | batchSize: number = 10
353 | ): Promise<R[]> {
354 | const results: R[] = [];
355 |
356 | for (let i = 0; i < items.length; i += batchSize) {
357 | const batch = items.slice(i, i + batchSize);
358 | const batchResults = await Promise.all(batch.map(transformer));
359 | results.push(...batchResults);
360 | }
361 |
362 | return results;
363 | }
364 |
365 | // ========== Usage Examples ==========
366 | export const asyncExamples = {
367 | // Event emitter
368 | userEvents: new EventEmitter<{ userId: number; action: string }>(),
369 |
370 | // Promise pool
371 | apiCallPool: new PromisePool<void, any>(3),
372 |
373 | // Async cache
374 | userCache: new AsyncCache<number, { id: number; name: string }>(30000),
375 |
376 | // Semaphore for rate limiting
377 | rateLimiter: new Semaphore(5),
378 |
379 | // Task queue
380 | notificationQueue: new TaskQueue<{ userId: number; message: string }>(async (notification) => {
381 | console.log(`Sending notification to user ${notification.userId}: ${notification.message}`);
382 | await new Promise(resolve => setTimeout(resolve, 100));
383 | }),
384 | };
385 |
386 | // ========== Complex Async Operations ==========
387 | export async function fetchUserProfile(userId: number): Promise<{
388 | user: { id: number; name: string; email: string };
389 | posts: { id: number; title: string; content: string }[];
390 | }> {
391 | try {
392 | // Fetch user and posts in parallel
393 | const [user, posts] = await Promise.all([
394 | fetchUserData(userId),
395 | fetchUserPosts(userId)
396 | ]);
397 |
398 | return { user, posts };
399 | } catch (error) {
400 | throw new Error(`Failed to fetch user profile: ${error}`);
401 | }
402 | }
403 |
404 | export async function batchProcessUsers(userIds: number[]): Promise<any[]> {
405 | // Use the promise pool to limit concurrent API calls
406 | const pool = new PromisePool<void, any>(3);
407 |
408 | userIds.forEach(id => {
409 | pool.add(async () => {
410 | const profile = await fetchUserProfile(id);
411 | return profile;
412 | });
413 | });
414 |
415 | const { results, errors } = await pool.execute();
416 |
417 | if (errors.length > 0) {
418 | console.warn(`${errors.length} errors occurred during batch processing:`, errors);
419 | }
420 |
421 | return results;
422 | }
423 |
424 | // Initialize some examples
425 | asyncExamples.userEvents.subscribe((event) => {
426 | console.log(`User event: ${event.action} for user ${event.userId}`);
427 | });
428 |
429 | // Example of using the notification queue
430 | asyncExamples.notificationQueue.enqueue({
431 | userId: 1,
432 | message: "Welcome to our platform!"
433 | });
434 |
435 | asyncExamples.notificationQueue.enqueue({
436 | userId: 2,
437 | message: "Your order has been shipped!"
438 | });
```
--------------------------------------------------------------------------------
/tests/sample_project_typescript/src/modules-namespaces.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Modules and Namespaces
3 | * Demonstrates TypeScript's module system, imports/exports, namespaces,
4 | * ambient declarations, and advanced module patterns
5 | */
6 |
7 | // ========== Basic Exports ==========
8 | export const MODULE_VERSION = "1.0.0";
9 | export const DEFAULT_CONFIG = {
10 | debug: false,
11 | timeout: 5000,
12 | retries: 3
13 | };
14 |
15 | // Named export
16 | export function calculateSum(a: number, b: number): number {
17 | return a + b;
18 | }
19 |
20 | // Export with alias
21 | export { calculateSum as add };
22 |
23 | // Multiple exports
24 | export const PI = Math.PI;
25 | export const E = Math.E;
26 |
27 | // ========== Default Export ==========
28 | class DefaultLogger {
29 | private prefix: string;
30 |
31 | constructor(prefix: string = "LOG") {
32 | this.prefix = prefix;
33 | }
34 |
35 | log(message: string): void {
36 | console.log(`[${this.prefix}] ${message}`);
37 | }
38 |
39 | error(message: string): void {
40 | console.error(`[${this.prefix}] ERROR: ${message}`);
41 | }
42 | }
43 |
44 | export default DefaultLogger;
45 |
46 | // ========== Re-exports ==========
47 | // Re-export everything from types-interfaces
48 | export * from './types-interfaces';
49 |
50 | // Re-export specific items with aliases
51 | export {
52 | Person as BasePerson,
53 | Employee as StaffMember
54 | } from './classes-inheritance';
55 |
56 | // Re-export default with a name
57 | export { default as Logger } from './modules-namespaces';
58 |
59 | // ========== Namespace Declarations ==========
60 | export namespace MathUtils {
61 | export interface Point2D {
62 | x: number;
63 | y: number;
64 | }
65 |
66 | export interface Point3D extends Point2D {
67 | z: number;
68 | }
69 |
70 | export class Vector2D implements Point2D {
71 | constructor(public x: number, public y: number) {}
72 |
73 | add(other: Vector2D): Vector2D {
74 | return new Vector2D(this.x + other.x, this.y + other.y);
75 | }
76 |
77 | magnitude(): number {
78 | return Math.sqrt(this.x * this.x + this.y * this.y);
79 | }
80 | }
81 |
82 | export class Vector3D implements Point3D {
83 | constructor(public x: number, public y: number, public z: number) {}
84 |
85 | add(other: Vector3D): Vector3D {
86 | return new Vector3D(this.x + other.x, this.y + other.y, this.z + other.z);
87 | }
88 |
89 | magnitude(): number {
90 | return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
91 | }
92 | }
93 |
94 | export function distance2D(p1: Point2D, p2: Point2D): number {
95 | const dx = p1.x - p2.x;
96 | const dy = p1.y - p2.y;
97 | return Math.sqrt(dx * dx + dy * dy);
98 | }
99 |
100 | export function distance3D(p1: Point3D, p2: Point3D): number {
101 | const dx = p1.x - p2.x;
102 | const dy = p1.y - p2.y;
103 | const dz = p1.z - p2.z;
104 | return Math.sqrt(dx * dx + dy * dy + dz * dz);
105 | }
106 |
107 | export namespace Constants {
108 | export const GOLDEN_RATIO = 1.618033988749895;
109 | export const EULER_CONSTANT = 0.5772156649015329;
110 | export const SQRT_2 = Math.sqrt(2);
111 | }
112 | }
113 |
114 | // Nested namespace
115 | export namespace DataStructures {
116 | export namespace Trees {
117 | export interface TreeNode<T> {
118 | value: T;
119 | left?: TreeNode<T>;
120 | right?: TreeNode<T>;
121 | }
122 |
123 | export class BinaryTree<T> {
124 | constructor(public root?: TreeNode<T>) {}
125 |
126 | insert(value: T): void {
127 | this.root = this.insertNode(this.root, value);
128 | }
129 |
130 | private insertNode(node: TreeNode<T> | undefined, value: T): TreeNode<T> {
131 | if (!node) {
132 | return { value };
133 | }
134 |
135 | // Simple insertion based on string comparison
136 | if (String(value) < String(node.value)) {
137 | node.left = this.insertNode(node.left, value);
138 | } else {
139 | node.right = this.insertNode(node.right, value);
140 | }
141 |
142 | return node;
143 | }
144 | }
145 | }
146 |
147 | export namespace Graphs {
148 | export interface Edge<T> {
149 | from: T;
150 | to: T;
151 | weight?: number;
152 | }
153 |
154 | export class Graph<T> {
155 | private adjacencyList: Map<T, T[]> = new Map();
156 |
157 | addVertex(vertex: T): void {
158 | if (!this.adjacencyList.has(vertex)) {
159 | this.adjacencyList.set(vertex, []);
160 | }
161 | }
162 |
163 | addEdge(from: T, to: T): void {
164 | this.addVertex(from);
165 | this.addVertex(to);
166 | this.adjacencyList.get(from)!.push(to);
167 | }
168 |
169 | getNeighbors(vertex: T): T[] {
170 | return this.adjacencyList.get(vertex) || [];
171 | }
172 |
173 | getVertices(): T[] {
174 | return Array.from(this.adjacencyList.keys());
175 | }
176 | }
177 | }
178 | }
179 |
180 | // ========== Module Augmentation ==========
181 | // Extending existing modules
182 | declare global {
183 | interface String {
184 | toTitleCase(): string;
185 | truncate(length: number): string;
186 | }
187 |
188 | interface Array<T> {
189 | chunk(size: number): T[][];
190 | unique(): T[];
191 | }
192 | }
193 |
194 | // Implement the extensions
195 | String.prototype.toTitleCase = function(): string {
196 | return this.replace(/\w\S*/g, (txt) =>
197 | txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
198 | );
199 | };
200 |
201 | String.prototype.truncate = function(length: number): string {
202 | return this.length > length ? this.substring(0, length) + '...' : this.toString();
203 | };
204 |
205 | Array.prototype.chunk = function<T>(this: T[], size: number): T[][] {
206 | const chunks: T[][] = [];
207 | for (let i = 0; i < this.length; i += size) {
208 | chunks.push(this.slice(i, i + size));
209 | }
210 | return chunks;
211 | };
212 |
213 | Array.prototype.unique = function<T>(this: T[]): T[] {
214 | return [...new Set(this)];
215 | };
216 |
217 | // ========== Ambient Declarations ==========
218 | // Declare external libraries or global variables
219 | declare global {
220 | var GLOBAL_CONFIG: {
221 | apiUrl: string;
222 | version: string;
223 | features: string[];
224 | };
225 | }
226 |
227 | // Ambient module declaration
228 | declare module "fictional-library" {
229 | export interface Config {
230 | apiKey: string;
231 | endpoint: string;
232 | }
233 |
234 | export class Client {
235 | constructor(config: Config);
236 | request(path: string): Promise<any>;
237 | }
238 |
239 | export function initialize(config: Config): Client;
240 | }
241 |
242 | // Declare a module with wildcard
243 | declare module "*.json" {
244 | const value: any;
245 | export default value;
246 | }
247 |
248 | declare module "*.svg" {
249 | const content: string;
250 | export default content;
251 | }
252 |
253 | // ========== Conditional Exports ==========
254 | export interface DatabaseConnection {
255 | connect(): Promise<void>;
256 | disconnect(): Promise<void>;
257 | query(sql: string): Promise<any[]>;
258 | }
259 |
260 | // Different implementations based on environment
261 | const isDevelopment = process.env.NODE_ENV === 'development';
262 |
263 | export const createDatabaseConnection = (): DatabaseConnection => {
264 | if (isDevelopment) {
265 | return new MockDatabaseConnection();
266 | } else {
267 | return new ProductionDatabaseConnection();
268 | }
269 | };
270 |
271 | class MockDatabaseConnection implements DatabaseConnection {
272 | async connect(): Promise<void> {
273 | console.log("Connected to mock database");
274 | }
275 |
276 | async disconnect(): Promise<void> {
277 | console.log("Disconnected from mock database");
278 | }
279 |
280 | async query(sql: string): Promise<any[]> {
281 | console.log(`Mock query: ${sql}`);
282 | return [{ id: 1, name: "Mock Data" }];
283 | }
284 | }
285 |
286 | class ProductionDatabaseConnection implements DatabaseConnection {
287 | async connect(): Promise<void> {
288 | console.log("Connected to production database");
289 | }
290 |
291 | async disconnect(): Promise<void> {
292 | console.log("Disconnected from production database");
293 | }
294 |
295 | async query(sql: string): Promise<any[]> {
296 | console.log(`Production query: ${sql}`);
297 | // Would connect to real database
298 | return [];
299 | }
300 | }
301 |
302 | // ========== Dynamic Imports ==========
303 | export async function loadModule(moduleName: string): Promise<any> {
304 | try {
305 | switch (moduleName) {
306 | case 'math':
307 | return await import('./functions-generics');
308 | case 'classes':
309 | return await import('./classes-inheritance');
310 | case 'types':
311 | return await import('./types-interfaces');
312 | default:
313 | throw new Error(`Module ${moduleName} not found`);
314 | }
315 | } catch (error) {
316 | console.error(`Failed to load module ${moduleName}:`, error);
317 | throw error;
318 | }
319 | }
320 |
321 | // Dynamic import with type assertion
322 | export async function loadTypedModule<T>(): Promise<T> {
323 | const module = await import('./types-interfaces');
324 | return module as T;
325 | }
326 |
327 | // ========== Module Factory Pattern ==========
328 | export interface ModuleConfig {
329 | name: string;
330 | version: string;
331 | dependencies?: string[];
332 | }
333 |
334 | export abstract class BaseModule {
335 | constructor(protected config: ModuleConfig) {}
336 |
337 | abstract initialize(): Promise<void>;
338 | abstract cleanup(): Promise<void>;
339 |
340 | getConfig(): ModuleConfig {
341 | return this.config;
342 | }
343 | }
344 |
345 | export class FeatureModule extends BaseModule {
346 | private isInitialized = false;
347 |
348 | async initialize(): Promise<void> {
349 | console.log(`Initializing ${this.config.name} v${this.config.version}`);
350 |
351 | if (this.config.dependencies) {
352 | for (const dep of this.config.dependencies) {
353 | await this.loadDependency(dep);
354 | }
355 | }
356 |
357 | this.isInitialized = true;
358 | }
359 |
360 | async cleanup(): Promise<void> {
361 | console.log(`Cleaning up ${this.config.name}`);
362 | this.isInitialized = false;
363 | }
364 |
365 | private async loadDependency(name: string): Promise<void> {
366 | console.log(`Loading dependency: ${name}`);
367 | // Simulate loading dependency
368 | await new Promise(resolve => setTimeout(resolve, 100));
369 | }
370 |
371 | isReady(): boolean {
372 | return this.isInitialized;
373 | }
374 | }
375 |
376 | // ========== Barrel Exports ==========
377 | // This file can serve as a barrel export for the entire project
378 | export {
379 | // Re-export all from other modules to create a single entry point
380 | createUser,
381 | greet,
382 | sum
383 | } from './functions-generics';
384 |
385 | export {
386 | EventEmitter,
387 | PromisePool,
388 | AsyncCache
389 | } from './async-promises';
390 |
391 | // ========== Triple-Slash Directives ==========
392 | /// <reference types="node" />
393 | /// <reference lib="es2020" />
394 |
395 | // ========== Usage Examples ==========
396 | export const moduleExamples = {
397 | // Math utilities
398 | vector2D: new MathUtils.Vector2D(3, 4),
399 | vector3D: new MathUtils.Vector3D(1, 2, 3),
400 | distance: MathUtils.distance2D({ x: 0, y: 0 }, { x: 3, y: 4 }),
401 |
402 | // Data structures
403 | binaryTree: new DataStructures.Trees.BinaryTree<number>(),
404 | graph: new DataStructures.Graphs.Graph<string>(),
405 |
406 | // String extensions (using global augmentation)
407 | titleCase: "hello world".toTitleCase(),
408 | truncated: "This is a very long string".truncate(10),
409 |
410 | // Array extensions
411 | chunked: [1, 2, 3, 4, 5, 6].chunk(2),
412 | uniqueArray: [1, 2, 2, 3, 3, 3].unique(),
413 |
414 | // Module factory
415 | featureModule: new FeatureModule({
416 | name: "SampleFeature",
417 | version: "1.0.0",
418 | dependencies: ["core", "utils"]
419 | }),
420 |
421 | // Database connection
422 | dbConnection: createDatabaseConnection()
423 | };
424 |
425 | // Initialize examples
426 | moduleExamples.binaryTree.insert(5);
427 | moduleExamples.binaryTree.insert(3);
428 | moduleExamples.binaryTree.insert(7);
429 |
430 | moduleExamples.graph.addVertex("A");
431 | moduleExamples.graph.addVertex("B");
432 | moduleExamples.graph.addEdge("A", "B");
433 |
434 | // Constants from nested namespace
435 | export const mathConstants = {
436 | goldenRatio: MathUtils.Constants.GOLDEN_RATIO,
437 | eulerConstant: MathUtils.Constants.EULER_CONSTANT,
438 | sqrt2: MathUtils.Constants.SQRT_2
439 | };
440 |
441 | // ========== Module Types ==========
442 | export type ModuleLoader = (name: string) => Promise<any>;
443 | export type ModuleRegistry = Map<string, BaseModule>;
444 |
445 | export interface ModuleSystem {
446 | register(name: string, module: BaseModule): void;
447 | unregister(name: string): void;
448 | get(name: string): BaseModule | undefined;
449 | has(name: string): boolean;
450 | initialize(): Promise<void>;
451 | shutdown(): Promise<void>;
452 | }
```
--------------------------------------------------------------------------------
/docs/site/assets/javascripts/lunr/min/lunr.es.min.js:
--------------------------------------------------------------------------------
```javascript
1 | /*!
2 | * Lunr languages, `Spanish` language
3 | * https://github.com/MihaiValentin/lunr-languages
4 | *
5 | * Copyright 2014, Mihai Valentin
6 | * http://www.mozilla.org/MPL/
7 | */
8 | /*!
9 | * based on
10 | * Snowball JavaScript Library v0.3
11 | * http://code.google.com/p/urim/
12 | * http://snowball.tartarus.org/
13 | *
14 | * Copyright 2010, Oleg Mazko
15 | * http://www.mozilla.org/MPL/
16 | */
17 |
18 | !function(e,s){"function"==typeof define&&define.amd?define(s):"object"==typeof exports?module.exports=s():s()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.es=function(){this.pipeline.reset(),this.pipeline.add(e.es.trimmer,e.es.stopWordFilter,e.es.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.es.stemmer))},e.es.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.es.trimmer=e.trimmerSupport.generateTrimmer(e.es.wordCharacters),e.Pipeline.registerFunction(e.es.trimmer,"trimmer-es"),e.es.stemmer=function(){var s=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,n=new function(){function e(){if(A.out_grouping(x,97,252)){for(;!A.in_grouping(x,97,252);){if(A.cursor>=A.limit)return!0;A.cursor++}return!1}return!0}function n(){if(A.in_grouping(x,97,252)){var s=A.cursor;if(e()){if(A.cursor=s,!A.in_grouping(x,97,252))return!0;for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!0;A.cursor++}}return!1}return!0}function i(){var s,r=A.cursor;if(n()){if(A.cursor=r,!A.out_grouping(x,97,252))return;if(s=A.cursor,e()){if(A.cursor=s,!A.in_grouping(x,97,252)||A.cursor>=A.limit)return;A.cursor++}}g=A.cursor}function a(){for(;!A.in_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}return!0}function t(){var e=A.cursor;g=A.limit,p=g,v=g,i(),A.cursor=e,a()&&(p=A.cursor,a()&&(v=A.cursor))}function o(){for(var e;;){if(A.bra=A.cursor,e=A.find_among(k,6))switch(A.ket=A.cursor,e){case 1:A.slice_from("a");continue;case 2:A.slice_from("e");continue;case 3:A.slice_from("i");continue;case 4:A.slice_from("o");continue;case 5:A.slice_from("u");continue;case 6:if(A.cursor>=A.limit)break;A.cursor++;continue}break}}function u(){return g<=A.cursor}function w(){return p<=A.cursor}function c(){return v<=A.cursor}function m(){var e;if(A.ket=A.cursor,A.find_among_b(y,13)&&(A.bra=A.cursor,(e=A.find_among_b(q,11))&&u()))switch(e){case 1:A.bra=A.cursor,A.slice_from("iendo");break;case 2:A.bra=A.cursor,A.slice_from("ando");break;case 3:A.bra=A.cursor,A.slice_from("ar");break;case 4:A.bra=A.cursor,A.slice_from("er");break;case 5:A.bra=A.cursor,A.slice_from("ir");break;case 6:A.slice_del();break;case 7:A.eq_s_b(1,"u")&&A.slice_del()}}function l(e,s){if(!c())return!0;A.slice_del(),A.ket=A.cursor;var r=A.find_among_b(e,s);return r&&(A.bra=A.cursor,1==r&&c()&&A.slice_del()),!1}function d(e){return!c()||(A.slice_del(),A.ket=A.cursor,A.eq_s_b(2,e)&&(A.bra=A.cursor,c()&&A.slice_del()),!1)}function b(){var e;if(A.ket=A.cursor,e=A.find_among_b(S,46)){switch(A.bra=A.cursor,e){case 1:if(!c())return!1;A.slice_del();break;case 2:if(d("ic"))return!1;break;case 3:if(!c())return!1;A.slice_from("log");break;case 4:if(!c())return!1;A.slice_from("u");break;case 5:if(!c())return!1;A.slice_from("ente");break;case 6:if(!w())return!1;A.slice_del(),A.ket=A.cursor,e=A.find_among_b(C,4),e&&(A.bra=A.cursor,c()&&(A.slice_del(),1==e&&(A.ket=A.cursor,A.eq_s_b(2,"at")&&(A.bra=A.cursor,c()&&A.slice_del()))));break;case 7:if(l(P,3))return!1;break;case 8:if(l(F,3))return!1;break;case 9:if(d("at"))return!1}return!0}return!1}function f(){var e,s;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(W,12),A.limit_backward=s,e)){if(A.bra=A.cursor,1==e){if(!A.eq_s_b(1,"u"))return!1;A.slice_del()}return!0}return!1}function _(){var e,s,r,n;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(L,96),A.limit_backward=s,e))switch(A.bra=A.cursor,e){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"u")?(n=A.limit-A.cursor,A.eq_s_b(1,"g")?A.cursor=A.limit-n:A.cursor=A.limit-r):A.cursor=A.limit-r,A.bra=A.cursor;case 2:A.slice_del()}}function h(){var e,s;if(A.ket=A.cursor,e=A.find_among_b(z,8))switch(A.bra=A.cursor,e){case 1:u()&&A.slice_del();break;case 2:u()&&(A.slice_del(),A.ket=A.cursor,A.eq_s_b(1,"u")&&(A.bra=A.cursor,s=A.limit-A.cursor,A.eq_s_b(1,"g")&&(A.cursor=A.limit-s,u()&&A.slice_del())))}}var v,p,g,k=[new s("",-1,6),new s("á",0,1),new s("é",0,2),new s("í",0,3),new s("ó",0,4),new s("ú",0,5)],y=[new s("la",-1,-1),new s("sela",0,-1),new s("le",-1,-1),new s("me",-1,-1),new s("se",-1,-1),new s("lo",-1,-1),new s("selo",5,-1),new s("las",-1,-1),new s("selas",7,-1),new s("les",-1,-1),new s("los",-1,-1),new s("selos",10,-1),new s("nos",-1,-1)],q=[new s("ando",-1,6),new s("iendo",-1,6),new s("yendo",-1,7),new s("ándo",-1,2),new s("iéndo",-1,1),new s("ar",-1,6),new s("er",-1,6),new s("ir",-1,6),new s("ár",-1,3),new s("ér",-1,4),new s("ír",-1,5)],C=[new s("ic",-1,-1),new s("ad",-1,-1),new s("os",-1,-1),new s("iv",-1,1)],P=[new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,1)],F=[new s("ic",-1,1),new s("abil",-1,1),new s("iv",-1,1)],S=[new s("ica",-1,1),new s("ancia",-1,2),new s("encia",-1,5),new s("adora",-1,2),new s("osa",-1,1),new s("ista",-1,1),new s("iva",-1,9),new s("anza",-1,1),new s("logía",-1,3),new s("idad",-1,8),new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,2),new s("mente",-1,7),new s("amente",13,6),new s("ación",-1,2),new s("ución",-1,4),new s("ico",-1,1),new s("ismo",-1,1),new s("oso",-1,1),new s("amiento",-1,1),new s("imiento",-1,1),new s("ivo",-1,9),new s("ador",-1,2),new s("icas",-1,1),new s("ancias",-1,2),new s("encias",-1,5),new s("adoras",-1,2),new s("osas",-1,1),new s("istas",-1,1),new s("ivas",-1,9),new s("anzas",-1,1),new s("logías",-1,3),new s("idades",-1,8),new s("ables",-1,1),new s("ibles",-1,1),new s("aciones",-1,2),new s("uciones",-1,4),new s("adores",-1,2),new s("antes",-1,2),new s("icos",-1,1),new s("ismos",-1,1),new s("osos",-1,1),new s("amientos",-1,1),new s("imientos",-1,1),new s("ivos",-1,9)],W=[new s("ya",-1,1),new s("ye",-1,1),new s("yan",-1,1),new s("yen",-1,1),new s("yeron",-1,1),new s("yendo",-1,1),new s("yo",-1,1),new s("yas",-1,1),new s("yes",-1,1),new s("yais",-1,1),new s("yamos",-1,1),new s("yó",-1,1)],L=[new s("aba",-1,2),new s("ada",-1,2),new s("ida",-1,2),new s("ara",-1,2),new s("iera",-1,2),new s("ía",-1,2),new s("aría",5,2),new s("ería",5,2),new s("iría",5,2),new s("ad",-1,2),new s("ed",-1,2),new s("id",-1,2),new s("ase",-1,2),new s("iese",-1,2),new s("aste",-1,2),new s("iste",-1,2),new s("an",-1,2),new s("aban",16,2),new s("aran",16,2),new s("ieran",16,2),new s("ían",16,2),new s("arían",20,2),new s("erían",20,2),new s("irían",20,2),new s("en",-1,1),new s("asen",24,2),new s("iesen",24,2),new s("aron",-1,2),new s("ieron",-1,2),new s("arán",-1,2),new s("erán",-1,2),new s("irán",-1,2),new s("ado",-1,2),new s("ido",-1,2),new s("ando",-1,2),new s("iendo",-1,2),new s("ar",-1,2),new s("er",-1,2),new s("ir",-1,2),new s("as",-1,2),new s("abas",39,2),new s("adas",39,2),new s("idas",39,2),new s("aras",39,2),new s("ieras",39,2),new s("ías",39,2),new s("arías",45,2),new s("erías",45,2),new s("irías",45,2),new s("es",-1,1),new s("ases",49,2),new s("ieses",49,2),new s("abais",-1,2),new s("arais",-1,2),new s("ierais",-1,2),new s("íais",-1,2),new s("aríais",55,2),new s("eríais",55,2),new s("iríais",55,2),new s("aseis",-1,2),new s("ieseis",-1,2),new s("asteis",-1,2),new s("isteis",-1,2),new s("áis",-1,2),new s("éis",-1,1),new s("aréis",64,2),new s("eréis",64,2),new s("iréis",64,2),new s("ados",-1,2),new s("idos",-1,2),new s("amos",-1,2),new s("ábamos",70,2),new s("áramos",70,2),new s("iéramos",70,2),new s("íamos",70,2),new s("aríamos",74,2),new s("eríamos",74,2),new s("iríamos",74,2),new s("emos",-1,1),new s("aremos",78,2),new s("eremos",78,2),new s("iremos",78,2),new s("ásemos",78,2),new s("iésemos",78,2),new s("imos",-1,2),new s("arás",-1,2),new s("erás",-1,2),new s("irás",-1,2),new s("ís",-1,2),new s("ará",-1,2),new s("erá",-1,2),new s("irá",-1,2),new s("aré",-1,2),new s("eré",-1,2),new s("iré",-1,2),new s("ió",-1,2)],z=[new s("a",-1,1),new s("e",-1,2),new s("o",-1,1),new s("os",-1,1),new s("á",-1,1),new s("é",-1,2),new s("í",-1,1),new s("ó",-1,1)],x=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,4,10],A=new r;this.setCurrent=function(e){A.setCurrent(e)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return t(),A.limit_backward=e,A.cursor=A.limit,m(),A.cursor=A.limit,b()||(A.cursor=A.limit,f()||(A.cursor=A.limit,_())),A.cursor=A.limit,h(),A.cursor=A.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.es.stemmer,"stemmer-es"),e.es.stopWordFilter=e.generateStopWordFilter("a al algo algunas algunos ante antes como con contra cual cuando de del desde donde durante e el ella ellas ellos en entre era erais eran eras eres es esa esas ese eso esos esta estaba estabais estaban estabas estad estada estadas estado estados estamos estando estar estaremos estará estarán estarás estaré estaréis estaría estaríais estaríamos estarían estarías estas este estemos esto estos estoy estuve estuviera estuvierais estuvieran estuvieras estuvieron estuviese estuvieseis estuviesen estuvieses estuvimos estuviste estuvisteis estuviéramos estuviésemos estuvo está estábamos estáis están estás esté estéis estén estés fue fuera fuerais fueran fueras fueron fuese fueseis fuesen fueses fui fuimos fuiste fuisteis fuéramos fuésemos ha habida habidas habido habidos habiendo habremos habrá habrán habrás habré habréis habría habríais habríamos habrían habrías habéis había habíais habíamos habían habías han has hasta hay haya hayamos hayan hayas hayáis he hemos hube hubiera hubierais hubieran hubieras hubieron hubiese hubieseis hubiesen hubieses hubimos hubiste hubisteis hubiéramos hubiésemos hubo la las le les lo los me mi mis mucho muchos muy más mí mía mías mío míos nada ni no nos nosotras nosotros nuestra nuestras nuestro nuestros o os otra otras otro otros para pero poco por porque que quien quienes qué se sea seamos sean seas seremos será serán serás seré seréis sería seríais seríamos serían serías seáis sido siendo sin sobre sois somos son soy su sus suya suyas suyo suyos sí también tanto te tendremos tendrá tendrán tendrás tendré tendréis tendría tendríais tendríamos tendrían tendrías tened tenemos tenga tengamos tengan tengas tengo tengáis tenida tenidas tenido tenidos teniendo tenéis tenía teníais teníamos tenían tenías ti tiene tienen tienes todo todos tu tus tuve tuviera tuvierais tuvieran tuvieras tuvieron tuviese tuvieseis tuviesen tuvieses tuvimos tuviste tuvisteis tuviéramos tuviésemos tuvo tuya tuyas tuyo tuyos tú un una uno unos vosotras vosotros vuestra vuestras vuestro vuestros y ya yo él éramos".split(" ")),e.Pipeline.registerFunction(e.es.stopWordFilter,"stopWordFilter-es")}});
```
--------------------------------------------------------------------------------
/website/src/components/Footer.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import { Button } from "@/components/ui/button";
2 | import { Github, ExternalLink, Mail, MapPin, Phone } from "lucide-react";
3 | import { useEffect, useState } from "react";
4 | import { toast } from "sonner";
5 | import { createClient } from "@supabase/supabase-js";
6 | import { FaGithub, FaDiscord } from "react-icons/fa";
7 | import { SiPypi } from "react-icons/si";
8 | import { FiBookOpen } from "react-icons/fi";
9 |
10 | // Only create Supabase client if environment variables are set
11 | const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
12 | const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
13 | const supabase =
14 | supabaseUrl && supabaseAnonKey
15 | ? createClient(supabaseUrl, supabaseAnonKey)
16 | : null;
17 |
18 | const Footer = () => {
19 | const [email, setEmail] = useState("");
20 | const [isLoading, setIsLoading] = useState(false);
21 | const [version, setVersion] = useState("");
22 | useEffect(() => {
23 | async function fetchVersion() {
24 | try {
25 | const res = await fetch(
26 | "https://raw.githubusercontent.com/Shashankss1205/CodeGraphContext/main/README.md"
27 | );
28 | if (!res.ok) throw new Error("Failed to fetch README");
29 |
30 | const text = await res.text();
31 | const match = text.match(
32 | /\*\*Version:\*\*\s*([0-9]+\.[0-9]+\.[0-9]+)/i
33 | );
34 | setVersion(match ? match[1] : "N/A");
35 | } catch (err) {
36 | console.error(err);
37 | setVersion("N/A");
38 | }
39 | }
40 |
41 | fetchVersion();
42 | }, []);
43 | const handleNewsletterSubmit = async (e: React.FormEvent) => {
44 | e.preventDefault();
45 |
46 | if (!email) {
47 | toast.error("Please enter your email address");
48 | return;
49 | }
50 |
51 | if (!/\S+@\S+\.\S+/.test(email)) {
52 | toast.error("Please enter a valid email address");
53 | return;
54 | }
55 |
56 | // Check if Supabase is configured
57 | if (!supabase) {
58 | toast.error(
59 | "Newsletter subscription is currently unavailable. Please try again later."
60 | );
61 | return;
62 | }
63 |
64 | setIsLoading(true);
65 |
66 | try {
67 | const { data, error } = await supabase
68 | .from("subscribers")
69 | .insert([{ email }]);
70 |
71 | if (error) {
72 | if (error.code === "23505") {
73 | // Duplicate email
74 | toast("You are already subscribed!");
75 | } else {
76 | toast.error(error.message);
77 | }
78 | } else {
79 | toast.success("Thank you for subscribing to our newsletter!");
80 | setEmail("");
81 | }
82 | } catch (err) {
83 | console.error(err);
84 | toast.error("Failed to subscribe. Please try again later.");
85 | } finally {
86 | setIsLoading(false);
87 | }
88 | };
89 |
90 | return (
91 | <footer className="border-t border-border/50 py-16 px-6 bg-muted/10" data-aos="fade-up">
92 | <div className="container mx-auto max-w-7xl">
93 | {/* Top Section */}
94 | <div className="flex flex-col lg:flex-row justify-between gap-12">
95 | {/* Left Side: Brand + Resources (closer together) */}
96 | <div className="flex-1 flex flex-col sm:flex-row gap-12">
97 | {/* Brand */}
98 | <div className="flex-1">
99 | <h3 className="text-2xl font-bold bg-gradient-primary bg-clip-text text-transparent mb-4">
100 | CodeGraphContext
101 | </h3>
102 | <p className="text-muted-foreground mb-6 leading-relaxed max-w-sm">
103 | Transform your codebase into an intelligent knowledge graph for
104 | AI assistants.
105 | </p>
106 | <div className="flex gap-3 flex-wrap">
107 | <Button
108 | variant="outline"
109 | size="sm"
110 | asChild
111 | className="social-btn social-github social-float"
112 | >
113 | <a
114 | href="https://github.com/Shashankss1205/CodeGraphContext"
115 | target="_blank"
116 | rel="noopener noreferrer"
117 | className="flex items-center"
118 | >
119 | <FaGithub
120 | className="h-4 w-4 mr-2"
121 | style={{ color: "#9CA3AF" }}
122 | />
123 | <span>GitHub</span>
124 | </a>
125 | </Button>
126 |
127 | <Button
128 | variant="outline"
129 | size="sm"
130 | asChild
131 | className="social-btn social-discord social-float"
132 | >
133 | <a
134 | href="https://discord.com/invite/dR4QY32uYQ"
135 | target="_blank"
136 | rel="noopener noreferrer"
137 | className="flex items-center"
138 | >
139 | <FaDiscord
140 | className="h-4 w-4 mr-2"
141 | style={{ color: "#5865F2" }}
142 | />
143 | <span>Discord</span>
144 | </a>
145 | </Button>
146 |
147 | <Button
148 | variant="outline"
149 | size="sm"
150 | asChild
151 | className="social-btn social-pypi social-float"
152 | >
153 | <a
154 | href="https://pypi.org/project/codegraphcontext/"
155 | target="_blank"
156 | rel="noopener noreferrer"
157 | className="flex items-center"
158 | >
159 | <SiPypi
160 | className="h-4 w-4 mr-2"
161 | style={{ color: "#EAB308" }}
162 | />
163 | <span>PyPI</span>
164 | </a>
165 | </Button>
166 |
167 | <Button
168 | variant="outline"
169 | size="sm"
170 | asChild
171 | className="social-btn social-docs social-float"
172 | >
173 | <a
174 | href="https://shashankss1205.github.io/CodeGraphContext/"
175 | target="_blank"
176 | rel="noopener noreferrer"
177 | className="flex items-center"
178 | >
179 | <FiBookOpen
180 | className="h-4 w-4 mr-2"
181 | style={{ color: "#6366F1" }}
182 | />
183 | <span>Documentation</span>
184 | </a>
185 | </Button>
186 | </div>
187 | </div>
188 |
189 | {/* Resources */}
190 | <div className="w-48">
191 | <h4 className="font-semibold mb-4">Resources</h4>
192 | <ul className="space-y-3 text-muted-foreground">
193 | <li>
194 | <a
195 | href="https://shashankss1205.github.io/CodeGraphContext/"
196 | className="hover:text-foreground transition-smooth"
197 | target="_blank"
198 | rel="noopener noreferrer"
199 | >
200 | Documentation
201 | </a>
202 | </li>
203 | <li>
204 | <a
205 | href="https://github.com/Shashankss1205/CodeGraphContext/blob/main/docs/cookbook.md"
206 | className="hover:text-foreground transition-smooth"
207 | >
208 | Cookbook
209 | </a>
210 | </li>
211 | <li>
212 | <a
213 | href="https://github.com/Shashankss1205/CodeGraphContext/blob/main/CONTRIBUTING.md"
214 | className="hover:text-foreground transition-smooth"
215 | >
216 | Contributing
217 | </a>
218 | </li>
219 | <li>
220 | <a
221 | href="https://github.com/Shashankss1205/CodeGraphContext/issues"
222 | className="hover:text-foreground transition-smooth"
223 | >
224 | Issues
225 | </a>
226 | </li>
227 | </ul>
228 | </div>
229 | </div>
230 |
231 | {/* Right Side: Contact + Newsletter */}
232 | <div className="flex-1 flex flex-col sm:flex-row gap-12">
233 | {/* Contact */}
234 | <div className="w-56">
235 | <h4 className="font-semibold mb-4">Contact</h4>
236 | <div className="space-y-5 text-muted-foreground">
237 | <div className="flex items-start gap-3">
238 | <Mail className="h-5 w-5 mt-1 text-primary" />
239 | <a
240 | href="mailto:[email protected]"
241 | className="hover:text-foreground transition-smooth text-sm break-all"
242 | >
243 | [email protected]
244 | </a>
245 | </div>
246 | {/* <div className="flex items-start gap-3">
247 | <Phone className="h-5 w-5 mt-1 text-primary" />
248 | <a
249 | href="tel:+911234567890"
250 | className="hover:text-foreground transition-smooth text-sm"
251 | >
252 | +91 12345 67890
253 | </a>
254 | </div> */}
255 | <div className="flex items-start gap-3">
256 | <MapPin className="h-5 w-5 mt-1 text-primary" />
257 | <p className="text-sm">(Available Worldwide 🌍)</p>
258 | </div>
259 | <div>
260 | <p className="font-medium text-foreground">
261 | Shashank Shekhar Singh
262 | </p>
263 | <p className="text-sm">Creator & Maintainer</p>
264 | </div>
265 | </div>
266 | </div>
267 |
268 | {/* Newsletter */}
269 | <div className="flex-1">
270 | <h4 className="font-semibold mb-4">Newsletter</h4>
271 | <p className="text-muted-foreground mb-4 text-sm leading-relaxed">
272 | Stay updated with the latest features, releases, and code
273 | intelligence insights.
274 | </p>
275 | <form onSubmit={handleNewsletterSubmit} className="space-y-3">
276 | <div className="flex flex-col sm:flex-row gap-2">
277 | <input
278 | type="email"
279 | placeholder="Enter your email"
280 | value={email}
281 | onChange={(e) => setEmail(e.target.value)}
282 | disabled={isLoading}
283 | className="flex-1 px-3 py-2 text-sm border border-border rounded-md bg-background focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-smooth disabled:opacity-50"
284 | required
285 | />
286 | <Button
287 | type="submit"
288 | size="sm"
289 | disabled={isLoading}
290 | className="whitespace-nowrap"
291 | >
292 | {isLoading ? "Subscribing..." : "Subscribe"}
293 | </Button>
294 | </div>
295 | <p className="text-xs text-muted-foreground">
296 | No spam. Unsubscribe at any time.
297 | </p>
298 | </form>
299 | </div>
300 | </div>
301 | </div>
302 |
303 | {/* Bottom Bar */}
304 | <div className="border-t border-border/50 mt-12 pt-8 flex flex-col md:flex-row justify-between items-center gap-4">
305 | <p className="text-muted-foreground text-sm">
306 | © 2025 CodeGraphContext. Released under the MIT License.
307 | </p>
308 | <div className="flex items-center gap-4 text-sm text-muted-foreground">
309 | <span>Version {version}</span>
310 | <div className="w-1 h-1 bg-muted-foreground rounded-full" />
311 | <span>Python 3.8+</span>
312 | <div className="w-1 h-1 bg-muted-foreground rounded-full" />
313 | <span>Neo4j 5.15+</span>
314 | </div>
315 | </div>
316 | </div>
317 | </footer>
318 | );
319 | };
320 |
321 | export default Footer;
322 |
323 |
```
--------------------------------------------------------------------------------
/website/src/components/ComparisonTable.tsx:
--------------------------------------------------------------------------------
```typescript
1 | "use client";
2 |
3 | import { Card, CardContent } from "@/components/ui/card";
4 | import { Badge } from "@/components/ui/badge";
5 | import { motion } from "framer-motion";
6 | import { useInView } from "framer-motion";
7 | import { useRef } from "react";
8 |
9 | const tableData = [
10 | {
11 | feature: "Code Completion",
12 | copilot: { text: "Strong", status: "good" },
13 | cursor: { text: "Strong", status: "good" },
14 | cgc: { text: "Strong", status: "good" },
15 | },
16 | {
17 | feature: "Refactoring Suggestions",
18 | copilot: { text: "Limited to context length", status: "warning" },
19 | cursor: { text: "Limited to context length", status: "warning" },
20 | cgc: { text: "Via dependency tracing", status: "good" },
21 | },
22 | {
23 | feature: "Codebase Understanding",
24 | copilot: { text: "Limited", status: "bad" },
25 | cursor: { text: "Partial (local context)", status: "warning" },
26 | cgc: { text: "Deep graph-based", status: "good" },
27 | },
28 | {
29 | feature: "Call Graph & Imports",
30 | copilot: { text: "No", status: "bad" },
31 | cursor: { text: "No", status: "bad" },
32 | cgc: { text: "Direct + Multi-hops", status: "good" },
33 | },
34 | {
35 | feature: "Cross-File Tracing",
36 | copilot: { text: "Very low", status: "bad" },
37 | cursor: { text: "Some", status: "warning" },
38 | cgc: { text: "Complete code", status: "good" },
39 | },
40 | {
41 | feature: "LLM Explainability",
42 | copilot: { text: "Low", status: "bad" },
43 | cursor: { text: "Hallucinate", status: "warning" },
44 | cgc: { text: "Extremely good", status: "good" },
45 | },
46 | {
47 | feature: "Performance on Large Codebases",
48 | copilot: { text: "Slows with size", status: "bad" },
49 | cursor: { text: "Slows with size", status: "bad" },
50 | cgc: { text: "Scales with graph DB", status: "good" },
51 | },
52 | {
53 | feature: "Extensible to Multiple Languages",
54 | copilot: { text: "Strong", status: "good" },
55 | cursor: { text: "Strong", status: "good" },
56 | cgc: { text: "Work-in-progress", status: "warning" },
57 | },
58 | {
59 | feature: "Set-up Time for new code",
60 | copilot: { text: "Low", status: "good" },
61 | cursor: { text: "Slows with size", status: "bad" },
62 | cgc: { text: "Slows with size", status: "bad" },
63 | },
64 | ];
65 |
66 | const StatusBadge = ({ status, text }: { status: string; text: string }) => {
67 | const getStatusStyles = () => {
68 | switch (status) {
69 | case "good":
70 | return "bg-emerald-100 text-emerald-700 border border-emerald-300 shadow-sm dark:bg-emerald-500/20 dark:text-emerald-300 dark:border-emerald-500/40 dark:shadow-lg dark:shadow-emerald-500/10";
71 | case "warning":
72 | return "bg-amber-100 text-amber-700 border border-amber-300 shadow-sm dark:bg-amber-500/20 dark:text-amber-300 dark:border-amber-500/40 dark:shadow-lg dark:shadow-amber-500/10";
73 | case "bad":
74 | return "bg-red-100 text-red-700 border border-red-300 shadow-sm dark:bg-red-500/20 dark:text-red-300 dark:border-red-500/40 dark:shadow-lg dark:shadow-red-500/10";
75 | default:
76 | return "bg-gray-200 text-gray-700 border border-gray-300 dark:bg-secondary/50 dark:text-muted-foreground";
77 | }
78 | };
79 |
80 | const getIcon = () => {
81 | switch (status) {
82 | case "good":
83 | return "✓";
84 | case "warning":
85 | return "⚠";
86 | case "bad":
87 | return "✕";
88 | default:
89 | return "";
90 | }
91 | };
92 |
93 | return (
94 | <motion.div
95 | whileHover={{ scale: 1.05 }}
96 | whileTap={{ scale: 0.95 }}
97 | transition={{ type: "spring", stiffness: 400, damping: 17 }}
98 | >
99 | <Badge
100 | className={`
101 | ${getStatusStyles()}
102 | border-2 font-medium text-[0.55rem] sm:text-[0.65rem] px-2 sm:px-3 py-1
103 | backdrop-blur-sm relative overflow-hidden
104 | transition-all duration-300 hover:shadow-xl
105 | `}
106 | >
107 | <motion.div
108 | className="absolute inset-0 bg-gradient-to-r from-white/10 to-transparent"
109 | initial={{ x: "-100%" }}
110 | whileHover={{ x: "100%" }}
111 | transition={{ duration: 0.6 }}
112 | />
113 | <span className="mr-1 sm:mr-2 font-bold">{getIcon()}</span>
114 | <span className="relative z-10">{text}</span>
115 | </Badge>
116 | </motion.div>
117 | );
118 | };
119 |
120 | const AnimatedCard = ({
121 | children,
122 | delay = 0,
123 | }: {
124 | children: React.ReactNode;
125 | delay?: number;
126 | }) => {
127 | const ref = useRef(null);
128 | const isInView = useInView(ref, { once: true, margin: "-50px" });
129 |
130 | return (
131 | <motion.div
132 | ref={ref}
133 | initial={{ opacity: 0, y: 50 }}
134 | animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 50 }}
135 | transition={{ duration: 0.6, delay, ease: "easeOut" }}
136 | >
137 | {children}
138 | </motion.div>
139 | );
140 | };
141 |
142 | const FloatingBackground = () => (
143 | <div className="absolute inset-0 overflow-hidden pointer-events-none">
144 | <motion.div
145 | className="absolute -top-40 -right-40 w-80 h-80 bg-primary/5 rounded-full blur-3xl"
146 | animate={{ x: [0, 30, 0], y: [0, -40, 0] }}
147 | transition={{ duration: 20, repeat: Infinity, ease: "easeInOut" }}
148 | />
149 | <motion.div
150 | className="absolute -bottom-40 -left-40 w-80 h-80 bg-accent/5 rounded-full blur-3xl"
151 | animate={{ x: [0, -30, 0], y: [0, 40, 0] }}
152 | transition={{ duration: 25, repeat: Infinity, ease: "easeInOut", delay: 2 }}
153 | />
154 | </div>
155 | );
156 |
157 | export default function ComparisonTable() {
158 | const containerRef = useRef(null);
159 | const isInView = useInView(containerRef, { once: true, margin: "-100px" });
160 |
161 | return (
162 | <section
163 | ref={containerRef}
164 | className="relative min-h-screen flex items-center justify-center bg-gradient-to-br from-background via-background to-secondary/5 overflow-hidden"
165 | style={{ maxWidth: "100vw", overflow: "hidden", padding: "2rem 1rem" }}
166 | data-aos="zoom-in"
167 | >
168 | <FloatingBackground />
169 |
170 | <div className="container mx-auto max-w-7xl relative z-10">
171 | <AnimatedCard delay={0.1}>
172 | <div className="text-center mb-16">
173 | <motion.h2
174 | className="text-2xl sm:text-4xl md:text-5xl font-bold mb-6 pb-4 bg-gradient-to-r from-primary via-primary/90 to-accent bg-clip-text text-transparent"
175 | initial={{ opacity: 0, y: 30 }}
176 | animate={isInView ? { opacity: 1, y: 0 } : {}}
177 | transition={{ duration: 0.8, delay: 0.2 }}
178 | >
179 | Why CodeGraphContext?
180 | </motion.h2>
181 | <motion.p
182 | className="text-lg text-muted-foreground max-w-3xl mx-auto leading-relaxed"
183 | initial={{ opacity: 0, y: 20 }}
184 | animate={isInView ? { opacity: 1, y: 0 } : {}}
185 | transition={{ duration: 0.8, delay: 0.4 }}
186 | >
187 | Experience the next generation of AI-powered code understanding
188 | with graph-based intelligence
189 | </motion.p>
190 | </div>
191 | </AnimatedCard>
192 |
193 | <AnimatedCard delay={0.3}>
194 | <motion.div
195 | initial={{ opacity: 0, scale: 0.95 }}
196 | animate={isInView ? { opacity: 1, scale: 1 } : {}}
197 | transition={{ duration: 0.8, delay: 0.5 }}
198 | >
199 | {/* Scrollable table wrapper */}
200 | <div className="overflow-x-auto rounded-3xl">
201 | <table className="w-full min-w-[600px] md:min-w-full table-auto">
202 | <thead>
203 | <tr className="border-b border-border/20 bg-gradient-to-r from-secondary/10 via-secondary/5 to-secondary/10 backdrop-blur-sm">
204 | <th className="p-2 sm:p-4 text-left font-bold text-foreground text-[0.65rem] sm:text-sm">
205 | <motion.span
206 | initial={{ opacity: 0, x: -20 }}
207 | animate={isInView ? { opacity: 1, x: 0 } : {}}
208 | transition={{ duration: 0.6, delay: 0.7 }}
209 | >
210 | Feature
211 | </motion.span>
212 | </th>
213 | <th className="p-2 sm:p-4 text-center font-bold text-foreground text-[0.65rem] sm:text-sm min-w-[120px]">
214 | <motion.span
215 | initial={{ opacity: 0, y: -20 }}
216 | animate={isInView ? { opacity: 1, y: 0 } : {}}
217 | transition={{ duration: 0.6, delay: 0.8 }}
218 | >
219 | GitHub Copilot
220 | </motion.span>
221 | </th>
222 | <th className="p-2 sm:p-4 text-center font-bold text-foreground text-[0.65rem] sm:text-sm min-w-[120px]">
223 | <motion.span
224 | initial={{ opacity: 0, y: -20 }}
225 | animate={isInView ? { opacity: 1, y: 0 } : {}}
226 | transition={{ duration: 0.6, delay: 0.9 }}
227 | >
228 | Cursor
229 | </motion.span>
230 | </th>
231 | <th className="p-2 sm:p-4 text-center font-bold text-foreground text-[0.65rem] sm:text-sm min-w-[120px]">
232 | <motion.span
233 | initial={{ opacity: 0, y: -20 }}
234 | animate={isInView ? { opacity: 1, y: 0 } : {}}
235 | transition={{ duration: 0.6, delay: 1.0 }}
236 | >
237 | CodeGraphContext
238 | </motion.span>
239 | </th>
240 | </tr>
241 | </thead>
242 | <tbody>
243 | {tableData.map((row, index) => (
244 | <motion.tr
245 | key={row.feature}
246 | initial={{ opacity: 0, x: -20 }}
247 | animate={isInView ? { opacity: 1, x: 0 } : {}}
248 | transition={{
249 | duration: 0.6,
250 | delay: 0.7 + index * 0.1,
251 | }}
252 | className={`
253 | border-b border-border/10 transition-all duration-300
254 | hover:bg-primary/5 group relative overflow-hidden
255 | ${index % 2 === 0 ? "bg-background/30" : "bg-secondary/3"}
256 | `}
257 | >
258 | <td className="p-2 sm:p-4 text-foreground font-semibold text-[0.6rem] sm:text-sm text-left relative z-10">
259 | {row.feature}
260 | <motion.div
261 | className="absolute left-0 top-0 w-1 h-0 bg-gradient-to-b from-primary to-accent group-hover:h-full transition-all duration-500"
262 | initial={{ height: 0 }}
263 | whileHover={{ height: "100%" }}
264 | />
265 | </td>
266 | <td className="p-2 sm:p-4 text-center">
267 | <div className="flex justify-center">
268 | <StatusBadge status={row.copilot.status} text={row.copilot.text} />
269 | </div>
270 | </td>
271 | <td className="p-2 sm:p-4 text-center">
272 | <div className="flex justify-center">
273 | <StatusBadge status={row.cursor.status} text={row.cursor.text} />
274 | </div>
275 | </td>
276 | <td className="p-2 sm:p-4 text-center relative">
277 | <div className="flex justify-center">
278 | <StatusBadge status={row.cgc.status} text={row.cgc.text} />
279 | </div>
280 | </td>
281 | </motion.tr>
282 | ))}
283 | </tbody>
284 | </table>
285 | </div>
286 | </motion.div>
287 | </AnimatedCard>
288 |
289 | <AnimatedCard delay={0.9}>
290 | <motion.div
291 | className="text-center mt-12"
292 | initial={{ opacity: 0, y: 30 }}
293 | animate={isInView ? { opacity: 1, y: 0 } : {}}
294 | transition={{ duration: 0.8, delay: 1.5 }}
295 | >
296 | <motion.p
297 | className="text-base text-muted-foreground mb-6"
298 | initial={{ opacity: 0 }}
299 | animate={isInView ? { opacity: 1 } : {}}
300 | transition={{ duration: 0.8, delay: 1.7 }}
301 | >
302 | Experience the power of graph-based code understanding
303 | </motion.p>
304 | </motion.div>
305 | </AnimatedCard>
306 | </div>
307 | </section>
308 | );
309 | }
310 |
311 |
```
--------------------------------------------------------------------------------
/tests/sample_project_typescript/src/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | /**
2 | * Main Entry Point
3 | * Imports and demonstrates usage of all TypeScript modules in the sample project
4 | * This file serves as the primary entry point and integration test for all features
5 | */
6 |
7 | // Import all modules to demonstrate the complete TypeScript feature set
8 | import * as TypesInterfaces from './types-interfaces';
9 | import * as ClassesInheritance from './classes-inheritance';
10 | import * as FunctionsGenerics from './functions-generics';
11 | import * as AsyncPromises from './async-promises';
12 | import * as DecoratorsMetadata from './decorators-metadata';
13 | import * as ModulesNamespaces from './modules-namespaces';
14 | import * as AdvancedTypes from './advanced-types';
15 | import * as ErrorValidation from './error-validation';
16 | import * as UtilitiesHelpers from './utilities-helpers';
17 |
18 | // Import specific examples for demonstration
19 | import { User, Shape, calculateArea } from './types-interfaces';
20 | import { Person, Employee, Dog } from './classes-inheritance';
21 | import { Stack, Queue, memoize } from './functions-generics';
22 | import { EventEmitter, PromisePool } from './async-promises';
23 | import { ValidationError, Result, Ok, Err } from './error-validation';
24 | import { StringUtils, ArrayUtils, ObjectUtils } from './utilities-helpers';
25 |
26 | /**
27 | * Main application class demonstrating all TypeScript features
28 | */
29 | export class TypeScriptShowcase {
30 | private eventEmitter = new EventEmitter<{ action: string; data: any }>();
31 | private promisePool = new PromisePool(5);
32 | private userCache = new Map<number, User>();
33 |
34 | constructor() {
35 | this.initializeEventHandlers();
36 | console.log('TypeScript Showcase initialized');
37 | }
38 |
39 | /**
40 | * Demonstrates basic types and interfaces
41 | */
42 | public demonstrateBasicTypes(): void {
43 | console.log('\n=== Demonstrating Basic Types ===');
44 |
45 | // Create a user with proper typing
46 | const user: User = {
47 | id: 1,
48 | name: "Alice Johnson",
49 | email: "[email protected]",
50 | createdAt: new Date(),
51 | preferences: {
52 | theme: "dark",
53 | notifications: true,
54 | language: "en"
55 | }
56 | };
57 |
58 | // Demonstrate shape calculation with discriminated unions
59 | const shapes: Shape[] = [
60 | { kind: "circle", radius: 5 },
61 | { kind: "rectangle", width: 10, height: 6 },
62 | { kind: "triangle", base: 8, height: 4 }
63 | ];
64 |
65 | const areas = shapes.map(calculateArea);
66 | console.log('User:', user.name, user.email);
67 | console.log('Shape areas:', areas);
68 |
69 | // Cache the user
70 | this.userCache.set(user.id, user);
71 | }
72 |
73 | /**
74 | * Demonstrates classes and inheritance
75 | */
76 | public demonstrateClassesInheritance(): void {
77 | console.log('\n=== Demonstrating Classes & Inheritance ===');
78 |
79 | // Create instances of different classes
80 | const person = new Person("John Doe", 30, 123);
81 | const employee = new Employee("Jane Smith", 28, 456, "Engineering", 75000);
82 | const dog = new Dog("Buddy", 3, "Golden Retriever");
83 |
84 | console.log(person.introduce());
85 | console.log(employee.introduce()); // Uses overridden method
86 | console.log(employee.work());
87 | console.log(dog.makeSound());
88 | console.log(dog.move(10));
89 |
90 | // Demonstrate polymorphism
91 | const animals = [dog];
92 | animals.forEach(animal => {
93 | console.log(animal.sleep()); // Inherited method
94 | });
95 |
96 | // Use static methods
97 | console.log('Species:', Person.getSpecies());
98 | }
99 |
100 | /**
101 | * Demonstrates functions and generics
102 | */
103 | public demonstrateFunctionsGenerics(): void {
104 | console.log('\n=== Demonstrating Functions & Generics ===');
105 |
106 | // Generic data structures
107 | const stringStack = new Stack<string>();
108 | const numberQueue = new Queue<number>();
109 |
110 | stringStack.push("Hello");
111 | stringStack.push("World");
112 | numberQueue.enqueue(1);
113 | numberQueue.enqueue(2);
114 | numberQueue.enqueue(3);
115 |
116 | console.log('Stack peek:', stringStack.peek());
117 | console.log('Queue dequeue:', numberQueue.dequeue());
118 | console.log('Queue size:', numberQueue.size());
119 |
120 | // Memoized function
121 | const memoizedFib = memoize((n: number): number => {
122 | if (n <= 1) return n;
123 | return memoizedFib(n - 1) + memoizedFib(n - 2);
124 | });
125 |
126 | console.log('Fibonacci(10):', memoizedFib(10));
127 | }
128 |
129 | /**
130 | * Demonstrates async programming patterns
131 | */
132 | public async demonstrateAsyncPatterns(): Promise<void> {
133 | console.log('\n=== Demonstrating Async Patterns ===');
134 |
135 | // Event emitter example
136 | this.eventEmitter.emit({ action: 'user_login', data: { userId: 1 } });
137 |
138 | // Promise pool example
139 | const tasks = Array.from({ length: 10 }, (_, i) =>
140 | () => this.simulateAsyncTask(`Task ${i + 1}`)
141 | );
142 |
143 | tasks.forEach(task => this.promisePool.add(task));
144 | const results = await this.promisePool.execute();
145 |
146 | console.log(`Completed ${results.results.length} tasks, ${results.errors.length} errors`);
147 |
148 | // Async generator example
149 | console.log('Processing async stream:');
150 | for await (const item of this.asyncGenerator(3)) {
151 | console.log(' Generated:', item);
152 | }
153 | }
154 |
155 | /**
156 | * Demonstrates error handling and validation
157 | */
158 | public demonstrateErrorHandling(): void {
159 | console.log('\n=== Demonstrating Error Handling ===');
160 |
161 | // Result pattern example
162 | const validationResult = this.validateUserData({
163 | id: "123",
164 | name: "John Doe",
165 | email: "[email protected]",
166 | age: "30"
167 | });
168 |
169 | if (validationResult.success) {
170 | console.log('Validation succeeded:', validationResult.data.name);
171 | } else {
172 | console.log('Validation failed:', validationResult.error.map(e => e.message));
173 | }
174 |
175 | // Error handling with custom errors
176 | try {
177 | this.riskyOperation();
178 | } catch (error) {
179 | if (error instanceof ValidationError) {
180 | console.log('Caught validation error:', error.message);
181 | }
182 | }
183 | }
184 |
185 | /**
186 | * Demonstrates utility functions
187 | */
188 | public demonstrateUtilities(): void {
189 | console.log('\n=== Demonstrating Utilities ===');
190 |
191 | // String utilities
192 | const camelCased = StringUtils.camelCase("hello-world-example");
193 | const kebabCased = StringUtils.kebabCase("HelloWorldExample");
194 | console.log('CamelCase:', camelCased);
195 | console.log('KebabCase:', kebabCased);
196 |
197 | // Array utilities
198 | const chunked = ArrayUtils.chunk([1, 2, 3, 4, 5, 6, 7], 3);
199 | const unique = ArrayUtils.unique([1, 2, 2, 3, 3, 3, 4]);
200 | console.log('Chunked:', chunked);
201 | console.log('Unique:', unique);
202 |
203 | // Object utilities
204 | const deepValue = ObjectUtils.get(
205 | { user: { profile: { name: 'Deep Value' } } },
206 | 'user.profile.name'
207 | );
208 | console.log('Deep value:', deepValue);
209 |
210 | // Grouped data
211 | const grouped = ArrayUtils.groupBy(
212 | [
213 | { type: 'fruit', name: 'apple' },
214 | { type: 'fruit', name: 'banana' },
215 | { type: 'vegetable', name: 'carrot' }
216 | ],
217 | item => item.type
218 | );
219 | console.log('Grouped:', grouped);
220 | }
221 |
222 | /**
223 | * Demonstrates advanced types
224 | */
225 | public demonstrateAdvancedTypes(): void {
226 | console.log('\n=== Demonstrating Advanced Types ===');
227 |
228 | // Using advanced type utilities
229 | const userPaths: AdvancedTypes.Paths<User>[] = [
230 | "name",
231 | "email",
232 | "preferences.theme",
233 | "preferences.notifications"
234 | ];
235 |
236 | console.log('Available user paths:', userPaths);
237 |
238 | // Branded types example
239 | const userId = AdvancedTypes.createUserId(123);
240 | const email = AdvancedTypes.createEmail("[email protected]");
241 |
242 | console.log('Branded types created:', { userId, email });
243 |
244 | // Template literal types
245 | const apiUrl: AdvancedTypes.ApiUrl<"users", "GET"> = "GET /api/users";
246 | console.log('API URL:', apiUrl);
247 | }
248 |
249 | /**
250 | * Demonstrates decorator usage (if decorators are enabled)
251 | */
252 | public demonstrateDecorators(): void {
253 | console.log('\n=== Demonstrating Decorators ===');
254 |
255 | // Create decorated user instance
256 | const decoratedUser = new DecoratorsMetadata.User(1, "decorated_user", "[email protected]", 25);
257 | decoratedUser.currentUserRole = "admin";
258 |
259 | // This will use caching decorator
260 | console.log('User info (cached):', decoratedUser.getInfo());
261 | console.log('User info (from cache):', decoratedUser.getInfo());
262 |
263 | // This will use validation decorator
264 | try {
265 | decoratedUser.updateAge(30);
266 | console.log('Age updated successfully');
267 | } catch (error) {
268 | console.log('Age update failed:', error);
269 | }
270 | }
271 |
272 | /**
273 | * Demonstrates module and namespace usage
274 | */
275 | public demonstrateModulesNamespaces(): void {
276 | console.log('\n=== Demonstrating Modules & Namespaces ===');
277 |
278 | // Using namespace utilities
279 | const vector2D = new ModulesNamespaces.MathUtils.Vector2D(3, 4);
280 | const magnitude = vector2D.magnitude();
281 | console.log(`Vector magnitude: ${magnitude}`);
282 |
283 | // Using nested namespaces
284 | const binaryTree = new ModulesNamespaces.DataStructures.Trees.BinaryTree<number>();
285 | binaryTree.insert(5);
286 | binaryTree.insert(3);
287 | binaryTree.insert(7);
288 | console.log('Binary tree created and populated');
289 |
290 | // Constants from nested namespace
291 | console.log('Golden ratio:', ModulesNamespaces.MathUtils.Constants.GOLDEN_RATIO);
292 | }
293 |
294 | /**
295 | * Runs all demonstrations
296 | */
297 | public async runAllDemonstrations(): Promise<void> {
298 | console.log('🚀 Starting TypeScript Feature Showcase\n');
299 |
300 | try {
301 | this.demonstrateBasicTypes();
302 | this.demonstrateClassesInheritance();
303 | this.demonstrateFunctionsGenerics();
304 | await this.demonstrateAsyncPatterns();
305 | this.demonstrateErrorHandling();
306 | this.demonstrateUtilities();
307 | this.demonstrateAdvancedTypes();
308 | this.demonstrateDecorators();
309 | this.demonstrateModulesNamespaces();
310 |
311 | console.log('\n✅ All TypeScript features demonstrated successfully!');
312 | } catch (error) {
313 | console.error('❌ Error during demonstration:', error);
314 | }
315 | }
316 |
317 | // Private helper methods
318 | private initializeEventHandlers(): void {
319 | this.eventEmitter.subscribe((event) => {
320 | console.log(`Event: ${event.action}`, event.data);
321 | });
322 | }
323 |
324 | private async simulateAsyncTask(name: string): Promise<string> {
325 | await new Promise(resolve => setTimeout(resolve, Math.random() * 100));
326 | return `${name} completed`;
327 | }
328 |
329 | private async* asyncGenerator(count: number): AsyncGenerator<string> {
330 | for (let i = 0; i < count; i++) {
331 | await new Promise(resolve => setTimeout(resolve, 50));
332 | yield `Item ${i + 1}`;
333 | }
334 | }
335 |
336 | private validateUserData(data: any): Result<any, ValidationError[]> {
337 | // Simple validation for demonstration
338 | const errors: ValidationError[] = [];
339 |
340 | if (!data.name || data.name.length < 2) {
341 | errors.push(new ValidationError("Name must be at least 2 characters", "name", data.name));
342 | }
343 |
344 | if (!data.email || !data.email.includes('@')) {
345 | errors.push(new ValidationError("Invalid email format", "email", data.email));
346 | }
347 |
348 | return errors.length === 0 ? Ok(data) : Err(errors);
349 | }
350 |
351 | private riskyOperation(): void {
352 | // Simulate a risky operation that might throw
353 | if (Math.random() > 0.5) {
354 | throw new ValidationError("Random validation failure");
355 | }
356 | }
357 | }
358 |
359 | // Main execution
360 | async function main(): Promise<void> {
361 | const showcase = new TypeScriptShowcase();
362 | await showcase.runAllDemonstrations();
363 |
364 | // Additional integration examples
365 | console.log('\n=== Integration Examples ===');
366 |
367 | // Complex type usage
368 | type UserUpdate = AdvancedTypes.DeepPartial<User>;
369 | const userUpdate: UserUpdate = {
370 | preferences: {
371 | theme: "light"
372 | }
373 | };
374 | console.log('User update:', userUpdate);
375 |
376 | // Utility function chaining
377 | const processedText = StringUtils.camelCase(
378 | StringUtils.truncate("hello-world-example-text", 15)
379 | );
380 | console.log('Processed text:', processedText);
381 |
382 | // Error handling with utilities
383 | const parseResult = ErrorValidation.safeParseInt("42");
384 | if (ErrorValidation.isOk(parseResult)) {
385 | console.log('Parsed number:', parseResult.data);
386 | }
387 | }
388 |
389 | // Export everything for external usage
390 | export * from './types-interfaces';
391 | export * from './classes-inheritance';
392 | export * from './functions-generics';
393 | export * from './async-promises';
394 | export * from './decorators-metadata';
395 | export * from './modules-namespaces';
396 | export * from './advanced-types';
397 | export * from './error-validation';
398 | export * from './utilities-helpers';
399 |
400 | // Run the main function if this is the entry point
401 | if (require.main === module) {
402 | main().catch(console.error);
403 | }
404 |
405 | export default TypeScriptShowcase;
```
--------------------------------------------------------------------------------
/website/src/components/CookbookSection.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import { useState } from "react";
2 | import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
3 | import { Badge } from "@/components/ui/badge";
4 | import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
5 | import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
6 | import { Button } from "@/components/ui/button";
7 | import { ChevronDown, Copy, Terminal, Search, Code, Database, BookOpen } from "lucide-react";
8 | import { useToast } from "@/hooks/use-toast";
9 |
10 | const CookbookSection = () => {
11 | const { toast } = useToast();
12 | const [openItems, setOpenItems] = useState<Set<string>>(new Set());
13 |
14 | const toggleItem = (id: string) => {
15 | const newOpenItems = new Set(openItems);
16 | if (newOpenItems.has(id)) {
17 | newOpenItems.delete(id);
18 | } else {
19 | newOpenItems.add(id);
20 | }
21 | setOpenItems(newOpenItems);
22 | };
23 |
24 | const copyToClipboard = (text: string) => {
25 | navigator.clipboard.writeText(text);
26 | toast({
27 | title: "Copied to clipboard!",
28 | description: "The code snippet has been copied to your clipboard.",
29 | });
30 | };
31 |
32 | const basicExamples = [
33 | {
34 | id: "find-function",
35 | title: "Find all definitions of a function",
36 | description: "Find all definitions of the 'helper' function.",
37 | tool: "analyze_code_relationships",
38 | args: `{
39 | "query_type": "find_definitions",
40 | "target": "helper"
41 | }`
42 | },
43 | {
44 | id: "find-callers",
45 | title: "Find all calls to a specific function",
46 | description: "Find all calls to the 'helper' function.",
47 | tool: "analyze_code_relationships",
48 | args: `{
49 | "query_type": "find_callers",
50 | "target": "helper"
51 | }`
52 | },
53 | {
54 | id: "find-callees",
55 | title: "Find what a function calls",
56 | description: "What functions are called inside the 'foo' function?",
57 | tool: "analyze_code_relationships",
58 | args: `{
59 | "query_type": "find_callees",
60 | "target": "foo",
61 | "context": "/path/to/your/project/module_a.py"
62 | }`
63 | },
64 | {
65 | id: "find-imports",
66 | title: "Find all imports of a module",
67 | description: "Where is the 'math' module imported?",
68 | tool: "analyze_code_relationships",
69 | args: `{
70 | "query_type": "find_importers",
71 | "target": "math"
72 | }`
73 | }
74 | ];
75 |
76 | const analysisExamples = [
77 | {
78 | id: "complex-functions",
79 | title: "Find the most complex functions",
80 | description: "Find the 5 most complex functions in your codebase.",
81 | tool: "find_most_complex_functions",
82 | args: `{
83 | "limit": 5
84 | }`
85 | },
86 | {
87 | id: "cyclomatic-complexity",
88 | title: "Calculate cyclomatic complexity",
89 | description: "What is the cyclomatic complexity of 'try_except_finally'?",
90 | tool: "calculate_cyclomatic_complexity",
91 | args: `{
92 | "function_name": "try_except_finally"
93 | }`
94 | },
95 | {
96 | id: "dead-code",
97 | title: "Find unused code",
98 | description: "Find unused code, but ignore API endpoints.",
99 | tool: "find_dead_code",
100 | args: `{
101 | "exclude_decorated_with": ["@app.route"]
102 | }`
103 | },
104 | {
105 | id: "call-chain",
106 | title: "Find call chain between functions",
107 | description: "What is the call chain from 'wrapper' to 'helper'?",
108 | tool: "analyze_code_relationships",
109 | args: `{
110 | "query_type": "call_chain",
111 | "target": "wrapper->helper"
112 | }`
113 | }
114 | ];
115 |
116 | const cypherExamples = [
117 | {
118 | id: "all-functions",
119 | title: "Find all function definitions",
120 | description: "Find all function definitions in the codebase.",
121 | tool: "execute_cypher_query",
122 | args: `{
123 | "cypher_query": "MATCH (n:Function) RETURN n.name, n.file_path, n.line_number LIMIT 50"
124 | }`
125 | },
126 | {
127 | id: "all-classes",
128 | title: "Find all classes",
129 | description: "Show me all the classes in the codebase.",
130 | tool: "execute_cypher_query",
131 | args: `{
132 | "cypher_query": "MATCH (n:Class) RETURN n.name, n.file_path, n.line_number LIMIT 50"
133 | }`
134 | },
135 | {
136 | id: "dataclasses",
137 | title: "Find all dataclasses",
138 | description: "Find all dataclasses in the codebase.",
139 | tool: "execute_cypher_query",
140 | args: `{
141 | "cypher_query": "MATCH (c:Class) WHERE 'dataclass' IN c.decorators RETURN c.name, c.file_path"
142 | }`
143 | },
144 | {
145 | id: "circular-imports",
146 | title: "Find circular file imports",
147 | description: "Are there any circular dependencies between files?",
148 | tool: "execute_cypher_query",
149 | args: `{
150 | "cypher_query": "MATCH path = (f1:File)-[:IMPORTS*2..]->(f1) RETURN path LIMIT 10"
151 | }`
152 | }
153 | ];
154 |
155 | const ExampleCard = ({
156 | example,
157 | isOpen,
158 | onToggle,
159 | }: {
160 | example: any;
161 | isOpen: boolean;
162 | onToggle: () => void;
163 | }) => (
164 | <div data-aos="fade-up" data-aos-delay="100">
165 | <Collapsible open={isOpen} onOpenChange={onToggle}>
166 | <CollapsibleTrigger asChild>
167 | <Card className="cursor-pointer hover:bg-muted/30 transition-all duration-200 border border-border/50">
168 | <CardHeader>
169 | <div className="flex flex-col-reverse gap-5 md:gap-0 md:flex-row items-center md:items-start justify-between">
170 | <div className="text-center md:text-left">
171 | <CardTitle className="text-base font-medium text-foreground">
172 | {example.title}
173 | </CardTitle>
174 | <p className="text-sm text-muted-foreground mt-1">
175 | {example.description}
176 | </p>
177 | </div>
178 | <div className="flex items-center gap-2 self-start sm:self-auto">
179 | <div className="flex items-center gap-1 bg-secondary text-secondary-foreground px-2 py-1 rounded-md text-xs">
180 | <span>{example.tool}</span>
181 | <ChevronDown
182 | className={`h-3.5 w-3.5 transition-transform ${
183 | isOpen ? "rotate-180" : ""
184 | }`}
185 | />
186 | </div>
187 | </div>
188 | </div>
189 | </CardHeader>
190 | </Card>
191 | </CollapsibleTrigger>
192 |
193 | <CollapsibleContent>
194 | <Card className="mt-2 border border-border/30 bg-muted/20">
195 | <CardContent className="p-4">
196 | <div className="space-y-3">
197 | <div className="flex items-center justify-between flex-wrap gap-2">
198 | <span className="text-sm font-medium text-muted-foreground">
199 | JSON Arguments:
200 | </span>
201 | <Button
202 | variant="ghost"
203 | size="sm"
204 | onClick={() => copyToClipboard(example.args)}
205 | className="h-7"
206 | >
207 | <Copy className="h-3 w-3" />
208 | </Button>
209 | </div>
210 | <pre className="bg-muted/50 rounded-md p-3 text-sm overflow-x-auto border border-border/30">
211 | <code className="text-foreground break-words">
212 | {example.args}
213 | </code>
214 | </pre>
215 | </div>
216 | </CardContent>
217 | </Card>
218 | </CollapsibleContent>
219 | </Collapsible>
220 | </div>
221 | );
222 |
223 | return (
224 | <section className="py-20 px-4 bg-gradient-subtle relative overflow-hidden" data-aos="fade-in">
225 | <div className="absolute inset-0 bg-grid-pattern opacity-20" />
226 | <div className="container mx-auto max-w-6xl relative z-10">
227 | <div className="text-center mb-16" data-aos="fade-down">
228 | <div className="flex items-center justify-center gap-3 mb-6">
229 | <div className="p-2 rounded-lg bg-primary/10 border border-primary/20">
230 | <BookOpen className="h-6 w-6 text-primary" />
231 | </div>
232 | <h2 className="text-4xl font-bold bg-gradient-to-r from-primary via-primary to-accent bg-clip-text text-transparent">
233 | MCP Tool Cookbook
234 | </h2>
235 | </div>
236 | <p className="text-xl text-muted-foreground max-w-3xl mx-auto leading-relaxed">
237 | Practical examples and patterns for using CodeGraphContext with AI assistants.
238 | Copy the JSON arguments and use them directly with your MCP-enabled AI tools.
239 | </p>
240 | </div>
241 |
242 | <Tabs defaultValue="basic" className="w-full">
243 | <TabsList className="grid w-full grid-cols-3 mb-8" data-aos="fade-up" data-aos-delay="200">
244 | <TabsTrigger value="basic" className="flex items-center gap-1 sm:gap-2 text-xs sm:text-sm">
245 | <Search className="h-3 w-3 sm:h-4 sm:w-4" />
246 | <span className="hidden sm:inline">Basic Navigation</span>
247 | <span className="sm:hidden">Basic</span>
248 | </TabsTrigger>
249 | <TabsTrigger value="analysis" className="flex items-center gap-1 sm:gap-2 text-xs sm:text-sm">
250 | <Terminal className="h-3 w-3 sm:h-4 sm:w-4" />
251 | <span className="hidden sm:inline">Code Analysis</span>
252 | <span className="sm:hidden">Analysis</span>
253 | </TabsTrigger>
254 | <TabsTrigger value="cypher" className="flex items-center gap-1 sm:gap-2 text-xs sm:text-sm">
255 | <Database className="h-3 w-3 sm:h-4 sm:w-4" />
256 | <span className="hidden sm:inline">Advanced Queries</span>
257 | <span className="sm:hidden">Advanced</span>
258 | </TabsTrigger>
259 | </TabsList>
260 |
261 | <TabsContent value="basic" className="space-y-4">
262 | <div className="text-center mb-8">
263 | <h3 className="text-2xl font-semibold mb-3">Basic Navigation & Discovery</h3>
264 | <p className="text-muted-foreground">
265 | Essential queries for exploring and understanding your codebase structure.
266 | </p>
267 | </div>
268 | {basicExamples.map((example) => (
269 | <ExampleCard
270 | key={example.id}
271 | example={example}
272 | isOpen={openItems.has(example.id)}
273 | onToggle={() => toggleItem(example.id)}
274 | />
275 | ))}
276 | </TabsContent>
277 |
278 | <TabsContent value="analysis" className="space-y-4">
279 | <div className="text-center mb-8">
280 | <h3 className="text-2xl font-semibold mb-3">Code Analysis & Quality</h3>
281 | <p className="text-muted-foreground">
282 | Advanced analysis tools for code quality, complexity, and dependency tracking.
283 | </p>
284 | </div>
285 | {analysisExamples.map((example) => (
286 | <ExampleCard
287 | key={example.id}
288 | example={example}
289 | isOpen={openItems.has(example.id)}
290 | onToggle={() => toggleItem(example.id)}
291 | />
292 | ))}
293 | </TabsContent>
294 |
295 | <TabsContent value="cypher" className="space-y-4">
296 | <div className="text-center mb-8">
297 | <h3 className="text-2xl font-semibold mb-3">Advanced Cypher Queries</h3>
298 | <p className="text-muted-foreground">
299 | Direct Neo4j Cypher queries for complex analysis and custom investigations.
300 | </p>
301 | </div>
302 | {cypherExamples.map((example) => (
303 | <ExampleCard
304 | key={example.id}
305 | example={example}
306 | isOpen={openItems.has(example.id)}
307 | onToggle={() => toggleItem(example.id)}
308 | />
309 | ))}
310 | </TabsContent>
311 | </Tabs>
312 |
313 | <div className="mt-16 text-center" data-aos="fade-up" data-aos-delay="300">
314 | <Card className="inline-block p-6 bg-gradient-to-r from-primary/5 to-accent/5 border border-primary/20">
315 | <div className="flex items-center gap-3 mb-3">
316 | <Code className="h-5 w-5 text-primary" />
317 | <h4 className="text-lg font-semibold">Want to contribute more examples?</h4>
318 | </div>
319 | <p className="text-muted-foreground mb-4">
320 | Help expand this cookbook with your own patterns and use cases.
321 | </p>
322 | <Button variant="outline" asChild>
323 | <a
324 | href="https://github.com/Shashankss1205/CodeGraphContext/blob/main/docs/cookbook.md"
325 | target="_blank"
326 | rel="noopener noreferrer"
327 | >
328 | View Full Cookbook on GitHub
329 | </a>
330 | </Button>
331 | </Card>
332 | </div>
333 | </div>
334 | </section>
335 | );
336 | };
337 |
338 | export default CookbookSection;
339 |
340 |
```
--------------------------------------------------------------------------------
/docs/site/assets/stylesheets/palette.06af60db.min.css:
--------------------------------------------------------------------------------
```css
1 | @media screen{[data-md-color-scheme=slate]{--md-default-fg-color:hsla(var(--md-hue),15%,90%,0.82);--md-default-fg-color--light:hsla(var(--md-hue),15%,90%,0.56);--md-default-fg-color--lighter:hsla(var(--md-hue),15%,90%,0.32);--md-default-fg-color--lightest:hsla(var(--md-hue),15%,90%,0.12);--md-default-bg-color:hsla(var(--md-hue),15%,14%,1);--md-default-bg-color--light:hsla(var(--md-hue),15%,14%,0.54);--md-default-bg-color--lighter:hsla(var(--md-hue),15%,14%,0.26);--md-default-bg-color--lightest:hsla(var(--md-hue),15%,14%,0.07);--md-code-fg-color:hsla(var(--md-hue),18%,86%,0.82);--md-code-bg-color:hsla(var(--md-hue),15%,18%,1);--md-code-hl-color:#2977ff;--md-code-hl-color--light:#2977ff1a;--md-code-hl-number-color:#e6695b;--md-code-hl-special-color:#f06090;--md-code-hl-function-color:#c973d9;--md-code-hl-constant-color:#9383e2;--md-code-hl-keyword-color:#6791e0;--md-code-hl-string-color:#2fb170;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-kbd-color:hsla(var(--md-hue),15%,90%,0.12);--md-typeset-kbd-accent-color:hsla(var(--md-hue),15%,90%,0.2);--md-typeset-kbd-border-color:hsla(var(--md-hue),15%,14%,1);--md-typeset-mark-color:#4287ff4d;--md-typeset-table-color:hsla(var(--md-hue),15%,95%,0.12);--md-typeset-table-color--light:hsla(var(--md-hue),15%,95%,0.035);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-footer-bg-color:hsla(var(--md-hue),15%,10%,0.87);--md-footer-bg-color--dark:hsla(var(--md-hue),15%,8%,1);--md-shadow-z1:0 0.2rem 0.5rem #0000000d,0 0 0.05rem #0000001a;--md-shadow-z2:0 0.2rem 0.5rem #00000040,0 0 0.05rem #00000040;--md-shadow-z3:0 0.2rem 0.5rem #0006,0 0 0.05rem #00000059;color-scheme:dark}[data-md-color-scheme=slate] img[src$="#gh-light-mode-only"],[data-md-color-scheme=slate] img[src$="#only-light"]{display:none}[data-md-color-scheme=slate][data-md-color-primary=pink]{--md-typeset-a-color:#ed5487}[data-md-color-scheme=slate][data-md-color-primary=purple]{--md-typeset-a-color:#c46fd3}[data-md-color-scheme=slate][data-md-color-primary=deep-purple]{--md-typeset-a-color:#a47bea}[data-md-color-scheme=slate][data-md-color-primary=indigo]{--md-typeset-a-color:#5488e8}[data-md-color-scheme=slate][data-md-color-primary=teal]{--md-typeset-a-color:#00ccb8}[data-md-color-scheme=slate][data-md-color-primary=green]{--md-typeset-a-color:#71c174}[data-md-color-scheme=slate][data-md-color-primary=deep-orange]{--md-typeset-a-color:#ff764d}[data-md-color-scheme=slate][data-md-color-primary=brown]{--md-typeset-a-color:#c1775c}[data-md-color-scheme=slate][data-md-color-primary=black],[data-md-color-scheme=slate][data-md-color-primary=blue-grey],[data-md-color-scheme=slate][data-md-color-primary=grey],[data-md-color-scheme=slate][data-md-color-primary=white]{--md-typeset-a-color:#5e8bde}[data-md-color-switching] *,[data-md-color-switching] :after,[data-md-color-switching] :before{transition-duration:0ms!important}}[data-md-color-accent=red]{--md-accent-fg-color:#ff1947;--md-accent-fg-color--transparent:#ff19471a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=pink]{--md-accent-fg-color:#f50056;--md-accent-fg-color--transparent:#f500561a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=purple]{--md-accent-fg-color:#df41fb;--md-accent-fg-color--transparent:#df41fb1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=deep-purple]{--md-accent-fg-color:#7c4dff;--md-accent-fg-color--transparent:#7c4dff1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=indigo]{--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:#526cfe1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=blue]{--md-accent-fg-color:#4287ff;--md-accent-fg-color--transparent:#4287ff1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=light-blue]{--md-accent-fg-color:#0091eb;--md-accent-fg-color--transparent:#0091eb1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=cyan]{--md-accent-fg-color:#00bad6;--md-accent-fg-color--transparent:#00bad61a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=teal]{--md-accent-fg-color:#00bda4;--md-accent-fg-color--transparent:#00bda41a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=green]{--md-accent-fg-color:#00c753;--md-accent-fg-color--transparent:#00c7531a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=light-green]{--md-accent-fg-color:#63de17;--md-accent-fg-color--transparent:#63de171a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=lime]{--md-accent-fg-color:#b0eb00;--md-accent-fg-color--transparent:#b0eb001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=yellow]{--md-accent-fg-color:#ffd500;--md-accent-fg-color--transparent:#ffd5001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=amber]{--md-accent-fg-color:#fa0;--md-accent-fg-color--transparent:#ffaa001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=orange]{--md-accent-fg-color:#ff9100;--md-accent-fg-color--transparent:#ff91001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=deep-orange]{--md-accent-fg-color:#ff6e42;--md-accent-fg-color--transparent:#ff6e421a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-primary=red]{--md-primary-fg-color:#ef5552;--md-primary-fg-color--light:#e57171;--md-primary-fg-color--dark:#e53734;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=pink]{--md-primary-fg-color:#e92063;--md-primary-fg-color--light:#ec417a;--md-primary-fg-color--dark:#c3185d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=purple]{--md-primary-fg-color:#ab47bd;--md-primary-fg-color--light:#bb69c9;--md-primary-fg-color--dark:#8c24a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=deep-purple]{--md-primary-fg-color:#7e56c2;--md-primary-fg-color--light:#9574cd;--md-primary-fg-color--dark:#673ab6;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=indigo]{--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=blue]{--md-primary-fg-color:#2094f3;--md-primary-fg-color--light:#42a5f5;--md-primary-fg-color--dark:#1975d2;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=light-blue]{--md-primary-fg-color:#02a6f2;--md-primary-fg-color--light:#28b5f6;--md-primary-fg-color--dark:#0287cf;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=cyan]{--md-primary-fg-color:#00bdd6;--md-primary-fg-color--light:#25c5da;--md-primary-fg-color--dark:#0097a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=teal]{--md-primary-fg-color:#009485;--md-primary-fg-color--light:#26a699;--md-primary-fg-color--dark:#007a6c;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=green]{--md-primary-fg-color:#4cae4f;--md-primary-fg-color--light:#68bb6c;--md-primary-fg-color--dark:#398e3d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=light-green]{--md-primary-fg-color:#8bc34b;--md-primary-fg-color--light:#9ccc66;--md-primary-fg-color--dark:#689f38;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=lime]{--md-primary-fg-color:#cbdc38;--md-primary-fg-color--light:#d3e156;--md-primary-fg-color--dark:#b0b52c;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=yellow]{--md-primary-fg-color:#ffec3d;--md-primary-fg-color--light:#ffee57;--md-primary-fg-color--dark:#fbc02d;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=amber]{--md-primary-fg-color:#ffc105;--md-primary-fg-color--light:#ffc929;--md-primary-fg-color--dark:#ffa200;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=orange]{--md-primary-fg-color:#ffa724;--md-primary-fg-color--light:#ffa724;--md-primary-fg-color--dark:#fa8900;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=deep-orange]{--md-primary-fg-color:#ff6e42;--md-primary-fg-color--light:#ff8a66;--md-primary-fg-color--dark:#f4511f;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=brown]{--md-primary-fg-color:#795649;--md-primary-fg-color--light:#8d6e62;--md-primary-fg-color--dark:#5d4037;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=grey]{--md-primary-fg-color:#757575;--md-primary-fg-color--light:#9e9e9e;--md-primary-fg-color--dark:#616161;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-typeset-a-color:#4051b5}[data-md-color-primary=blue-grey]{--md-primary-fg-color:#546d78;--md-primary-fg-color--light:#607c8a;--md-primary-fg-color--dark:#455a63;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-typeset-a-color:#4051b5}[data-md-color-primary=light-green]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#72ad2e}[data-md-color-primary=lime]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#8b990a}[data-md-color-primary=yellow]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#b8a500}[data-md-color-primary=amber]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#d19d00}[data-md-color-primary=orange]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#e68a00}[data-md-color-primary=white]{--md-primary-fg-color:hsla(var(--md-hue),0%,100%,1);--md-primary-fg-color--light:hsla(var(--md-hue),0%,100%,0.7);--md-primary-fg-color--dark:hsla(var(--md-hue),0%,0%,0.07);--md-primary-bg-color:hsla(var(--md-hue),0%,0%,0.87);--md-primary-bg-color--light:hsla(var(--md-hue),0%,0%,0.54);--md-typeset-a-color:#4051b5}[data-md-color-primary=white] .md-button{color:var(--md-typeset-a-color)}[data-md-color-primary=white] .md-button--primary{background-color:var(--md-typeset-a-color);border-color:var(--md-typeset-a-color);color:hsla(var(--md-hue),0%,100%,1)}@media screen and (min-width:60em){[data-md-color-primary=white] .md-search__form{background-color:hsla(var(--md-hue),0%,0%,.07)}[data-md-color-primary=white] .md-search__form:hover{background-color:hsla(var(--md-hue),0%,0%,.32)}[data-md-color-primary=white] .md-search__input+.md-search__icon{color:hsla(var(--md-hue),0%,0%,.87)}}@media screen and (min-width:76.25em){[data-md-color-primary=white] .md-tabs{border-bottom:.05rem solid #00000012}}[data-md-color-primary=black]{--md-primary-fg-color:hsla(var(--md-hue),15%,9%,1);--md-primary-fg-color--light:hsla(var(--md-hue),15%,9%,0.54);--md-primary-fg-color--dark:hsla(var(--md-hue),15%,9%,1);--md-primary-bg-color:hsla(var(--md-hue),15%,100%,1);--md-primary-bg-color--light:hsla(var(--md-hue),15%,100%,0.7);--md-typeset-a-color:#4051b5}[data-md-color-primary=black] .md-button{color:var(--md-typeset-a-color)}[data-md-color-primary=black] .md-button--primary{background-color:var(--md-typeset-a-color);border-color:var(--md-typeset-a-color);color:hsla(var(--md-hue),0%,100%,1)}[data-md-color-primary=black] .md-header{background-color:hsla(var(--md-hue),15%,9%,1)}@media screen and (max-width:59.984375em){[data-md-color-primary=black] .md-nav__source{background-color:hsla(var(--md-hue),15%,11%,.87)}}@media screen and (max-width:76.234375em){html [data-md-color-primary=black] .md-nav--primary .md-nav__title[for=__drawer]{background-color:hsla(var(--md-hue),15%,9%,1)}}@media screen and (min-width:76.25em){[data-md-color-primary=black] .md-tabs{background-color:hsla(var(--md-hue),15%,9%,1)}}
```
--------------------------------------------------------------------------------
/src/codegraphcontext/tools/languages/java.py:
--------------------------------------------------------------------------------
```python
1 | from pathlib import Path
2 | from typing import Any, Dict, Optional, Tuple
3 | import re
4 | from codegraphcontext.utils.debug_log import debug_log, info_logger, error_logger, warning_logger
5 |
6 | JAVA_QUERIES = {
7 | "functions": """
8 | (method_declaration
9 | name: (identifier) @name
10 | parameters: (formal_parameters) @params
11 | ) @function_node
12 |
13 | (constructor_declaration
14 | name: (identifier) @name
15 | parameters: (formal_parameters) @params
16 | ) @function_node
17 | """,
18 | "classes": """
19 | [
20 | (class_declaration name: (identifier) @name)
21 | (interface_declaration name: (identifier) @name)
22 | (enum_declaration name: (identifier) @name)
23 | (annotation_type_declaration name: (identifier) @name)
24 | ] @class
25 | """,
26 | "imports": """
27 | (import_declaration) @import
28 | """,
29 | "calls": """
30 | (method_invocation
31 | name: (identifier) @name
32 | )
33 |
34 | (object_creation_expression
35 | type: (type_identifier) @name
36 | )
37 | """,
38 | }
39 |
40 | class JavaTreeSitterParser:
41 | def __init__(self, generic_parser_wrapper: Any):
42 | self.generic_parser_wrapper = generic_parser_wrapper
43 | self.language_name = "java"
44 | self.language = generic_parser_wrapper.language
45 | self.parser = generic_parser_wrapper.parser
46 |
47 | self.queries = {
48 | name: self.language.query(query_str)
49 | for name, query_str in JAVA_QUERIES.items()
50 | }
51 |
52 | def parse(self, file_path: Path, is_dependency: bool = False) -> Dict[str, Any]:
53 | try:
54 | with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
55 | source_code = f.read()
56 |
57 | if not source_code.strip():
58 | warning_logger(f"Empty or whitespace-only file: {file_path}")
59 | return {
60 | "file_path": str(file_path),
61 | "functions": [],
62 | "classes": [],
63 | "variables": [],
64 | "imports": [],
65 | "function_calls": [],
66 | "is_dependency": is_dependency,
67 | "lang": self.language_name,
68 | }
69 |
70 | tree = self.parser.parse(bytes(source_code, "utf8"))
71 |
72 | parsed_functions = []
73 | parsed_classes = []
74 | parsed_imports = []
75 | parsed_calls = []
76 |
77 | for capture_name, query in self.queries.items():
78 | captures = query.captures(tree.root_node)
79 |
80 | if capture_name == "functions":
81 | parsed_functions = self._parse_functions(captures, source_code, file_path)
82 | elif capture_name == "classes":
83 | parsed_classes = self._parse_classes(captures, source_code, file_path)
84 | elif capture_name == "imports":
85 | parsed_imports = self._parse_imports(captures, source_code)
86 | elif capture_name == "calls":
87 | parsed_calls = self._parse_calls(captures, source_code)
88 |
89 | return {
90 | "file_path": str(file_path),
91 | "functions": parsed_functions,
92 | "classes": parsed_classes,
93 | "variables": [],
94 | "imports": parsed_imports,
95 | "function_calls": parsed_calls,
96 | "is_dependency": is_dependency,
97 | "lang": self.language_name,
98 | }
99 |
100 | except Exception as e:
101 | error_logger(f"Error parsing Java file {file_path}: {e}")
102 | return {
103 | "file_path": str(file_path),
104 | "functions": [],
105 | "classes": [],
106 | "variables": [],
107 | "imports": [],
108 | "function_calls": [],
109 | "is_dependency": is_dependency,
110 | "lang": self.language_name,
111 | }
112 |
113 | def _parse_functions(self, captures: list, source_code: str, file_path: Path) -> list[Dict[str, Any]]:
114 | functions = []
115 | source_lines = source_code.splitlines()
116 |
117 | for node, capture_name in captures:
118 | if capture_name == "function_node":
119 | try:
120 | start_line = node.start_point[0] + 1
121 | end_line = node.end_point[0] + 1
122 |
123 | name_captures = [
124 | (n, cn) for n, cn in captures
125 | if cn == "name" and n.parent == node
126 | ]
127 |
128 | if name_captures:
129 | name_node = name_captures[0][0]
130 | func_name = source_code[name_node.start_byte:name_node.end_byte]
131 |
132 | params_captures = [
133 | (n, cn) for n, cn in captures
134 | if cn == "params" and n.parent == node
135 | ]
136 |
137 | parameters = []
138 | if params_captures:
139 | params_node = params_captures[0][0]
140 | params_text = source_code[params_node.start_byte:params_node.end_byte]
141 | parameters = self._extract_parameter_names(params_text)
142 | # Extract annotations applied to this function
143 | annotations = []
144 | for n, cn in captures:
145 | if cn == "annotation" and n.parent == node:
146 | ann_name_node = n.child_by_field_name("name")
147 | if ann_name_node:
148 | ann_name = source_code[ann_name_node.start_byte:ann_name_node.end_byte]
149 | annotations.append(ann_name)
150 |
151 | source_text = source_code[node.start_byte:node.end_byte]
152 |
153 | functions.append({
154 | "name": func_name,
155 | "parameters": parameters,
156 | "annotations":annotations,
157 | "line_number": start_line,
158 | "end_line": end_line,
159 | "source": source_text,
160 | "file_path": str(file_path),
161 | "lang": self.language_name,
162 | })
163 |
164 | except Exception as e:
165 | error_logger(f"Error parsing function in {file_path}: {e}")
166 | continue
167 |
168 | return functions
169 |
170 | def _parse_classes(self, captures: list, source_code: str, file_path: Path) -> list[Dict[str, Any]]:
171 | classes = []
172 |
173 | for node, capture_name in captures:
174 | if capture_name == "class":
175 | try:
176 | start_line = node.start_point[0] + 1
177 | end_line = node.end_point[0] + 1
178 |
179 | name_captures = [
180 | (n, cn) for n, cn in captures
181 | if cn == "name" and n.parent == node
182 | ]
183 |
184 | if name_captures:
185 | name_node = name_captures[0][0]
186 | class_name = source_code[name_node.start_byte:name_node.end_byte]
187 |
188 | source_text = source_code[node.start_byte:node.end_byte]
189 |
190 | classes.append({
191 | "name": class_name,
192 | "line_number": start_line,
193 | "end_line": end_line,
194 | "source": source_text,
195 | "file_path": str(file_path),
196 | "lang": self.language_name,
197 | })
198 |
199 | except Exception as e:
200 | error_logger(f"Error parsing class in {file_path}: {e}")
201 | continue
202 |
203 | return classes
204 |
205 | def _parse_imports(self, captures: list, source_code: str) -> list[dict]:
206 | imports = []
207 |
208 | for node, capture_name in captures:
209 | if capture_name == "import":
210 | try:
211 | import_text = source_code[node.start_byte:node.end_byte]
212 | import_match = re.search(r'import\s+(?:static\s+)?([^;]+)', import_text)
213 | if import_match:
214 | import_path = import_match.group(1).strip()
215 |
216 | import_data = {
217 | "name": import_path,
218 | "full_import_name": import_path,
219 | "line_number": node.start_point[0] + 1,
220 | "alias": None,
221 | "context": (None, None),
222 | "lang": self.language_name,
223 | "is_dependency": False,
224 | }
225 | imports.append(import_data)
226 | except Exception as e:
227 | error_logger(f"Error parsing import: {e}")
228 | continue
229 |
230 | return imports
231 |
232 | def _parse_calls(self, captures: list, source_code: str) -> list[dict]:
233 | calls = []
234 | seen_calls = set()
235 |
236 | for node, capture_name in captures:
237 | if capture_name == "name":
238 | try:
239 | call_name = source_code[node.start_byte:node.end_byte]
240 | line_number = node.start_point[0] + 1
241 |
242 | # Avoid duplicates
243 | call_key = f"{call_name}_{line_number}"
244 | if call_key in seen_calls:
245 | continue
246 | seen_calls.add(call_key)
247 |
248 | call_data = {
249 | "name": call_name,
250 | "full_name": call_name,
251 | "line_number": line_number,
252 | "args": [],
253 | "inferred_obj_type": None,
254 | "context": (None, None),
255 | "class_context": (None, None),
256 | "lang": self.language_name,
257 | "is_dependency": False,
258 | }
259 | calls.append(call_data)
260 | except Exception as e:
261 | error_logger(f"Error parsing call: {e}")
262 | continue
263 |
264 | return calls
265 |
266 |
267 | def _extract_parameter_names(self, params_text: str) -> list[str]:
268 | params = []
269 | if not params_text or params_text.strip() == "()":
270 | return params
271 |
272 | params_content = params_text.strip("()")
273 | if not params_content:
274 | return params
275 |
276 | for param in params_content.split(","):
277 | param = param.strip()
278 | if param:
279 | parts = param.split()
280 | if len(parts) >= 2:
281 | param_name = parts[-1]
282 | params.append(param_name)
283 |
284 | return params
285 |
286 |
287 | def pre_scan_java(files: list[Path], parser_wrapper) -> dict:
288 | name_to_files = {}
289 |
290 | for file_path in files:
291 | try:
292 | with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
293 | content = f.read()
294 |
295 | class_matches = re.finditer(r'\b(?:public\s+|private\s+|protected\s+)?(?:static\s+)?(?:abstract\s+)?(?:final\s+)?class\s+(\w+)', content)
296 | for match in class_matches:
297 | class_name = match.group(1)
298 | if class_name not in name_to_files:
299 | name_to_files[class_name] = []
300 | name_to_files[class_name].append(str(file_path))
301 |
302 | interface_matches = re.finditer(r'\b(?:public\s+|private\s+|protected\s+)?interface\s+(\w+)', content)
303 | for match in interface_matches:
304 | interface_name = match.group(1)
305 | if interface_name not in name_to_files:
306 | name_to_files[interface_name] = []
307 | name_to_files[interface_name].append(str(file_path))
308 |
309 | except Exception as e:
310 | error_logger(f"Error pre-scanning Java file {file_path}: {e}")
311 |
312 | return name_to_files
313 | def _find_annotations(tree):
314 | # Detect annotation definitions like @interface CustomAnnotation
315 | annotations = []
316 | for node in tree.find_all("annotation_type_declaration"):
317 | name = node.child_by_field_name("name").text
318 | annotations.append({
319 | "type": "Annotation",
320 | "name": name,
321 | "location": node.start_point
322 | })
323 | return annotations
324 |
325 | def _find_applied_annotations(tree):
326 | # Detect usages like @Entity, @Override
327 | applied = []
328 | for node in tree.find_all("marker_annotation"):
329 | name = node.child_by_field_name("name").text
330 | applied.append({
331 | "type": "AnnotationUsage",
332 | "name": name,
333 | "location": node.start_point
334 | })
335 | return applied
336 |
337 |
```