cg-code-graph 0.12.0__tar.gz → 0.13.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cg_code_graph-0.13.0/PKG-INFO +84 -0
- cg_code_graph-0.13.0/README.md +60 -0
- cg_code_graph-0.13.0/cg_code_graph.egg-info/PKG-INFO +84 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/cg_code_graph.egg-info/SOURCES.txt +5 -1
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/__init__.py +1 -1
- cg_code_graph-0.13.0/codegraph/apps.py +88 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/cli.py +43 -5
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/config.py +16 -4
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/external.py +136 -40
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/link.py +223 -75
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/mcp_server.py +14 -6
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/python/external.py +61 -1
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/protocols/__init__.py +6 -2
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/query.py +34 -2
- cg_code_graph-0.13.0/codegraph/sdk_systems.py +963 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_config_extras.py +9 -9
- cg_code_graph-0.13.0/tests/test_docs_links.py +57 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_external.py +114 -0
- cg_code_graph-0.13.0/tests/test_sdk_external.py +102 -0
- cg_code_graph-0.13.0/tests/test_workspace_link.py +201 -0
- cg_code_graph-0.12.0/PKG-INFO +0 -680
- cg_code_graph-0.12.0/README.md +0 -656
- cg_code_graph-0.12.0/cg_code_graph.egg-info/PKG-INFO +0 -680
- cg_code_graph-0.12.0/codegraph/apps.py +0 -76
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/LICENSE +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/MANIFEST.in +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/cg_code_graph.egg-info/dependency_links.txt +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/cg_code_graph.egg-info/entry_points.txt +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/cg_code_graph.egg-info/requires.txt +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/cg_code_graph.egg-info/top_level.txt +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/agent_rules.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/agents.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/aitools.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/android_ipc.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/apple_ipc.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/blindspots.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/bridges.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/brokers.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/concepts.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/core/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/core/cache.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/core/detect.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/core/extractors.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/core/fsutil.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/core/generated.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/core/model.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/core/paths.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/core/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/core/store.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/core/syntax_errors.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/coverage.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/dart_isolates.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/doctor.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/graphql.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/indexer.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/jobs.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/lint_async.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/local_ipc.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/local_sockets.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/parity.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/parity_structure.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/payload.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plans.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/platform_scan.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/platforms.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/cfamily/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/cfamily/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/cfamily/syntax.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/dart/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/dart/bridges.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/dart/extractor/bin/extract.dart +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/dart/extractor/pubspec.lock +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/dart/extractor/pubspec.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/dart/http.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/dart/models.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/dart/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/dart/program.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/django/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/django/extras.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/django/models.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/django/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/django/schemas.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/django/shapes.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/django/urls.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/express/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/express/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/flutter/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/flutter/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/kotlin/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/kotlin/exact.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/kotlin/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/kotlin/reparse.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/laravel/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/laravel/broadcast.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/laravel/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/laravel/tests.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/laravel/values.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/native/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/native/gates.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/native/runner.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/native/scipread.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/native/ts.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/nest/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/nest/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/nextjs/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/nextjs/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/nuxt/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/nuxt/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/php/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/php/external.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/php/extractor/composer.json +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/php/extractor/composer.lock +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/php/extractor/extract.php +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/php/gating.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/php/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/php/strings.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/python/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/python/aitools.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/python/fields.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/python/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/python/refs.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/python/roots.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/python/socketio.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/python/subproc.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/python/tests.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/python/values.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/pyweb/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/pyweb/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/pyweb/values.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/rust/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/rust/cargo.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/rust/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/rust/syntax.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/scip/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/scip/importer.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/scip/scip.proto +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/scip/scip_pb2.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/stubs/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/stubs/plugins.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/swift/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/swift/baseurl.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/swift/exact.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/swift/indexstore.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/swift/packages.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/swift/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/ts/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/ts/baseurl.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/ts/extractor/extract.mjs +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/ts/extractor/fw.mjs +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/ts/extractor/package-lock.json +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/ts/extractor/package.json +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/ts/nav.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/ts/plugin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/tsweb/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/tsweb/common.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/plugins/tsweb/data.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/c_cpp.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/common.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/dart.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/django-ninja.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/django.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/djangorestframework.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/express.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/kotlin.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/laravel.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/nest.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/nextjs.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/nuxt.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/php.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/python.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/rust.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/swift.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/presets/typescript.yaml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/process_runs.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/protocols/builtin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/protocols/matchers.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/protocols/view.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/realtime.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/realtime_events.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/realtime_native.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/realtime_ws.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/roundtrip.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/routes.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/rpc.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/sockets.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/starters.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/tests_index.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/udp_apps.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/__init__.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/graph.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/server.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/static/app.css +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/static/app.js +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/static/index.html +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/static/layered.js +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/static/vendor/VERSIONS.txt +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/static/vendor/cose-base.js +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/static/vendor/cytoscape-fcose.js +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/static/vendor/cytoscape.min.js +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/static/vendor/layout-base.js +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/tools/package-lock.json +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/tools/package.json +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/viz/tools/shoot.mjs +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/webhooks.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/codegraph/xcode.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/pyproject.toml +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/setup.cfg +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_agents_install.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_agents_md.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_ai_tools.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_android_ipc.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_apple_ipc.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_bridges.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_bridges_pigeon_monorepo.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_brokers.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_cache_clean.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_cache_invalidation.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_channels_tests.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_cli_output.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_completeness.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_coverage.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_coverage_ts_hint.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_dart_isolates.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_dispatch_interfaces.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_django_flutter.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_enum_constants.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_gating.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_generated.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_graphql.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_impact_overrides.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_index_isolation.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_inherited_overrides.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_jobs.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_js_refs.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_kotlin.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_kotlin_binding.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_kotlin_exact.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_kotlin_fields.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_kotlin_mixed.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_kotlin_nav_consts.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_kotlin_props.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_laravel_determinism.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_laravel_resources.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_lint_async.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_local_ipc.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_local_sockets.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_mcp.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_mcp_index.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_native_cfamily.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_native_concurrency.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_native_rust.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_nuxt_import_dirs.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_nuxt_rootsrc.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_packaging.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_parity.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_parity_structure.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_php_props.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_plain_js.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_plans.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_platform_gaps.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_platform_type_variants.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_platforms.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_platforms_apple.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_presets_config.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_process_ipc.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_process_runs.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_protocols.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_app_tests_module.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_collection_chains.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_compat.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_entry_refs.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_fields.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_infer_cycles.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_roots.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_subprocess_tests.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_tests.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_web_hosts.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_web_routes.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_python_web_routes_more.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_realtime.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_realtime_native.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_roundtrip.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_route_tables.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_routes_search_explain.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_rpc.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_scip_health.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_snippet.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_sockets.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_starters_budget.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_binding.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_exact.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_facts.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_fields.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_modules.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_more.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_nav_values.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_parse_errors.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_props.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_sdk.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_testing.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_swift_values.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_tests_scope.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_ts_fields.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_ts_fields_js_vue.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_ts_file_specs.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_ts_frameworks.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_ts_nuxt.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_values.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_viz.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_vue_nav.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_webhooks.py +0 -0
- {cg_code_graph-0.12.0 → cg_code_graph-0.13.0}/tests/test_websockets.py +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cg-code-graph
|
|
3
|
+
Version: 0.13.0
|
|
4
|
+
Summary: cg: a code graph of routes, calls, data access and platform boundaries for agents and humans (CLI + MCP server)
|
|
5
|
+
Author: cyberchronos00
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/cyberchronos00/code-graph
|
|
8
|
+
Project-URL: Changelog, https://github.com/cyberchronos00/code-graph/blob/main/CHANGELOG.md
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: mcp>=2.2
|
|
13
|
+
Requires-Dist: pyyaml>=6
|
|
14
|
+
Requires-Dist: protobuf>=4.21
|
|
15
|
+
Requires-Dist: tree-sitter>=0.23
|
|
16
|
+
Requires-Dist: tree-sitter-rust>=0.23
|
|
17
|
+
Requires-Dist: tree-sitter-c>=0.23
|
|
18
|
+
Requires-Dist: tree-sitter-cpp>=0.23
|
|
19
|
+
Requires-Dist: tree-sitter-kotlin>=1.0
|
|
20
|
+
Requires-Dist: tree-sitter-swift<0.7.4,>=0.6
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# code-graph
|
|
26
|
+
|
|
27
|
+
**A deterministic dependency graph for Laravel, Django, FastAPI, Flask, NestJS, Next.js, Express, Nuxt, Flutter, Rust, C and C++ codebases, so you (and your AI agent) can see everything a change touches before you make it.**
|
|
28
|
+
|
|
29
|
+
Ask "what depends on this table, connection, config key or method?" and get every caller, route, command and page that reaches it, each hop backed by `file:line` evidence. It runs locally on your source files. Answers are exact, deterministic and reproducible: the graph is built from parsers and the type checker, with no LLM in the graph. BloodHound-style: you walk real paths instead of grepping names.
|
|
30
|
+
|
|
31
|
+
> **Status:** beta. Laravel (PHP), Django, FastAPI / Starlette and Flask (Python), TypeScript/JavaScript (Nuxt/Vue, NestJS, Next.js, Express/Fastify/Koa/Hono), Flutter (Dart), Rust, C and C++ are supported natively; other languages can be imported through SCIP.
|
|
32
|
+
|
|
33
|
+
## Documentation
|
|
34
|
+
|
|
35
|
+
**[code-graph docs](https://code-graph.cyberchronos00.workers.dev/)** — install, CLI, MCP, architecture, schema, languages and limitations.
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
`cg` is a user-level tool (no sudo, no checkout). The PyPI package is [`cg-code-graph`](https://pypi.org/project/cg-code-graph/); the commands are `cg` and `cg-mcp`.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pipx install cg-code-graph # or: uv tool install cg-code-graph
|
|
43
|
+
# or the script (also installs exact-mode tools with --with c,rust,...):
|
|
44
|
+
# curl -fsSL https://raw.githubusercontent.com/cyberchronos00/code-graph/main/install.sh | sh
|
|
45
|
+
# or the latest commit: uv tool install git+https://github.com/cyberchronos00/code-graph
|
|
46
|
+
cg doctor # what indexes exact / heuristic on this machine
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Update with `uv tool upgrade cg-code-graph`, `pipx upgrade cg-code-graph` or `install.sh --update`. Caches live under `~/.cache/codegraph`; `cg clean` removes them. Windows, options and per-language toolchains: [install](https://code-graph.cyberchronos00.workers.dev/).
|
|
50
|
+
|
|
51
|
+
## Quickstart
|
|
52
|
+
|
|
53
|
+
Clone the repo for the bundled sample apps (a Laravel API and a Nuxt web app). Python 3.11+. PHP 8.2+ and Composer for the Laravel sample; Node.js 20+ for the TypeScript samples.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/cyberchronos00/code-graph.git && cd code-graph
|
|
57
|
+
mkdir -p out
|
|
58
|
+
cg index examples/bookstore-api --name bookstore-api --gates examples/bookstore.gates.json --db out/api.db
|
|
59
|
+
cg index examples/bookstore-web --name bookstore-web --db out/web.db
|
|
60
|
+
cg link --backend out/api.db --frontend out/web.db \
|
|
61
|
+
--backend-name bookstore-api --frontend-name bookstore-web --db out/graph.db
|
|
62
|
+
|
|
63
|
+
cg reaches connection:warehouse table:warehouse_stock --db out/graph.db
|
|
64
|
+
cg impact StockService::reserve --db out/graph.db
|
|
65
|
+
cg path page:/reports/:id table:orders --db out/graph.db
|
|
66
|
+
cg plan check preorders --plans-dir examples/plans --db out/graph.db
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
A workspace `.cg.yaml` can list several apps, including checkouts outside that directory, and `cg index` builds one combined graph. `cg link --repo` merges graphs you already indexed. Other samples in `examples/` (Nest, Next, Express, Django, Flutter, Rust, C, C++) index the same way. Queries, MCP (`cg-mcp --db out/graph.db`) and `cg serve` are in the [docs](https://code-graph.cyberchronos00.workers.dev/).
|
|
70
|
+
|
|
71
|
+
## Preview
|
|
72
|
+
|
|
73
|
+
[](docs/media/cg-view-demo.mp4)
|
|
74
|
+
|
|
75
|
+
[](docs/media/cg-terminal-demo.mp4)
|
|
76
|
+
|
|
77
|
+
More recordings (setup, visual view, agent over MCP): [docs/media/](docs/media).
|
|
78
|
+
|
|
79
|
+
## Links
|
|
80
|
+
|
|
81
|
+
- [Documentation](https://code-graph.cyberchronos00.workers.dev/)
|
|
82
|
+
- [PyPI: cg-code-graph](https://pypi.org/project/cg-code-graph/)
|
|
83
|
+
- [GitHub releases](https://github.com/cyberchronos00/code-graph/releases)
|
|
84
|
+
- [Changelog](CHANGELOG.md) · [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md) · [License: MIT](LICENSE)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# code-graph
|
|
2
|
+
|
|
3
|
+
**A deterministic dependency graph for Laravel, Django, FastAPI, Flask, NestJS, Next.js, Express, Nuxt, Flutter, Rust, C and C++ codebases, so you (and your AI agent) can see everything a change touches before you make it.**
|
|
4
|
+
|
|
5
|
+
Ask "what depends on this table, connection, config key or method?" and get every caller, route, command and page that reaches it, each hop backed by `file:line` evidence. It runs locally on your source files. Answers are exact, deterministic and reproducible: the graph is built from parsers and the type checker, with no LLM in the graph. BloodHound-style: you walk real paths instead of grepping names.
|
|
6
|
+
|
|
7
|
+
> **Status:** beta. Laravel (PHP), Django, FastAPI / Starlette and Flask (Python), TypeScript/JavaScript (Nuxt/Vue, NestJS, Next.js, Express/Fastify/Koa/Hono), Flutter (Dart), Rust, C and C++ are supported natively; other languages can be imported through SCIP.
|
|
8
|
+
|
|
9
|
+
## Documentation
|
|
10
|
+
|
|
11
|
+
**[code-graph docs](https://code-graph.cyberchronos00.workers.dev/)** — install, CLI, MCP, architecture, schema, languages and limitations.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
`cg` is a user-level tool (no sudo, no checkout). The PyPI package is [`cg-code-graph`](https://pypi.org/project/cg-code-graph/); the commands are `cg` and `cg-mcp`.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pipx install cg-code-graph # or: uv tool install cg-code-graph
|
|
19
|
+
# or the script (also installs exact-mode tools with --with c,rust,...):
|
|
20
|
+
# curl -fsSL https://raw.githubusercontent.com/cyberchronos00/code-graph/main/install.sh | sh
|
|
21
|
+
# or the latest commit: uv tool install git+https://github.com/cyberchronos00/code-graph
|
|
22
|
+
cg doctor # what indexes exact / heuristic on this machine
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Update with `uv tool upgrade cg-code-graph`, `pipx upgrade cg-code-graph` or `install.sh --update`. Caches live under `~/.cache/codegraph`; `cg clean` removes them. Windows, options and per-language toolchains: [install](https://code-graph.cyberchronos00.workers.dev/).
|
|
26
|
+
|
|
27
|
+
## Quickstart
|
|
28
|
+
|
|
29
|
+
Clone the repo for the bundled sample apps (a Laravel API and a Nuxt web app). Python 3.11+. PHP 8.2+ and Composer for the Laravel sample; Node.js 20+ for the TypeScript samples.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git clone https://github.com/cyberchronos00/code-graph.git && cd code-graph
|
|
33
|
+
mkdir -p out
|
|
34
|
+
cg index examples/bookstore-api --name bookstore-api --gates examples/bookstore.gates.json --db out/api.db
|
|
35
|
+
cg index examples/bookstore-web --name bookstore-web --db out/web.db
|
|
36
|
+
cg link --backend out/api.db --frontend out/web.db \
|
|
37
|
+
--backend-name bookstore-api --frontend-name bookstore-web --db out/graph.db
|
|
38
|
+
|
|
39
|
+
cg reaches connection:warehouse table:warehouse_stock --db out/graph.db
|
|
40
|
+
cg impact StockService::reserve --db out/graph.db
|
|
41
|
+
cg path page:/reports/:id table:orders --db out/graph.db
|
|
42
|
+
cg plan check preorders --plans-dir examples/plans --db out/graph.db
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
A workspace `.cg.yaml` can list several apps, including checkouts outside that directory, and `cg index` builds one combined graph. `cg link --repo` merges graphs you already indexed. Other samples in `examples/` (Nest, Next, Express, Django, Flutter, Rust, C, C++) index the same way. Queries, MCP (`cg-mcp --db out/graph.db`) and `cg serve` are in the [docs](https://code-graph.cyberchronos00.workers.dev/).
|
|
46
|
+
|
|
47
|
+
## Preview
|
|
48
|
+
|
|
49
|
+
[](docs/media/cg-view-demo.mp4)
|
|
50
|
+
|
|
51
|
+
[](docs/media/cg-terminal-demo.mp4)
|
|
52
|
+
|
|
53
|
+
More recordings (setup, visual view, agent over MCP): [docs/media/](docs/media).
|
|
54
|
+
|
|
55
|
+
## Links
|
|
56
|
+
|
|
57
|
+
- [Documentation](https://code-graph.cyberchronos00.workers.dev/)
|
|
58
|
+
- [PyPI: cg-code-graph](https://pypi.org/project/cg-code-graph/)
|
|
59
|
+
- [GitHub releases](https://github.com/cyberchronos00/code-graph/releases)
|
|
60
|
+
- [Changelog](CHANGELOG.md) · [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md) · [License: MIT](LICENSE)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cg-code-graph
|
|
3
|
+
Version: 0.13.0
|
|
4
|
+
Summary: cg: a code graph of routes, calls, data access and platform boundaries for agents and humans (CLI + MCP server)
|
|
5
|
+
Author: cyberchronos00
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/cyberchronos00/code-graph
|
|
8
|
+
Project-URL: Changelog, https://github.com/cyberchronos00/code-graph/blob/main/CHANGELOG.md
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: mcp>=2.2
|
|
13
|
+
Requires-Dist: pyyaml>=6
|
|
14
|
+
Requires-Dist: protobuf>=4.21
|
|
15
|
+
Requires-Dist: tree-sitter>=0.23
|
|
16
|
+
Requires-Dist: tree-sitter-rust>=0.23
|
|
17
|
+
Requires-Dist: tree-sitter-c>=0.23
|
|
18
|
+
Requires-Dist: tree-sitter-cpp>=0.23
|
|
19
|
+
Requires-Dist: tree-sitter-kotlin>=1.0
|
|
20
|
+
Requires-Dist: tree-sitter-swift<0.7.4,>=0.6
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# code-graph
|
|
26
|
+
|
|
27
|
+
**A deterministic dependency graph for Laravel, Django, FastAPI, Flask, NestJS, Next.js, Express, Nuxt, Flutter, Rust, C and C++ codebases, so you (and your AI agent) can see everything a change touches before you make it.**
|
|
28
|
+
|
|
29
|
+
Ask "what depends on this table, connection, config key or method?" and get every caller, route, command and page that reaches it, each hop backed by `file:line` evidence. It runs locally on your source files. Answers are exact, deterministic and reproducible: the graph is built from parsers and the type checker, with no LLM in the graph. BloodHound-style: you walk real paths instead of grepping names.
|
|
30
|
+
|
|
31
|
+
> **Status:** beta. Laravel (PHP), Django, FastAPI / Starlette and Flask (Python), TypeScript/JavaScript (Nuxt/Vue, NestJS, Next.js, Express/Fastify/Koa/Hono), Flutter (Dart), Rust, C and C++ are supported natively; other languages can be imported through SCIP.
|
|
32
|
+
|
|
33
|
+
## Documentation
|
|
34
|
+
|
|
35
|
+
**[code-graph docs](https://code-graph.cyberchronos00.workers.dev/)** — install, CLI, MCP, architecture, schema, languages and limitations.
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
`cg` is a user-level tool (no sudo, no checkout). The PyPI package is [`cg-code-graph`](https://pypi.org/project/cg-code-graph/); the commands are `cg` and `cg-mcp`.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pipx install cg-code-graph # or: uv tool install cg-code-graph
|
|
43
|
+
# or the script (also installs exact-mode tools with --with c,rust,...):
|
|
44
|
+
# curl -fsSL https://raw.githubusercontent.com/cyberchronos00/code-graph/main/install.sh | sh
|
|
45
|
+
# or the latest commit: uv tool install git+https://github.com/cyberchronos00/code-graph
|
|
46
|
+
cg doctor # what indexes exact / heuristic on this machine
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Update with `uv tool upgrade cg-code-graph`, `pipx upgrade cg-code-graph` or `install.sh --update`. Caches live under `~/.cache/codegraph`; `cg clean` removes them. Windows, options and per-language toolchains: [install](https://code-graph.cyberchronos00.workers.dev/).
|
|
50
|
+
|
|
51
|
+
## Quickstart
|
|
52
|
+
|
|
53
|
+
Clone the repo for the bundled sample apps (a Laravel API and a Nuxt web app). Python 3.11+. PHP 8.2+ and Composer for the Laravel sample; Node.js 20+ for the TypeScript samples.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/cyberchronos00/code-graph.git && cd code-graph
|
|
57
|
+
mkdir -p out
|
|
58
|
+
cg index examples/bookstore-api --name bookstore-api --gates examples/bookstore.gates.json --db out/api.db
|
|
59
|
+
cg index examples/bookstore-web --name bookstore-web --db out/web.db
|
|
60
|
+
cg link --backend out/api.db --frontend out/web.db \
|
|
61
|
+
--backend-name bookstore-api --frontend-name bookstore-web --db out/graph.db
|
|
62
|
+
|
|
63
|
+
cg reaches connection:warehouse table:warehouse_stock --db out/graph.db
|
|
64
|
+
cg impact StockService::reserve --db out/graph.db
|
|
65
|
+
cg path page:/reports/:id table:orders --db out/graph.db
|
|
66
|
+
cg plan check preorders --plans-dir examples/plans --db out/graph.db
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
A workspace `.cg.yaml` can list several apps, including checkouts outside that directory, and `cg index` builds one combined graph. `cg link --repo` merges graphs you already indexed. Other samples in `examples/` (Nest, Next, Express, Django, Flutter, Rust, C, C++) index the same way. Queries, MCP (`cg-mcp --db out/graph.db`) and `cg serve` are in the [docs](https://code-graph.cyberchronos00.workers.dev/).
|
|
70
|
+
|
|
71
|
+
## Preview
|
|
72
|
+
|
|
73
|
+
[](docs/media/cg-view-demo.mp4)
|
|
74
|
+
|
|
75
|
+
[](docs/media/cg-terminal-demo.mp4)
|
|
76
|
+
|
|
77
|
+
More recordings (setup, visual view, agent over MCP): [docs/media/](docs/media).
|
|
78
|
+
|
|
79
|
+
## Links
|
|
80
|
+
|
|
81
|
+
- [Documentation](https://code-graph.cyberchronos00.workers.dev/)
|
|
82
|
+
- [PyPI: cg-code-graph](https://pypi.org/project/cg-code-graph/)
|
|
83
|
+
- [GitHub releases](https://github.com/cyberchronos00/code-graph/releases)
|
|
84
|
+
- [Changelog](CHANGELOG.md) · [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md) · [License: MIT](LICENSE)
|
|
@@ -48,6 +48,7 @@ codegraph/realtime_ws.py
|
|
|
48
48
|
codegraph/roundtrip.py
|
|
49
49
|
codegraph/routes.py
|
|
50
50
|
codegraph/rpc.py
|
|
51
|
+
codegraph/sdk_systems.py
|
|
51
52
|
codegraph/sockets.py
|
|
52
53
|
codegraph/starters.py
|
|
53
54
|
codegraph/tests_index.py
|
|
@@ -214,6 +215,7 @@ tests/test_coverage_ts_hint.py
|
|
|
214
215
|
tests/test_dart_isolates.py
|
|
215
216
|
tests/test_dispatch_interfaces.py
|
|
216
217
|
tests/test_django_flutter.py
|
|
218
|
+
tests/test_docs_links.py
|
|
217
219
|
tests/test_enum_constants.py
|
|
218
220
|
tests/test_external.py
|
|
219
221
|
tests/test_gating.py
|
|
@@ -276,6 +278,7 @@ tests/test_route_tables.py
|
|
|
276
278
|
tests/test_routes_search_explain.py
|
|
277
279
|
tests/test_rpc.py
|
|
278
280
|
tests/test_scip_health.py
|
|
281
|
+
tests/test_sdk_external.py
|
|
279
282
|
tests/test_snippet.py
|
|
280
283
|
tests/test_sockets.py
|
|
281
284
|
tests/test_starters_budget.py
|
|
@@ -302,4 +305,5 @@ tests/test_values.py
|
|
|
302
305
|
tests/test_viz.py
|
|
303
306
|
tests/test_vue_nav.py
|
|
304
307
|
tests/test_webhooks.py
|
|
305
|
-
tests/test_websockets.py
|
|
308
|
+
tests/test_websockets.py
|
|
309
|
+
tests/test_workspace_link.py
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""code-graph: deterministic code knowledge graph (beta)."""
|
|
2
|
-
__version__ = "0.
|
|
2
|
+
__version__ = "0.13.0"
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Workspace apps (`.cg.yaml` `apps`): one `cg index <root>` indexes every app into one combined graph.
|
|
2
|
+
|
|
3
|
+
apps:
|
|
4
|
+
- {name: api, root: apps/api, role: backend}
|
|
5
|
+
- {name: web, root: apps/web, role: frontend, links: [api]} # links: the backends it calls (default: all)
|
|
6
|
+
- {name: other, root: ../other-repo, role: backend} # root may sit outside this checkout
|
|
7
|
+
|
|
8
|
+
`cg index <root> --db out/mono.db` writes `out/mono.<app>.db` per app and one combined `out/mono.db`.
|
|
9
|
+
Client HTTP calls in every app are matched against every other backend; a frontend `links:` list limits that app.
|
|
10
|
+
Each app is indexed with its own `.cg.yaml` (at the app root), like a separate checkout.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import shutil
|
|
15
|
+
import time
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
from .config import ConfigError
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def app_dbs(db: str | Path, apps: list[dict]) -> dict:
|
|
22
|
+
"""App name -> per-app DB path next to `db`."""
|
|
23
|
+
db = Path(db)
|
|
24
|
+
stem = db.name[:-3] if db.name.endswith(".db") else db.name
|
|
25
|
+
return {a["name"]: db.parent / f"{stem}.{a['name']}.db" for a in apps}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def app_path(root: Path, rel: str) -> Path:
|
|
29
|
+
"""Directory for an app root: empty means the workspace root; absolute is used as-is; `../x` resolves."""
|
|
30
|
+
if not rel:
|
|
31
|
+
return root
|
|
32
|
+
p = Path(rel)
|
|
33
|
+
return p if p.is_absolute() else (root / rel).resolve()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def index_apps(root: str | Path, db: str | Path, cfg: dict, scip=None, python_roots=None,
|
|
37
|
+
include_generated: bool = False) -> dict:
|
|
38
|
+
"""Index each app of `cfg["apps"]` and link them into one graph. Returns per-app and per-pair stats."""
|
|
39
|
+
from .indexer import index_project
|
|
40
|
+
from .link import link_many
|
|
41
|
+
t0 = time.time()
|
|
42
|
+
root = Path(root).resolve()
|
|
43
|
+
apps = cfg["apps"]
|
|
44
|
+
fname = cfg.get("file", ".cg.yaml")
|
|
45
|
+
located = []
|
|
46
|
+
for a in apps:
|
|
47
|
+
d = app_path(root, a["root"]) if a["root"] else root
|
|
48
|
+
if not d.is_dir():
|
|
49
|
+
raise ConfigError(f"{fname}: apps[{a['name']}].root: {a['root']!r} is not a directory under {root.name}")
|
|
50
|
+
located.append(d)
|
|
51
|
+
per_app = app_dbs(db, apps)
|
|
52
|
+
Path(db).parent.mkdir(parents=True, exist_ok=True)
|
|
53
|
+
out = {"project": root.name, "config": fname, "apps": [], "links": []}
|
|
54
|
+
for a, d in zip(apps, located):
|
|
55
|
+
st = index_project(d, per_app[a["name"]], a["name"], scip, python_roots=python_roots,
|
|
56
|
+
include_generated=include_generated)
|
|
57
|
+
out["apps"].append({"name": a["name"], "root": a["root"] or ".", "role": a["role"], "db": str(per_app[a["name"]]),
|
|
58
|
+
"nodes": st.get("nodes"), "edges": st.get("edges"), "index_seconds": st.get("index_seconds"),
|
|
59
|
+
"frameworks": sorted(((st.get("presets") or {}).get("frameworks") or {}))})
|
|
60
|
+
if len(apps) == 1:
|
|
61
|
+
shutil.copyfile(per_app[apps[0]["name"]], db)
|
|
62
|
+
out["db_is"] = f"graph of app {apps[0]['name']}"
|
|
63
|
+
else:
|
|
64
|
+
allow = {a["name"]: a["links"] for a in apps if "links" in a}
|
|
65
|
+
res = link_many([(a["name"], str(per_app[a["name"]]), a["role"]) for a in apps], str(db), allow=allow)
|
|
66
|
+
s = res["stats"]
|
|
67
|
+
for p in s.get("pairs") or []:
|
|
68
|
+
out["links"].append({"frontend": p["client"], "backend": p["server"], "db": str(db),
|
|
69
|
+
"endpoints": p.get("endpoints"), "endpoints_matched": p.get("endpoints_matched"),
|
|
70
|
+
"call_sites": p.get("call_sites"), "call_sites_matched": p.get("call_sites_matched"),
|
|
71
|
+
"link_seconds": s.get("link_seconds")})
|
|
72
|
+
out["db_is"] = "combined graph of " + ", ".join(a["name"] for a in apps)
|
|
73
|
+
out["db"] = str(db)
|
|
74
|
+
out["index_seconds"] = round(time.time() - t0, 2)
|
|
75
|
+
return out
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def render(summary: dict) -> str:
|
|
79
|
+
lines = [f"apps of {summary['project']} ({summary['config']}): {len(summary['apps'])} indexed, "
|
|
80
|
+
f"{len(summary['links'])} link pairs in {summary['index_seconds']} s"]
|
|
81
|
+
for a in summary["apps"]:
|
|
82
|
+
lines.append(f" {a['name']:<16} {a['role']:<8} {a['root']:<28} {a['nodes']} nodes, {a['edges']} edges, "
|
|
83
|
+
f"{a['index_seconds']} s -> {Path(a['db']).name}")
|
|
84
|
+
for ln in summary["links"]:
|
|
85
|
+
lines.append(f" {ln['frontend']} -> {ln['backend']}: {ln['endpoints_matched']}/{ln['endpoints']} endpoints, "
|
|
86
|
+
f"{ln['call_sites_matched']}/{ln['call_sites']} call sites matched")
|
|
87
|
+
lines.append(f" {Path(summary['db']).name}: {summary['db_is']}")
|
|
88
|
+
return "\n".join(lines)
|
|
@@ -37,6 +37,23 @@ from . import query as Q
|
|
|
37
37
|
from .bridges import PROTOCOLS as BRIDGE_PROTOCOLS
|
|
38
38
|
|
|
39
39
|
|
|
40
|
+
def _parse_repo(spec: str) -> tuple[str, str, str]:
|
|
41
|
+
"""`NAME=DB[:role]` with role backend, frontend or both (default both)."""
|
|
42
|
+
if "=" not in spec:
|
|
43
|
+
raise ValueError(f"--repo {spec!r} must be NAME=DB[:role]")
|
|
44
|
+
name, rest = spec.split("=", 1)
|
|
45
|
+
if not name or not rest:
|
|
46
|
+
raise ValueError(f"--repo {spec!r} must be NAME=DB[:role]")
|
|
47
|
+
role = "both"
|
|
48
|
+
for r in ("backend", "frontend", "both"):
|
|
49
|
+
if rest.endswith(":" + r):
|
|
50
|
+
role, rest = r, rest[:-(len(r) + 1)]
|
|
51
|
+
break
|
|
52
|
+
if not rest:
|
|
53
|
+
raise ValueError(f"--repo {spec!r} must be NAME=DB[:role]")
|
|
54
|
+
return name, rest, role
|
|
55
|
+
|
|
56
|
+
|
|
40
57
|
def main(argv=None):
|
|
41
58
|
from . import __version__
|
|
42
59
|
ap = argparse.ArgumentParser(prog="cg")
|
|
@@ -93,9 +110,13 @@ def main(argv=None):
|
|
|
93
110
|
p.add_argument("--details", action="store_true", help="the full report: file lists (the first 5 per bucket), fix hints, "
|
|
94
111
|
"syntax error lines, Python source roots (default: a short summary)")
|
|
95
112
|
p.add_argument("--all-files", action="store_true", help="the full report with every file per bucket, excluded files too")
|
|
96
|
-
p = sub.add_parser("link", help="
|
|
97
|
-
p.add_argument("--backend",
|
|
113
|
+
p = sub.add_parser("link", help="merge graphs and match client HTTP calls to routes (two repos, or N --repo)")
|
|
114
|
+
p.add_argument("--backend", help="backend graph (with --frontend; not with --repo)")
|
|
115
|
+
p.add_argument("--frontend", help="frontend graph (with --backend; not with --repo)")
|
|
116
|
+
p.add_argument("--db", required=True)
|
|
98
117
|
p.add_argument("--backend-name", default="backend"); p.add_argument("--frontend-name", default="frontend")
|
|
118
|
+
p.add_argument("--repo", action="append", default=[], metavar="NAME=DB[:ROLE]",
|
|
119
|
+
help="repeatable. ROLE is backend, frontend or both (default both). Not with --backend/--frontend")
|
|
99
120
|
p.add_argument("--report", help="write <prefix>.json/.md match report")
|
|
100
121
|
p = sub.add_parser("path", help="one shortest evidence chain from SRC to DST (exit status 1 when there is none)"); p.add_argument("src"); p.add_argument("dst"); p.add_argument("--db", required=True)
|
|
101
122
|
p.add_argument("--min-confidence", default="heuristic", choices=["heuristic", "resolved", "exact"])
|
|
@@ -260,7 +281,7 @@ def main(argv=None):
|
|
|
260
281
|
from .config import ConfigError, load as load_config
|
|
261
282
|
try:
|
|
262
283
|
cfg = load_config(a.root) if not a.no_apps else {}
|
|
263
|
-
if cfg.get("apps"): #
|
|
284
|
+
if cfg.get("apps"): # workspace: index each app into one combined graph
|
|
264
285
|
from .apps import index_apps, render as render_apps
|
|
265
286
|
summary = index_apps(a.root, a.db, cfg, a.scip, python_roots=a.python_root,
|
|
266
287
|
include_generated=a.include_generated)
|
|
@@ -341,8 +362,25 @@ def main(argv=None):
|
|
|
341
362
|
print(render(covs, all_files=a.all_files) if a.details or a.all_files else render_summary(covs))
|
|
342
363
|
return
|
|
343
364
|
if a.cmd == "link":
|
|
344
|
-
from .link import link, write_match_report
|
|
345
|
-
|
|
365
|
+
from .link import link, link_many, write_match_report
|
|
366
|
+
if a.repo and (a.backend or a.frontend):
|
|
367
|
+
print("cg link: --repo cannot be combined with --backend/--frontend", file=sys.stderr)
|
|
368
|
+
return 2
|
|
369
|
+
try:
|
|
370
|
+
if a.repo:
|
|
371
|
+
if len(a.repo) < 2:
|
|
372
|
+
print("cg link: pass at least two --repo NAME=DB[:role]", file=sys.stderr)
|
|
373
|
+
return 2
|
|
374
|
+
repos = [_parse_repo(s) for s in a.repo]
|
|
375
|
+
res = link_many(repos, a.db)
|
|
376
|
+
elif a.backend and a.frontend:
|
|
377
|
+
res = link(a.backend, a.frontend, a.db, a.backend_name, a.frontend_name)
|
|
378
|
+
else:
|
|
379
|
+
print("cg link: pass --backend and --frontend, or repeated --repo NAME=DB[:role]", file=sys.stderr)
|
|
380
|
+
return 2
|
|
381
|
+
except ValueError as ex:
|
|
382
|
+
print(f"cg link: {ex}", file=sys.stderr)
|
|
383
|
+
return 2
|
|
346
384
|
if a.report:
|
|
347
385
|
write_match_report(res, a.report)
|
|
348
386
|
print(json.dumps(res["stats"], indent=2))
|
|
@@ -33,9 +33,10 @@ Records project-specific knowledge once, for the CLI, the MCP server and the vis
|
|
|
33
33
|
viz:
|
|
34
34
|
presets: # canned queries in the visual view's starter cards
|
|
35
35
|
- {id: orders_writes, label: what writes the orders table, mode: reaches, specs: ["table:orders"]}
|
|
36
|
-
apps: #
|
|
36
|
+
apps: # workspace: `cg index <root>` indexes each app into one combined graph
|
|
37
37
|
- {name: api, root: apps/api, role: backend}
|
|
38
38
|
- {name: web, root: apps/web, role: frontend, links: [api]} # links: backends it calls (default: all)
|
|
39
|
+
# root may also be absolute or ../other-repo (a workspace of separate checkouts)
|
|
39
40
|
|
|
40
41
|
Command-line flags take precedence over the file. Top-level keys this version does not read are kept and reported
|
|
41
42
|
in the index stats (and as a warning by `cg config validate`), so a file written for a newer cg still indexes."""
|
|
@@ -75,6 +76,17 @@ def find(root: str | Path) -> Path | None:
|
|
|
75
76
|
return None
|
|
76
77
|
|
|
77
78
|
|
|
79
|
+
def norm_app_root(value: Any, where: str) -> str:
|
|
80
|
+
"""An app directory: relative to the workspace (`apps/api`, `./src`, `.`), `../other-repo`, or absolute."""
|
|
81
|
+
if not isinstance(value, str) or not value.strip():
|
|
82
|
+
raise ConfigError(f"{where}: expected a directory path, got {value!r}")
|
|
83
|
+
v = value.strip().replace("\\", "/")
|
|
84
|
+
if re.match(r"^[A-Za-z]:/", v) or v.startswith("/"):
|
|
85
|
+
return v.rstrip("/") or "/"
|
|
86
|
+
s = str(PurePosixPath(v))
|
|
87
|
+
return "" if s == "." else s
|
|
88
|
+
|
|
89
|
+
|
|
78
90
|
def norm_root(value: Any, where: str) -> str:
|
|
79
91
|
"""A repo-relative directory: 'lib', 'tools/scripts/', './src', '.'. Absolute paths and '..' are rejected."""
|
|
80
92
|
if not isinstance(value, str) or not value.strip():
|
|
@@ -309,8 +321,8 @@ def parse(data: Any, fname: str = ".cg.yaml") -> dict:
|
|
|
309
321
|
|
|
310
322
|
def _apps(v: Any, fname: str) -> list[dict]:
|
|
311
323
|
"""apps as a list of {name, root, role, links} (or a mapping name -> {root, role, links}), validated: unique names,
|
|
312
|
-
|
|
313
|
-
links to every backend."""
|
|
324
|
+
role backend / frontend, links naming backend apps. `root` may be relative, `../other-repo` or absolute.
|
|
325
|
+
A frontend without `links` links to every backend."""
|
|
314
326
|
if isinstance(v, dict):
|
|
315
327
|
v = [dict(x or {}, name=k) if isinstance(x, dict) or x is None else x for k, x in v.items()]
|
|
316
328
|
if not isinstance(v, list) or not v:
|
|
@@ -329,7 +341,7 @@ def _apps(v: Any, fname: str) -> list[dict]:
|
|
|
329
341
|
if name in names:
|
|
330
342
|
raise ConfigError(f"{where}.name: {name!r} is used by two apps")
|
|
331
343
|
names.add(name)
|
|
332
|
-
root =
|
|
344
|
+
root = norm_app_root(a.get("root") if a.get("root") is not None else name, f"{where}.root")
|
|
333
345
|
role = a.get("role", "backend")
|
|
334
346
|
if role not in APP_ROLES:
|
|
335
347
|
raise ConfigError(f"{where}.role: expected backend or frontend, got {role!r}")
|