Skip to content

Commit 208e4e8

Browse files
feat: add Angular framework support for understand analysis
1 parent 0e8ad84 commit 208e4e8

5 files changed

Lines changed: 106 additions & 3 deletions

File tree

understand-anything-plugin/agents/project-scanner.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ From these, synthesize:
4343
- **`name`** -- in priority order: `package.json` `name`, `Cargo.toml` `[package].name`, `go.mod` module path's last segment, `pyproject.toml` `[project].name` or `[tool.poetry].name`, else the directory name of the project root.
4444
- **`rawDescription`** -- the `description` field from `package.json` (or its equivalent in the matching manifest), or `""` if none.
4545
- **`readmeHead`** -- the first ~10 lines of `README.md` (or equivalent), or `""` if no README exists.
46-
- **`frameworks`** -- match dependency names against known frameworks: `react`, `vue`, `svelte`, `@angular/core`, `express`, `fastify`, `koa`, `next`, `nuxt`, `vite`, `vitest`, `jest`, `mocha`, `tailwindcss`, `prisma`, `typeorm`, `sequelize`, `mongoose`, `redux`, `zustand`, `mobx`; Python: `django`, `djangorestframework`, `fastapi`, `flask`, `sqlalchemy`, `alembic`, `celery`, `pydantic`, `uvicorn`, `gunicorn`, `aiohttp`, `tornado`, `starlette`, `pytest`, `hypothesis`, `channels`; Ruby: `rails`, `railties`, `sinatra`, `grape`, `rspec`, `sidekiq`, `activerecord`, `actionpack`, `devise`, `pundit`; Go: `github.com/gin-gonic/gin`, `github.com/labstack/echo`, `github.com/gofiber/fiber`, `github.com/go-chi/chi`, `gorm.io/gorm`; Rust: `actix-web`, `axum`, `rocket`, `diesel`, `tokio`, `serde`, `warp`; JVM: `spring-boot`, `spring-web`, `spring-data`, `quarkus`, `micronaut`, `hibernate`, `jakarta`, `junit`, `ktor`. Also infer infrastructure tools from manifest presence: add `Docker` if `Dockerfile` exists in the file list, `Docker Compose` if `docker-compose.yml`/`docker-compose.yaml` exists, `Terraform` if any `*.tf`, `GitHub Actions` if `.github/workflows/*.yml`, `GitLab CI` if `.gitlab-ci.yml`, `Jenkins` if `Jenkinsfile`.
46+
- **`frameworks`** -- match dependency names against known frameworks: `react`, `vue`, `svelte`, `angular` (match `@angular/core` in dependencies), `express`, `fastify`, `koa`, `next`, `nuxt`, `vite`, `vitest`, `jest`, `mocha`, `tailwindcss`, `prisma`, `typeorm`, `sequelize`, `mongoose`, `redux`, `zustand`, `mobx`; Python: `django`, `djangorestframework`, `fastapi`, `flask`, `sqlalchemy`, `alembic`, `celery`, `pydantic`, `uvicorn`, `gunicorn`, `aiohttp`, `tornado`, `starlette`, `pytest`, `hypothesis`, `channels`; Ruby: `rails`, `railties`, `sinatra`, `grape`, `rspec`, `sidekiq`, `activerecord`, `actionpack`, `devise`, `pundit`; Go: `github.com/gin-gonic/gin`, `github.com/labstack/echo`, `github.com/gofiber/fiber`, `github.com/go-chi/chi`, `gorm.io/gorm`; Rust: `actix-web`, `axum`, `rocket`, `diesel`, `tokio`, `serde`, `warp`; JVM: `spring-boot`, `spring-web`, `spring-data`, `quarkus`, `micronaut`, `hibernate`, `jakarta`, `junit`, `ktor`. Also infer infrastructure tools from manifest presence: add `Docker` if `Dockerfile` exists in the file list, `Docker Compose` if `docker-compose.yml`/`docker-compose.yaml` exists, `Terraform` if any `*.tf`, `GitHub Actions` if `.github/workflows/*.yml`, `GitLab CI` if `.gitlab-ci.yml`, `Jenkins` if `Jenkinsfile`.
4747
- **`languages`** -- the deduplicated, alphabetically-sorted top-level language set you observe across the manifests + the bundled script's per-file language tally (you will read this from Step B's output).
4848

4949
If the manifest is missing or malformed, leave the corresponding field empty rather than guessing.

understand-anything-plugin/packages/core/src/__tests__/framework-registry.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ describe("FrameworkRegistry", () => {
106106
});
107107

