@mnemonica/tactica 0.1.15 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -5
- package/lib/analyzer.d.ts +59 -2
- package/lib/analyzer.js +346 -21
- package/lib/cli.d.ts +4 -1
- package/lib/cli.js +222 -7
- package/lib/creation-graph.d.ts +131 -0
- package/lib/creation-graph.js +568 -0
- package/lib/index.d.ts +8 -2
- package/lib/index.js +11 -3
- package/lib/module-graph.d.ts +109 -0
- package/lib/module-graph.js +690 -0
- package/lib/plugins.d.ts +44 -0
- package/lib/plugins.js +27 -0
- package/lib/scopes.d.ts +113 -0
- package/lib/scopes.js +582 -0
- package/lib/topologica-analyzer.js +13 -10
- package/lib/types.d.ts +320 -0
- package/lib/types.js +1 -1
- package/lib/writer.d.ts +14 -1
- package/lib/writer.js +61 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -134,8 +134,11 @@ Tactica writes everything under the `--output` directory (default `.tactica/`):
|
|
|
134
134
|
| `index.ts` | default mode | Re-exports everything from `types.ts` and `registry.ts`. |
|
|
135
135
|
| `index.d.ts` | with `--module-augmentation` | Single global-augmentation file (legacy mode). |
|
|
136
136
|
| `definitions.json` | always | One entry per discovered type: `{ name, location, kind: 'define'\|'decorate', parent, strictChain, blockErrors }`. Consumed by `mnemographica`'s Go to Definition. |
|
|
137
|
-
| `usages.json` | always | One entry per type, value is an array of `{ location, kind, code }` records — where each type is instantiated, referenced, accessed, or looked up. Consumed by `mnemographica`'s Find References. |
|
|
137
|
+
| `usages.json` | always | One entry per type, value is an array of `{ location, kind, code, holderScopeId?, constructorText? }` records — where each type is instantiated, referenced, accessed, or looked up. `holderScopeId` points into `scopes.json` (the innermost scope holding the usage); `constructorText` (instantiations only) is the constructor expression text actually used. Consumed by `mnemographica`'s Find References. |
|
|
138
138
|
| `flow.json` | always | Native instance-flow patterns (property reads/writes, method calls, destructuring, returns, spreads, etc.) per type. |
|
|
139
|
+
| `instrumentation.json` | always | v2 envelope. `points`: framework lifecycle crossroads (interceptors, guards, pipes, filters, middleware) detected via **plugin-supplied vocabulary** — heritage declarations, decorator sites, provider-token registrations, `consumer.apply()` wiring. Syntactic only — no dive dependency; with no plugins loaded, `points` is `[]`. `creationGraph`: the inside-out walk from every instantiation site out to the starters — see "Creation graph" below. |
|
|
140
|
+
| `modules.json` | always | Module-scope graph: every module's `exportedBindings`/`importedBindings` (functions, classes, consts, types — not only mnemonica types), project-internal `dependencies`, `builtinSpecifiers` (Node builtins are skipped entirely — both `'path'` and `'node:path'` forms), `unresolvedSpecifiers`, circular-import `cycles`, and cross-module mnemonica-type `edges`. Resolution uses `ts.resolveModuleName` with the project's compilerOptions (tsconfig `paths`, extensionless imports, index files) — no type checker. Bindings resolved into `node_modules` are marked `external: true` and never enter `dependencies`. |
|
|
141
|
+
| `scopes.json` | always | Local-scope graph: function/method/arrow scopes only (no block scopes) plus one module scope per file; variables with `typePath` (mnemonica type when known), `isParameter`, `isMutable`, and `reassignments` — each reassignment of a mutable binding is a flow-termination point. |
|
|
139
142
|
| `eds.json` | when EDS enabled | Execution-flow patterns (`wrap`, `current`, `getFlow`, `attachHooks` lifecycle wiring). Consumed by tools that visualize execution chains. |
|
|
140
143
|
|
|
141
144
|
### Default mode (types.ts + registry.ts)
|
|
@@ -474,7 +477,7 @@ When inference fails the property's type falls back to `unknown` (or `any` in so
|
|
|
474
477
|
|
|
475
478
|
```ts
|
|
476
479
|
class MnemonicaAnalyzer {
|
|
477
|
-
constructor(program?: ts.Program);
|
|
480
|
+
constructor(program?: ts.Program, plugins?: TacticaPlugin[]);
|
|
478
481
|
|
|
479
482
|
analyzeFile(sourceFile: ts.SourceFile): AnalyzeResult;
|
|
480
483
|
analyzeSource(sourceCode: string, fileName?: string): AnalyzeResult;
|
|
@@ -487,6 +490,7 @@ class MnemonicaAnalyzer {
|
|
|
487
490
|
getUsages(): Map<string, UsageInfo[]>;
|
|
488
491
|
getEDSUsages(): Map<string, EDSInfo[]>;
|
|
489
492
|
getFlowUsages(): Map<string, FlowInfo[]>;
|
|
493
|
+
getInstrumentationPoints(): InstrumentationPoint[];
|
|
490
494
|
}
|
|
491
495
|
```
|
|
492
496
|
|
|
@@ -534,6 +538,61 @@ class TypesGenerator {
|
|
|
534
538
|
}
|
|
535
539
|
```
|
|
536
540
|
|
|
541
|
+
### `ModuleGraphBuilder`
|
|
542
|
+
|
|
543
|
+
Module-scope walker. Tracks every export/import binding of every module —
|
|
544
|
+
generically, not only mnemonica types — and resolves specifiers with
|
|
545
|
+
`ts.resolveModuleName` driven by the program's compilerOptions
|
|
546
|
+
(no `getTypeChecker()`).
|
|
547
|
+
|
|
548
|
+
```ts
|
|
549
|
+
class ModuleGraphBuilder {
|
|
550
|
+
constructor(program?: ts.Program, compilerOptions?: ts.CompilerOptions);
|
|
551
|
+
|
|
552
|
+
addFile(sourceFile: ts.SourceFile): ModuleInfo; // call per file (definitions pass)
|
|
553
|
+
build(definedTypesByFile?: Map<string, string[]>): ModuleGraph;
|
|
554
|
+
}
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
`ModuleGraph` = `{ modules: Map<absPath, ModuleInfo>, edges: CrossModuleUsage[], cycles: string[][] }`.
|
|
558
|
+
Each `ModuleBinding` carries `{ name, kind: 'function'|'class'|'const'|'type'|'unknown',
|
|
559
|
+
sourceModule (resolved absolute path), importKind?, importAlias?, isReExport, external? }`.
|
|
560
|
+
Node.js builtins (`'path'`, `'node:fs'`, …) are skipped entirely and recorded
|
|
561
|
+
only in the module's `builtinSpecifiers`; bindings resolved into `node_modules`
|
|
562
|
+
carry `external: true` and never enter `dependencies`. Re-export chains
|
|
563
|
+
(barrels, `export * from`) are chased to the origin module when producing
|
|
564
|
+
`edges`; circular imports are recorded in `cycles`, never treated as errors.
|
|
565
|
+
Unused-export detection is internal only — nothing about it is emitted.
|
|
566
|
+
|
|
567
|
+
### `LocalScopeWalker`
|
|
568
|
+
|
|
569
|
+
Local-scope walker. Tracks function/method/arrow scopes only (no block
|
|
570
|
+
scopes), plus one synthetic module scope per file. Variables carry
|
|
571
|
+
`isParameter`, `isMutable` (const vs let/var; `this` parameters are
|
|
572
|
+
immutable), and `reassignments` — every reassignment site of a mutable
|
|
573
|
+
binding is a flow-termination point where downstream walking stops.
|
|
574
|
+
|
|
575
|
+
```ts
|
|
576
|
+
class LocalScopeWalker {
|
|
577
|
+
addFile(sourceFile: ts.SourceFile): void; // call per file
|
|
578
|
+
build(resolver?: ScopeTypeResolver): ScopeAnalysis;
|
|
579
|
+
findHolderScopeId(location: string): string | undefined;
|
|
580
|
+
|
|
581
|
+
static attachHolderScopeIds(usages: Map<string, UsageInfo[]>, walker: LocalScopeWalker): void;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
interface ScopeTypeResolver {
|
|
585
|
+
resolveByName(name: string): string | undefined; // bare name → mnemonica fullPath
|
|
586
|
+
hasPath(fullPath: string): boolean;
|
|
587
|
+
}
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
`ScopeAnalysis` = `{ scopes: Map<scopeId, ScopeInfo>, variables: Map<'scopeId#name', ScopeVariable> }`.
|
|
591
|
+
Scope ids: module scope = file path; function scopes = `file:line:col`.
|
|
592
|
+
Labels: functions by name, methods as `Class.method`, arrows by the binding
|
|
593
|
+
they are assigned to, anonymous holders as `file:line`. Never relies on
|
|
594
|
+
`node.parent` (program files can be unbound).
|
|
595
|
+
|
|
537
596
|
### `TypesWriter`
|
|
538
597
|
|
|
539
598
|
```ts
|
|
@@ -548,6 +607,9 @@ class TypesWriter {
|
|
|
548
607
|
writeUsagesFile (map: Map<string, UsageInfo[]>): string; // → outputDir/usages.json
|
|
549
608
|
writeEDSFile (map: Map<string, EDSInfo[]>): string; // → outputDir/eds.json
|
|
550
609
|
writeFlowFile (map: Map<string, FlowInfo[]>): string; // → outputDir/flow.json
|
|
610
|
+
writeInstrumentationFile(points: InstrumentationPoint[], creationGraph?: CreationGraph): string; // → outputDir/instrumentation.json
|
|
611
|
+
writeModulesFile (graph: ModuleGraph): string; // → outputDir/modules.json
|
|
612
|
+
writeScopesFile (analysis: ScopeAnalysis): string; // → outputDir/scopes.json
|
|
551
613
|
|
|
552
614
|
write(generated: GeneratedTypes): string; // legacy alias for writeTypesFile
|
|
553
615
|
clean(): void;
|
|
@@ -557,7 +619,7 @@ class TypesWriter {
|
|
|
557
619
|
|
|
558
620
|
### Types
|
|
559
621
|
|
|
560
|
-
`TacticaConfig`, `TypeNode`, `TypeGraph`, `PropertyInfo`, `ConstructorParamInfo`, `AnalyzeResult`, `AnalyzeError`, `GeneratedTypes`, `DefinitionInfo`, `UsageInfo`, `UsagesJson`, `DefinitionsJson`, `EDSInfo`, `EDSJson`, `EDSKind`, `FlowInfo`, `FlowJson`, `FlowKind` — all exported from `@mnemonica/tactica`. See [`src/types.ts`](src/types.ts) for the full schema.
|
|
622
|
+
`TacticaConfig`, `TypeNode`, `TypeGraph`, `PropertyInfo`, `ConstructorParamInfo`, `AnalyzeResult`, `AnalyzeError`, `GeneratedTypes`, `DefinitionInfo`, `UsageInfo`, `UsagesJson`, `DefinitionsJson`, `EDSInfo`, `EDSJson`, `EDSKind`, `FlowInfo`, `FlowJson`, `FlowKind`, `InstrumentationKind`, `InstrumentationScope`, `InstrumentationPoint`, `InstrumentationJson`, `ModuleBindingKind`, `ModuleImportKind`, `ModuleBinding`, `ModuleInfo`, `CrossModuleUsage`, `ModuleGraph`, `ModulesJson`, `ScopeKind`, `ScopeInfo`, `ScopeVariable`, `ScopeAnalysis`, `ScopesJson`, `CreationGraphNode`, `CreationGraphEdge`, `CreationAnchor`, `CreationGraph`, `TacticaPlugin`, `InstrumentationVocabulary` — all exported from `@mnemonica/tactica`. See [`src/types.ts`](src/types.ts) for the full schema. The `mergeTacticaPlugins(plugins)` helper merges plugin vocabulary the same way the analyzer does.
|
|
561
623
|
|
|
562
624
|
## EDS (Execution Data Storage) Tracking
|
|
563
625
|
|
|
@@ -567,7 +629,7 @@ When enabled, tactica detects execution-flow patterns alongside type definitions
|
|
|
567
629
|
|---|---|---|
|
|
568
630
|
| `wrap(fn)`, `wrapConstructorArg(fn, parent)`, `upgradeConstructorArg(arg, inst)`, `wrapInstanceMethods(obj)` | `wrap` | Wrap a function / constructor argument / instance methods for context propagation and tracing (`@mnemonica/dive`) |
|
|
569
631
|
| `current()`, `getErrorInstance(err)`, `getFlow(target?)` | `contextConsume` | Read the current context, the error-pinned instance, or the recorded flow (`@mnemonica/dive`) |
|
|
570
|
-
| `attachHooks(collection)` | `hookAttach` | Wire a TypesCollection to dive's lifecycle tracing (`@mnemonica/
|
|
632
|
+
| `attachHooks(collection)` | `hookAttach` | Wire a TypesCollection to dive's lifecycle tracing (`@mnemonica/otel`) |
|
|
571
633
|
|
|
572
634
|
`eds.json` structure:
|
|
573
635
|
|
|
@@ -588,12 +650,110 @@ When enabled, tactica detects execution-flow patterns alongside type definitions
|
|
|
588
650
|
}
|
|
589
651
|
```
|
|
590
652
|
|
|
653
|
+
`wrap` entries additionally carry graph-join fields (all optional, additive):
|
|
654
|
+
|
|
655
|
+
- `label` — the label string literal of `wrap(fn, …, 'label')` when statically visible.
|
|
656
|
+
- `callbackScopeId` — the scopeId (scopes.json) of the wrapped callback's own scope; the callback is what the wrapper runs, so graph consumers join on it first.
|
|
657
|
+
- `instanceArg` — the identifier passed as the instance/context argument (`user` in `wrap(fn, user)`), when it is one.
|
|
658
|
+
- `scopeId` — the scopeId of the scope holding the wrap call site (fallback join).
|
|
659
|
+
- `wrapsTypePath` — the mnemonica fullPath of the instance argument, resolved through the scope-variable chain (innermost binding wins; an untyped local shadows a typed outer one rather than being guessed).
|
|
660
|
+
- `via` — the location of the enclosing wrap site when the call is nested inside another wrapped body (or returns a function): the wrappers-graph generation chain is built from it.
|
|
661
|
+
|
|
662
|
+
## Instrumentation Points
|
|
663
|
+
|
|
664
|
+
Tactica statically detects framework lifecycle crossroads — interceptors, guards, pipes, exception filters, middleware — purely syntactically (no type checker), and always emits `.tactica/instrumentation.json`. **Tactica core ships no framework vocabulary**: detection is driven entirely by plugins, so with no plugins loaded `points` is `[]`. Framework adapters ship a plugin; projects enable it through a `.tactica.js` (or `tactica.config.js`) config file next to `tsconfig.json`:
|
|
665
|
+
|
|
666
|
+
```js
|
|
667
|
+
// .tactica.js
|
|
668
|
+
module.exports = {
|
|
669
|
+
plugins: [ '@mnemonica/example-adapter/tactica' ],
|
|
670
|
+
};
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
Plugin entries are module specifiers (required relative to the config file) or inline plugin objects. A plugin is a plain object:
|
|
674
|
+
|
|
675
|
+
```ts
|
|
676
|
+
interface TacticaPlugin {
|
|
677
|
+
name?: string;
|
|
678
|
+
// `implements X` heritage matches: interface identifier -> kind
|
|
679
|
+
instrumentationInterfaces?: Record<string, InstrumentationKind>;
|
|
680
|
+
// `@X(Impl)` decorator sites: decorator identifier -> kind
|
|
681
|
+
useDecorators?: Record<string, InstrumentationKind>;
|
|
682
|
+
// `{ provide: TOKEN, useClass: Impl }` registrations: token identifier -> kind
|
|
683
|
+
appTokens?: Record<string, InstrumentationKind>;
|
|
684
|
+
// opt in to shape-based `consumer.apply(Mw).forRoutes(...)` detection
|
|
685
|
+
middlewareWiring?: boolean;
|
|
686
|
+
}
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
Programmatic callers pass plugins directly: `new MnemonicaAnalyzer(program, plugins)` or `run({ …, plugins })`; config-file plugins append after programmatic ones, and later plugins override earlier ones on the same identifier key. Detection covers:
|
|
690
|
+
|
|
691
|
+
- **Heritage** — `class X implements <plugin-listed interface>` (matched by interface identifier name). Bare declarations carry scope `module` (attachment statically unknown).
|
|
692
|
+
- **Decorator sites** — plugin-listed decorators on classes or methods, including inline instances (`@Register(new Impl(…))`). One point per referenced class; scope is `controller:<Name>` or `method:<Class>.<method>`.
|
|
693
|
+
- **Global providers** — `{ provide: <plugin-listed token>, useClass: X }` object literals → scope `global`. `useExisting`/`useFactory` without `useClass` are skipped.
|
|
694
|
+
- **Middleware wiring** — `consumer.apply(Mw).forRoutes(...)` inside a class's `configure()` method → scope `module`, targets from `forRoutes` arguments when statically readable. Requires `middlewareWiring: true` from any loaded plugin.
|
|
695
|
+
|
|
696
|
+
When a referenced class is declared in the analyzed project, the point's `location`/`code` resolve to the class declaration; external classes keep the registration site. Points are deduped by `(kind, className, location, scope)` with `targets` merged — a class seen via both heritage and a decorator yields separate entries per scope, with the bare declaration carrying scope `module`.
|
|
697
|
+
|
|
698
|
+
`instrumentation.json` structure (v2):
|
|
699
|
+
|
|
700
|
+
```json
|
|
701
|
+
{
|
|
702
|
+
"version": 2,
|
|
703
|
+
"generatedAt": "2026-09-04T…",
|
|
704
|
+
"points": [
|
|
705
|
+
{
|
|
706
|
+
"kind": "pipe",
|
|
707
|
+
"className": "PayloadPipe",
|
|
708
|
+
"location": "/project/src/user.controller.ts:49:2",
|
|
709
|
+
"code": "@RegisterPipe(new PayloadPipe({ transform: true }))",
|
|
710
|
+
"scope": "method:UserController.createUser",
|
|
711
|
+
"targets": ["UserController"]
|
|
712
|
+
}
|
|
713
|
+
],
|
|
714
|
+
"creationGraph": {
|
|
715
|
+
"nodes": [
|
|
716
|
+
{
|
|
717
|
+
"scopeId": "/project/src/main.ts",
|
|
718
|
+
"name": "/project/src/main.ts",
|
|
719
|
+
"kind": "module",
|
|
720
|
+
"filePath": "/project/src/main.ts",
|
|
721
|
+
"location": "/project/src/main.ts:1:1",
|
|
722
|
+
"starter": true
|
|
723
|
+
}
|
|
724
|
+
],
|
|
725
|
+
"edges": [
|
|
726
|
+
{ "caller": "/project/src/main.ts", "callee": "/project/src/user.service.ts:26:2" }
|
|
727
|
+
],
|
|
728
|
+
"anchors": [
|
|
729
|
+
{
|
|
730
|
+
"location": "/project/src/user.service.ts:29:24",
|
|
731
|
+
"holderScopeId": "/project/src/user.service.ts:26:2",
|
|
732
|
+
"typePath": "UserEntity.UserResponse",
|
|
733
|
+
"constructorText": "user.UserResponse",
|
|
734
|
+
"variable": "userResponse"
|
|
735
|
+
}
|
|
736
|
+
]
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
## Creation graph (inside-out walk)
|
|
742
|
+
|
|
743
|
+
The `creationGraph` key is the third phase of the instrumentation walker: it starts at the certain points — every `usages.json` `instantiation` entry (each carries a `holderScopeId` into `scopes.json`) — and walks **outward**: who invokes or references the holder function, crossing files through `modules.json` (re-export barrels chased to the origin module), until no callers remain. Terminals are the **starters** (application entry points); the walk never assumes a linear type Trie (mnemonica `strictChain: false` permits cycles and out-of-order construction), so traversal is cycle-guarded and every anchor records the constructor expression actually used.
|
|
744
|
+
|
|
745
|
+
- **Nodes** are scopes (`module` / `function` / `method` / `arrow`), labeled like `scopes.json`; `starter: true` marks nodes with no discovered callers.
|
|
746
|
+
- **Edges** point `caller → callee`, where the callee is closer to the creation site.
|
|
747
|
+
- **Anchors** pin each creation site to its holder scope: `typePath`, the `constructorText` used, `rooted: true` for module-scope creations (a legitimate root or a developer error — labeled, not policed), and a `variable`/`terminatedAt` pair from a documented heuristic: the variable declared in the holder scope on the same line as the creation (typePath must match when known), with `terminatedAt` being that variable's first reassignment site — the flow-termination point where the walk stops following the binding.
|
|
748
|
+
|
|
749
|
+
Deliberate approximations (name-based, no type checker): namespace imports count any reference to the alias once the namespace's module exposes the holder's export; method holders bind to their **class** name (that is what callers reference); any non-declaration identifier counts as a reference. Export wiring alone (`export { f }`, `export default f`) is not a caller — an importer's usage creates the edge.
|
|
750
|
+
|
|
591
751
|
## How It Works
|
|
592
752
|
|
|
593
753
|
1. **Parse** — load `tsconfig.json`, build a `ts.Program`, walk each source file's AST.
|
|
594
754
|
2. **Detect** — find `define()` and `@decorate()` calls, plus `lookup` lookups, `new` expressions, and EDS / flow patterns.
|
|
595
755
|
3. **Graph** — build a Trie of types in `TypeGraphImpl`, with parent links via the chain of `.define()` calls and `@decorate(Parent)` references.
|
|
596
|
-
4. **Generate** — emit `types.ts`, `registry.ts`, `index.ts` (default mode) or `index.d.ts` (legacy mode), plus `definitions.json`, `usages.json
|
|
756
|
+
4. **Generate** — emit `types.ts`, `registry.ts`, `index.ts` (default mode) or `index.d.ts` (legacy mode), plus `definitions.json`, `usages.json` (with `holderScopeId`), `flow.json`, `instrumentation.json`, `modules.json`, `scopes.json`, `hierarchy.json`/`hierarchy.txt`, and optionally `eds.json`.
|
|
597
757
|
5. **Write** — files land in the output directory (default `.tactica/`).
|
|
598
758
|
|
|
599
759
|
```
|
package/lib/analyzer.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
import { AnalyzeResult, DefinitionInfo, UsageInfo, EDSInfo, FlowInfo } from './types';
|
|
2
|
+
import { AnalyzeResult, DefinitionInfo, UsageInfo, EDSInfo, FlowInfo, InstrumentationPoint } from './types';
|
|
3
3
|
import { TypeGraphImpl } from './graph';
|
|
4
|
+
import { TacticaPlugin } from './plugins';
|
|
4
5
|
/**
|
|
5
6
|
* AST Analyzer for finding Mnemonica define() and decorate() calls
|
|
7
|
+
*
|
|
8
|
+
* Framework-blind by construction: instrumentation detection vocabulary
|
|
9
|
+
* (interface names, decorator names, provider tokens, middleware wiring)
|
|
10
|
+
* comes entirely from plugins — with none loaded, zero points are collected.
|
|
6
11
|
*/
|
|
7
12
|
export declare class MnemonicaAnalyzer {
|
|
8
13
|
private errors;
|
|
@@ -22,7 +27,10 @@ export declare class MnemonicaAnalyzer {
|
|
|
22
27
|
private collectionVariables;
|
|
23
28
|
private collectionInfo;
|
|
24
29
|
private collectionCounter;
|
|
25
|
-
|
|
30
|
+
private instrumentationClassDecls;
|
|
31
|
+
private instrumentationSites;
|
|
32
|
+
private instrumentationVocabulary;
|
|
33
|
+
constructor(program?: ts.Program, plugins?: TacticaPlugin[]);
|
|
26
34
|
/**
|
|
27
35
|
* Reset usage-related state for a fresh pass.
|
|
28
36
|
* Call before the usage-collection pass to avoid duplicates from definition pass.
|
|
@@ -56,6 +64,17 @@ export declare class MnemonicaAnalyzer {
|
|
|
56
64
|
* Get collected flow usages
|
|
57
65
|
*/
|
|
58
66
|
getFlowUsages(): Map<string, FlowInfo[]>;
|
|
67
|
+
/**
|
|
68
|
+
* Get collected instrumentation points.
|
|
69
|
+
* Registration sites referencing a class declared in the same project
|
|
70
|
+
* resolve to the class declaration's location/code; external classes
|
|
71
|
+
* (e.g., a framework-builtin implementation from node_modules) keep
|
|
72
|
+
* the registration site.
|
|
73
|
+
* Deduped by kind+className+location+scope with targets merged — a
|
|
74
|
+
* class detected by heritage AND by a decorator site yields separate
|
|
75
|
+
* entries with distinct scopes (see InstrumentationPoint in types.ts).
|
|
76
|
+
*/
|
|
77
|
+
getInstrumentationPoints(): InstrumentationPoint[];
|
|
59
78
|
/**
|
|
60
79
|
* Add a topologica type to the analyzer for usage tracking.
|
|
61
80
|
* This allows the analyzer to recognize topologica types when collecting usages.
|
|
@@ -462,4 +481,42 @@ export declare class MnemonicaAnalyzer {
|
|
|
462
481
|
* Extract constructor parameters from a constructor expression.
|
|
463
482
|
*/
|
|
464
483
|
private extractConstructorParamsFromConstructor;
|
|
484
|
+
/**
|
|
485
|
+
* Collect framework instrumentation points. Purely syntactic: heritage
|
|
486
|
+
* clauses, decorator application sites, provider-token object literals
|
|
487
|
+
* and consumer.apply().forRoutes() wiring. The vocabulary comes from
|
|
488
|
+
* plugins; identifier text is matched as-is — no import resolution,
|
|
489
|
+
* the type checker stays unused.
|
|
490
|
+
*/
|
|
491
|
+
private collectInstrumentation;
|
|
492
|
+
/**
|
|
493
|
+
* Record a named class declaration for instrumentation site resolution
|
|
494
|
+
* and detect heritage-based kinds (`implements <plugin interface>`)
|
|
495
|
+
*/
|
|
496
|
+
private collectInstrumentationClass;
|
|
497
|
+
/**
|
|
498
|
+
* Detect decorator application sites: plugin-listed decorators applied
|
|
499
|
+
* with class arguments on a class or one of its methods. One site per
|
|
500
|
+
* referenced class identifier.
|
|
501
|
+
*/
|
|
502
|
+
private collectInstrumentationDecorator;
|
|
503
|
+
/**
|
|
504
|
+
* Detect global registrations: object literals shaped like
|
|
505
|
+
* `{ provide: <plugin-listed token>, useClass: X }`.
|
|
506
|
+
* useExisting/useFactory without a useClass identifier are not
|
|
507
|
+
* statically obvious — skipped rather than guessed.
|
|
508
|
+
*/
|
|
509
|
+
private collectInstrumentationProvider;
|
|
510
|
+
/**
|
|
511
|
+
* Detect middleware wiring: `consumer.apply(Mw1, Mw2).forRoutes(...)`
|
|
512
|
+
* inside a class's configure() method. Targets come from forRoutes
|
|
513
|
+
* arguments when statically readable (string routes or controller
|
|
514
|
+
* identifiers), else []. Shape-based, so a plugin must opt in via
|
|
515
|
+
* `middlewareWiring: true`.
|
|
516
|
+
*/
|
|
517
|
+
private collectInstrumentationMiddleware;
|
|
518
|
+
/**
|
|
519
|
+
* Walk up the parent chain looking for an enclosing configure() method
|
|
520
|
+
*/
|
|
521
|
+
private isInsideConfigureMethod;
|
|
465
522
|
}
|