108108
describe("createDefault", () => {
109-
it("registers all 10 built-in framework configs", () => {
109+
it("registers all 11 built-in framework configs", () => {
110110
const registry = FrameworkRegistry.createDefault();
111-
expect(registry.getAllFrameworks()).toHaveLength(10);
111+
expect(registry.getAllFrameworks()).toHaveLength(11);
112112
});
113113

114114
it("includes frameworks for multiple languages", () => {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { FrameworkConfig } from "../types.js";
2+
3+
export const angularConfig = {
4+
id: "angular",
5+
displayName: "Angular",
6+
languages: ["typescript", "javascript"],
7+
detectionKeywords: ["@angular/core", "@angular/common", "@angular/router"],
8+
manifestFiles: ["package.json"],
9+
promptSnippetPath: "./frameworks/angular.md",
10+
entryPoints: [
11+
"src/main.ts",
12+
"src/app/app.component.ts",
13+
"src/app/app.config.ts",
14+
"src/app/app.routes.ts",
15+
"src/app/app.module.ts",
16+
],
17+
layerHints: {
18+
components: "ui",
19+
services: "service",
20+
guards: "middleware",
21+
interceptors: "middleware",
22+
pipes: "utility",
23+
directives: "utility",
24+
models: "types",
25+
environments: "config",
26+
},
27+
} satisfies FrameworkConfig;

understand-anything-plugin/packages/core/src/languages/frameworks/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { reactConfig } from "./react.js";
77
import { nextjsConfig } from "./nextjs.js";
88
import { expressConfig } from "./express.js";
99
import { vueConfig } from "./vue.js";
10+
import { angularConfig } from "./angular.js";
1011
import { springConfig } from "./spring.js";
1112
import { railsConfig } from "./rails.js";
1213
import { ginConfig } from "./gin.js";
@@ -19,6 +20,7 @@ export const builtinFrameworkConfigs: FrameworkConfig[] = [
1920
nextjsConfig,
2021
expressConfig,
2122
vueConfig,
23+
angularConfig,
2224
springConfig,
2325
railsConfig,
2426
ginConfig,
@@ -32,6 +34,7 @@ export {
3234
nextjsConfig,
3335
expressConfig,
3436
vueConfig,
37+
angularConfig,
3538
springConfig,
3639
railsConfig,
3740
ginConfig,
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Angular Framework Addendum
2+
3+
> Injected into file-analyzer and architecture-analyzer prompts when Angular is detected.
4+
> Do NOT use as a standalone prompt — always appended to the base prompt template.
5+
6+
## Angular Project Structure
7+
8+
When analyzing an Angular project, apply these additional conventions on top of the base analysis rules.
9+
10+
### Canonical File Roles
11+
12+
| File / Pattern | Role | Tags |
13+
|---|---|---|
14+
| `src/main.ts` | Application bootstrap — calls `bootstrapApplication()` or `platformBrowserDynamic().bootstrapModule()` | `entry-point`, `config` |
15+
| `src/app/app.component.ts` | Root application component — top-level shell and router outlet | `entry-point`, `ui` |
16+
| `src/app/app.config.ts` | Standalone app configuration — providers, router, interceptors, animations | `config` |
17+
| `src/app/app.routes.ts`, `src/app/app-routing.module.ts` | Route definitions — path-to-component mapping, lazy routes, guards | `config`, `routing` |
18+
| `src/app/app.module.ts` | Root NgModule (legacy) — declares bootstrap component, imports feature modules | `config` |
19+
| `**/*.component.ts` | UI components — template, styles, and component class with selector | `ui` |
20+
| `**/*.component.html` | Component templates — declarative view markup bound to the component class | `ui` |
21+
| `**/*.component.scss`, `**/*.component.css` | Component-scoped styles | `ui` |
22+
| `**/*.import.const.ts` | Standalone component import bundles — grouped `imports` arrays for reuse | `config`, `utility` |
23+
| `**/*.service.ts` | Injectable services — business logic, HTTP clients, state, facades | `service` |
24+
| `**/*.guard.ts` | Route guards — `CanActivate`, `CanDeactivate`, `CanMatch` authorization/navigation checks | `middleware`, `routing` |
25+
| `**/*.interceptor.ts` | HTTP interceptors — request/response mutation, auth headers, error handling | `middleware`, `service` |
26+
| `**/*.resolver.ts` | Route resolvers — prefetch data before route activation | `service`, `routing` |
27+
| `**/*.pipe.ts` | Template pipes — synchronous value transformations in templates | `utility` |
28+
| `**/*.directive.ts` | Attribute and structural directives — DOM behavior and template control flow | `utility` |
29+
| `**/*.module.ts` | Feature NgModules (legacy) — group declarations, imports, providers, routing | `config` |
30+
| `**/models/*.ts`, `**/interfaces/*.ts` | Domain models, DTOs, and shared TypeScript interfaces | `type-definition` |
31+
| `environments/*.ts` | Environment-specific configuration (API URLs, feature flags) | `config` |
32+
| `**/*.spec.ts` | Unit and integration tests (Jasmine/Karma or Jest) | `test` |
33+
34+
### Edge Patterns to Look For
35+
36+
**Component composition** — When a parent component template references a child component selector (e.g., `<app-user-card>`), create `contains` edges from the parent component to the child. Check both inline templates and external `.component.html` files. `imports` arrays in standalone components list direct composition dependencies.
37+
38+
**Dependency injection** — When a class constructor or `inject()` call requests a service/token, create `depends_on` edges from the consumer to the provider. Follow `providedIn: 'root'`, route-level `providers`, and `bootstrapApplication({ providers: [...] })` to trace where services are registered. Factory providers and `InjectionToken` bindings are config-to-service edges.
39+
40+
**Input/output bindings** — When a parent passes `[input]` or listens to `(output)` on a child selector, create `depends_on` edges from parent to child. `input()` / `output()` signal-based APIs and legacy `@Input()` / `@Output()` decorators both indicate parent-child data coupling.
41+
42+
**Router configuration** — When `app.routes.ts` or a routing module maps paths to components or `loadChildren`/`loadComponent` lazy imports, create `configures` edges from the router file to each routed component or lazy chunk entry. Guards and resolvers referenced in route definitions add middleware edges.
43+
44+
**NgModule wiring (legacy)** — When an `*.module.ts` file lists components in `declarations` or modules in `imports`, create `contains` and `depends_on` edges reflecting the module graph. `RouterModule.forChild(routes)` links feature modules to their route tables.
45+
46+
**HTTP and state flow** — When a component or resolver calls a service method that returns an `Observable` or `Promise`, create `depends_on` from the consumer to the service. NgRx/store actions, selectors, and effects form a state subgraph: components `dispatch` actions, effects `depend_on` services, selectors `depend_on` state slices.
47+
48+
**Standalone import bundles** — When a `*.import.const.ts` file exports a shared `imports` array consumed by multiple standalone components, create `depends_on` edges from each consumer component to the bundle and from the bundle to its listed dependencies.
49+
50+
### Architectural Layers for Angular
51+
52+
Assign nodes to these layers when detected:
53+
54+
| Layer ID | Layer Name | What Goes Here |
55+
|---|---|---|
56+
| `layer:ui` | UI Layer | `*.component.ts`, templates, feature/page components, layouts |
57+
| `layer:service` | Service Layer | `*.service.ts`, facades, API clients, NgRx stores/effects, resolvers |
58+
| `layer:middleware` | Middleware Layer | `*.guard.ts`, `*.interceptor.ts`, route guards, HTTP middleware |
59+
| `layer:config` | Config Layer | `app.config.ts`, `app.module.ts`, `app.routes.ts`, `environments/`, `*.module.ts`, `*.import.const.ts` |
60+
| `layer:utility` | Utility Layer | `*.pipe.ts`, `*.directive.ts`, pure helpers, shared validators |
61+
| `layer:types` | Types Layer | `models/`, `interfaces/`, shared DTOs and type definitions |
62+
| `layer:test` | Test Layer | `*.spec.ts`, test harnesses and mocks |
63+
64+
### Notable Patterns to Capture in languageLesson
65+
66+
- **Standalone components over NgModules**: Modern Angular (v14+) favors `standalone: true` components with explicit `imports` arrays; `bootstrapApplication()` replaces `NgModule`-based bootstrapping in new projects
67+
- **Signals and computed state**: `signal()`, `computed()`, and `effect()` provide fine-grained reactivity — trace signal reads/writes when analyzing component state flow
68+
- **Dependency injection hierarchy**: Services use `@Injectable({ providedIn: 'root' })` for app-wide singletons; feature-scoped providers live on routes or component `providers` arrays
69+
- **RxJS for async streams**: HTTP, router events, and complex async flows use Observables — `subscribe`, `async` pipe, and operators (`map`, `switchMap`, `catchError`) indicate data-flow paths
70+
- **OnPush change detection**: Components with `changeDetection: ChangeDetectionStrategy.OnPush` only re-render when inputs change or events fire — marks performance-sensitive UI
71+
- **Lazy-loaded feature routes**: `loadComponent` and `loadChildren` split the app into lazy chunks — each lazy entry is a feature boundary worth capturing as a module node
72+
- **Control flow syntax**: Built-in `@if`, `@for`, and `@switch` in templates replace structural directives (`*ngIf`, `*ngFor`) — both styles may coexist during migration
73+
- **Import const bundles**: `componentName.import.const.ts` files centralize standalone `imports` for large components — a project-specific composition pattern that reduces duplication across related views

0 commit comments

Comments
 (0)