@genvidtech/c3-domain-manager 0.0.1 → 0.6.1
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/LICENSE +18 -0
- package/README.md +195 -29
- package/dist/adapters/locations.d.ts +22 -0
- package/dist/adapters/locations.d.ts.map +1 -0
- package/dist/adapters/locations.js +42 -0
- package/dist/adapters/locations.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +99 -0
- package/dist/cli.js.map +1 -0
- package/dist/domain/classification.d.ts +8 -0
- package/dist/domain/classification.d.ts.map +1 -0
- package/dist/domain/classification.js +66 -0
- package/dist/domain/classification.js.map +1 -0
- package/dist/domain/contextMap.d.ts +8 -0
- package/dist/domain/contextMap.d.ts.map +1 -0
- package/dist/domain/contextMap.js +168 -0
- package/dist/domain/contextMap.js.map +1 -0
- package/dist/domain/domainAnalysis.d.ts +25 -0
- package/dist/domain/domainAnalysis.d.ts.map +1 -0
- package/dist/domain/domainAnalysis.js +136 -0
- package/dist/domain/domainAnalysis.js.map +1 -0
- package/dist/domain/domainGenerator.d.ts +33 -0
- package/dist/domain/domainGenerator.d.ts.map +1 -0
- package/dist/domain/domainGenerator.js +307 -0
- package/dist/domain/domainGenerator.js.map +1 -0
- package/dist/domain/editorValidation.d.ts +19 -0
- package/dist/domain/editorValidation.d.ts.map +1 -0
- package/dist/domain/editorValidation.js +40 -0
- package/dist/domain/editorValidation.js.map +1 -0
- package/dist/domain/formatting.d.ts +16 -0
- package/dist/domain/formatting.d.ts.map +1 -0
- package/dist/domain/formatting.js +414 -0
- package/dist/domain/formatting.js.map +1 -0
- package/dist/domain/glossary.d.ts +20 -0
- package/dist/domain/glossary.d.ts.map +1 -0
- package/dist/domain/glossary.js +62 -0
- package/dist/domain/glossary.js.map +1 -0
- package/dist/domain/health.d.ts +14 -0
- package/dist/domain/health.d.ts.map +1 -0
- package/dist/domain/health.js +21 -0
- package/dist/domain/health.js.map +1 -0
- package/dist/domain/relationships.d.ts +13 -0
- package/dist/domain/relationships.d.ts.map +1 -0
- package/dist/domain/relationships.js +74 -0
- package/dist/domain/relationships.js.map +1 -0
- package/dist/domain/types.d.ts +290 -0
- package/dist/domain/types.d.ts.map +1 -0
- package/dist/domain/types.js +29 -0
- package/dist/domain/types.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +519 -0
- package/dist/mcp/server.js.map +1 -0
- package/docs/TOC.md +27 -0
- package/docs/decisions/0001-adopt-c3source-extractors.md +67 -0
- package/docs/decisions/0002-configurable-locations-adapters-seam.md +72 -0
- package/docs/decisions/0003-adopt-loadprojectconfig-schema-first.md +73 -0
- package/docs/decisions/0004-adopt-mcp-utils-0.4.0-helpers.md +74 -0
- package/docs/decisions/0005-validateforeditor-read-side-diagnostic.md +65 -0
- package/docs/decisions/0006-event-variable-reference-coupling.md +77 -0
- package/docs/decisions/0007-project-dir-resolverootfolder.md +72 -0
- package/docs/decisions/0008-adopt-openproject-option-a.md +74 -0
- package/docs/domain-architecture.md +242 -0
- package/docs/releasing.md +122 -0
- package/package.json +79 -8
package/LICENSE
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
MIT No Attribution
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Genvid Technologies, inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so.
|
|
11
|
+
|
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
13
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
14
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
15
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
16
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
17
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
18
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,45 +1,211 @@
|
|
|
1
|
-
#
|
|
1
|
+
# c3-domain-manager
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Domain-driven design analysis for Construct 3 projects. Classifies source files into domains, parses event sheet dependencies, and provides health and boundary validation — all driven by a single `domain-config.json` file.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## What it does
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **File classification** — maps `eventSheets/`, `layouts/`, and `scripts/` files to named domains using directory patterns and per-file overrides
|
|
8
|
+
- **Domain index generation** — writes markdown pages to `extracted/domain-index/` with per-domain file lists, function signatures, and include graphs
|
|
9
|
+
- **Health metrics** — computes coupling (Ca/Ce) and instability scores for each domain
|
|
10
|
+
- **Boundary validation** — detects undeclared cross-domain dependencies and forbidden dependency directions
|
|
11
|
+
- **Glossary collision detection** — flags terms defined differently across domains
|
|
12
|
+
- **Context map** — generates text or Mermaid diagrams of inter-domain relationships
|
|
13
|
+
- **Editor-strictness validation** — reports event sheets the C3 editor would refuse to import (e.g. missing required fields on `variable` or `group` events)
|
|
14
|
+
- **MCP server** — exposes all of the above as Model Context Protocol tools for AI agents
|
|
8
15
|
|
|
9
|
-
##
|
|
16
|
+
## Requirements
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
3. Establish provenance for packages published under this name
|
|
18
|
+
- Node.js >= 22
|
|
19
|
+
- A Construct 3 project with `eventSheets/`, `layouts/`, and `scripts/` directories
|
|
20
|
+
- A `domain-config.json` at the project root (see [docs/domain-architecture.md](docs/domain-architecture.md))
|
|
15
21
|
|
|
16
|
-
##
|
|
22
|
+
## Installation
|
|
17
23
|
|
|
18
|
-
|
|
24
|
+
Install from npm:
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
```bash
|
|
27
|
+
npm install @genvidtech/c3-domain-manager
|
|
28
|
+
```
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
Or run the CLI without installing:
|
|
23
31
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
4. Use the configured workflow to publish your actual package
|
|
32
|
+
```bash
|
|
33
|
+
npx @genvidtech/c3-domain-manager generate
|
|
34
|
+
```
|
|
28
35
|
|
|
29
|
-
##
|
|
36
|
+
## Quick start
|
|
30
37
|
|
|
31
|
-
|
|
32
|
-
- Contains no executable code
|
|
33
|
-
- Provides no functionality
|
|
34
|
-
- Should not be installed as a dependency
|
|
35
|
-
- Exists only for administrative purposes
|
|
38
|
+
### 1. Create domain-config.json
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
At the root of your Construct 3 project:
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"domains": {
|
|
45
|
+
"Authentication": {
|
|
46
|
+
"description": "Login, device binding, user profile",
|
|
47
|
+
"eventSheetDirs": ["Login", "Profile"],
|
|
48
|
+
"layoutDirs": ["Login"],
|
|
49
|
+
"scriptDirs": ["Auth"]
|
|
50
|
+
},
|
|
51
|
+
"Gameplay": {
|
|
52
|
+
"description": "Battle loop, enemies, skills",
|
|
53
|
+
"eventSheetDirs": ["Battle", "Enemies"],
|
|
54
|
+
"layoutDirs": ["Levels"],
|
|
55
|
+
"scriptDirs": ["Battle", "Skills"]
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"sharedSubdomains": {
|
|
59
|
+
"UI Components": {
|
|
60
|
+
"description": "Reusable UI widgets used across domains",
|
|
61
|
+
"scriptDirs": ["UI"]
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"overrides": {
|
|
65
|
+
"eventSheets/Shared/ChatEvents.json": "Watch Content"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
42
69
|
|
|
43
|
-
|
|
70
|
+
### 2. Generate the domain index
|
|
44
71
|
|
|
45
|
-
|
|
72
|
+
Run from your project root:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npx @genvidtech/c3-domain-manager generate
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This writes markdown pages to `extracted/domain-index/`.
|
|
79
|
+
|
|
80
|
+
### 3. Check coverage
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npx @genvidtech/c3-domain-manager list-uncategorized
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Lists files not covered by any domain mapping.
|
|
87
|
+
|
|
88
|
+
## CLI reference
|
|
89
|
+
|
|
90
|
+
Run any subcommand with `--help` for full usage.
|
|
91
|
+
|
|
92
|
+
| Subcommand | Description |
|
|
93
|
+
|------------|-------------|
|
|
94
|
+
| `generate` | Generate domain index at `extracted/domain-index/` |
|
|
95
|
+
| `list-uncategorized` | List files not mapped to any domain |
|
|
96
|
+
| `list-stale-overrides` | List override entries pointing to non-existent files |
|
|
97
|
+
| `validate-editor` | Report event sheets the C3 editor would reject (editor-strictness validation) |
|
|
98
|
+
| `server` | Start the MCP server (stdio transport) |
|
|
99
|
+
|
|
100
|
+
All subcommands share three global options:
|
|
101
|
+
|
|
102
|
+
| Option | Default | Description |
|
|
103
|
+
|--------|---------|-------------|
|
|
104
|
+
| `--project-dir <path>` | auto-detected | C3 project source root (`eventSheets/`, `layouts/`, `scripts/`). Auto-detected from a `project.c3proj` marker in the current dir or an immediate child; also honoured via the `C3_PROJECT_DIR` env var. Relative paths resolve from the current directory. |
|
|
105
|
+
| `--config <path>` | `<project-root>/domain-config.json` | Path to `domain-config.json`. Relative paths resolve from the project root. |
|
|
106
|
+
| `--extracted <path>` | `<project-root>/extracted` | Output directory for the generated domain index. Pass `none` for an ephemeral temp dir auto-cleaned on exit. |
|
|
107
|
+
|
|
108
|
+
See [docs/domain-architecture.md](docs/domain-architecture.md#paths-and-locations) for the full `--project-dir` resolution precedence (flag > `C3_PROJECT_DIR` > `project.c3proj` discovery > cwd).
|
|
109
|
+
|
|
110
|
+
## MCP server
|
|
111
|
+
|
|
112
|
+
The MCP server exposes 13 tools over stdio, suitable for use with Claude or any MCP-compatible client.
|
|
113
|
+
|
|
114
|
+
### Starting the server
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npx @genvidtech/c3-domain-manager server
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Or in an MCP client config (e.g. Claude Desktop `claude_desktop_config.json`):
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"mcpServers": {
|
|
125
|
+
"c3-domain-manager": {
|
|
126
|
+
"command": "npx",
|
|
127
|
+
"args": ["@genvidtech/c3-domain-manager", "server"],
|
|
128
|
+
"cwd": "/path/to/your/c3-project"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The server auto-generates the domain index on startup if `extracted/domain-index/` does not exist.
|
|
135
|
+
|
|
136
|
+
### Available tools
|
|
137
|
+
|
|
138
|
+
**Read tools** (no side effects)
|
|
139
|
+
|
|
140
|
+
| Tool | Description |
|
|
141
|
+
|------|-------------|
|
|
142
|
+
| `read-domain-index` | Read the master index or a named domain's detail page. Supports `offset`/`limit` pagination. |
|
|
143
|
+
| `read-domain-config` | Read `domain-config.json` in formatted text. Filter by `section`: `domains`, `sharedSubdomains`, `overrides`, or `all`. |
|
|
144
|
+
| `list-uncategorized` | List files with no domain assignment. |
|
|
145
|
+
| `list-stale-overrides` | List override entries whose files no longer exist on disk. |
|
|
146
|
+
| `get-state` | Return current `txId` and `domainDirty` flag. |
|
|
147
|
+
| `glossary-check` | Report glossary terms that are defined differently across domains. |
|
|
148
|
+
| `validate-boundaries` | Report undeclared cross-domain dependencies and forbidden dependency directions. |
|
|
149
|
+
| `domain-health` | Compute Ca, Ce, and instability metrics per domain. |
|
|
150
|
+
| `context-map` | Generate a context map in `text` or `mermaid` format. |
|
|
151
|
+
| `validate-editor` | Report event sheets the C3 editor would reject. Re-walks sheets fresh from disk; never reads the cached domain index. |
|
|
152
|
+
|
|
153
|
+
**Mutate tools** (modify `domain-config.json`)
|
|
154
|
+
|
|
155
|
+
| Tool | Description |
|
|
156
|
+
|------|-------------|
|
|
157
|
+
| `set-overrides` | Add or update file-to-domain override entries. Accepts optional `txId` for optimistic concurrency. |
|
|
158
|
+
| `remove-overrides` | Remove override entries by file path. |
|
|
159
|
+
|
|
160
|
+
**Regenerate tools**
|
|
161
|
+
|
|
162
|
+
| Tool | Description |
|
|
163
|
+
|------|-------------|
|
|
164
|
+
| `regenerate` | Re-run the domain index generator and clear the `domainDirty` flag. |
|
|
165
|
+
|
|
166
|
+
### Stale index warning
|
|
167
|
+
|
|
168
|
+
If `domain-config.json` changes while the server is running, mutate tools mark the index as dirty. Read tools that depend on the index append a warning: `[Warning: domain index may be stale — run regenerate to refresh]`. Call `regenerate` to clear it.
|
|
169
|
+
|
|
170
|
+
### Optimistic concurrency
|
|
171
|
+
|
|
172
|
+
`set-overrides` and `remove-overrides` accept an optional `txId`. If provided, the write is rejected when the server's current `txId` does not match. Use `get-state` to read the current `txId` before a write sequence.
|
|
173
|
+
|
|
174
|
+
## Library API
|
|
175
|
+
|
|
176
|
+
Import directly in TypeScript:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import {
|
|
180
|
+
classifyFile,
|
|
181
|
+
generateDomainIndex,
|
|
182
|
+
computeDomainData,
|
|
183
|
+
listUncategorized,
|
|
184
|
+
listStaleOverrides,
|
|
185
|
+
validateEditorStrictness,
|
|
186
|
+
formatEditorStrictnessReport,
|
|
187
|
+
} from "@genvidtech/c3-domain-manager";
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Key exports from `src/index.ts`:
|
|
191
|
+
|
|
192
|
+
| Export | Module | Description |
|
|
193
|
+
|--------|--------|-------------|
|
|
194
|
+
| `classifyFile(path, fileType, config)` | `classification` | Classify one file path into a domain name |
|
|
195
|
+
| `generateDomainIndex(root, extracted, configDir, configFileName, log)` → `Promise` | `domainGenerator` | Async I/O entry point — validates config via `DomainConfigSchema`, writes index |
|
|
196
|
+
| `computeDomainData(root, config)` | `domainGenerator` | Pure computation — returns `DomainData[]` without I/O |
|
|
197
|
+
| `listUncategorized(root, config)` | `domainAnalysis` | Return file paths not covered by the config |
|
|
198
|
+
| `listStaleOverrides(root, config)` | `domainAnalysis` | Return override keys whose files are missing |
|
|
199
|
+
| `collectGlossary(config)` | `glossary` | Collect all glossary entries across domains |
|
|
200
|
+
| `findCollisions(entries)` | `glossary` | Find terms with conflicting definitions |
|
|
201
|
+
| `validateBoundaries(domains, config, filter?)` | `relationships` | Check declared vs observed dependencies |
|
|
202
|
+
| `computeHealth(domain)` | `health` | Ca, Ce, instability for one `DomainData` |
|
|
203
|
+
| `generateContextMap(domains, config, opts)` | `contextMap` | Produce text or Mermaid context map |
|
|
204
|
+
| `validateEditorStrictness(root, config, log?)` | `editorValidation` | Re-walk event sheets and return issues grouped by sheet |
|
|
205
|
+
| `formatEditorStrictnessReport(report)` | `editorValidation` | Render an `EditorStrictnessReport` to text |
|
|
206
|
+
|
|
207
|
+
Type definitions are in `src/domain/types.ts`: `DomainConfig`, `DomainDefinition`, `SharedSubdomainDefinition`, `DomainData`, `Relationship`, `FunctionDef`. Editor-validation types (`EditorStrictnessReport`, `EditorStrictnessSheetReport`) are in `src/domain/editorValidation.ts`.
|
|
208
|
+
|
|
209
|
+
## Further reading
|
|
210
|
+
|
|
211
|
+
- [docs/domain-architecture.md](docs/domain-architecture.md) — domain model concepts, configuration schema, classification rules
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ResolvedRoot } from "@genvidtech/mcp-utils";
|
|
2
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
export declare const NO_EXTRACTED = "none";
|
|
4
|
+
export interface LocationOptions {
|
|
5
|
+
config?: string;
|
|
6
|
+
extracted?: string;
|
|
7
|
+
projectDir?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ResolvedLocations {
|
|
10
|
+
projectRoot: string;
|
|
11
|
+
configPath: string;
|
|
12
|
+
configDir: string;
|
|
13
|
+
configFileName: string;
|
|
14
|
+
extractedDir: string;
|
|
15
|
+
extractedEphemeral: boolean;
|
|
16
|
+
configWatchKey: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function resolveLocations(opts: LocationOptions, projectRoot: string, mkTempDir?: () => string): ResolvedLocations;
|
|
19
|
+
export declare function resolveProjectRoot(opts: {
|
|
20
|
+
projectDir?: string;
|
|
21
|
+
}, cwd?: string, env?: NodeJS.ProcessEnv): ResolvedRoot | CallToolResult;
|
|
22
|
+
//# sourceMappingURL=locations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locations.d.ts","sourceRoot":"","sources":["../../src/adapters/locations.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,eAAO,MAAM,YAAY,SAAS,CAAC;AAEnC,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;CACxB;AAMD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAAM,MAAwE,GACxF,iBAAiB,CA8BnB;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAC7B,GAAG,GAAE,MAAsB,EAC3B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,YAAY,GAAG,cAAc,CAK/B"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import { resolveRootFolder } from "@genvidtech/mcp-utils";
|
|
5
|
+
import { PROJECT_MANIFEST_FILE } from "@genvidtech/c3source";
|
|
6
|
+
export const NO_EXTRACTED = "none";
|
|
7
|
+
function toForwardSlash(p) {
|
|
8
|
+
return p.replace(/\\/g, "/");
|
|
9
|
+
}
|
|
10
|
+
export function resolveLocations(opts, projectRoot, mkTempDir = () => fs.mkdtempSync(path.join(os.tmpdir(), "c3dm-extracted-"))) {
|
|
11
|
+
const configPath = opts.config
|
|
12
|
+
? path.resolve(projectRoot, opts.config)
|
|
13
|
+
: path.join(projectRoot, "domain-config.json");
|
|
14
|
+
let extractedDir;
|
|
15
|
+
let extractedEphemeral;
|
|
16
|
+
if (opts.extracted === NO_EXTRACTED) {
|
|
17
|
+
extractedDir = mkTempDir();
|
|
18
|
+
extractedEphemeral = true;
|
|
19
|
+
}
|
|
20
|
+
else if (opts.extracted) {
|
|
21
|
+
extractedDir = path.resolve(projectRoot, opts.extracted);
|
|
22
|
+
extractedEphemeral = false;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
extractedDir = path.join(projectRoot, "extracted");
|
|
26
|
+
extractedEphemeral = false;
|
|
27
|
+
}
|
|
28
|
+
const configWatchKey = toForwardSlash(path.resolve(configPath));
|
|
29
|
+
return {
|
|
30
|
+
projectRoot,
|
|
31
|
+
configPath,
|
|
32
|
+
configDir: path.dirname(configPath),
|
|
33
|
+
configFileName: path.basename(configPath),
|
|
34
|
+
extractedDir,
|
|
35
|
+
extractedEphemeral,
|
|
36
|
+
configWatchKey,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function resolveProjectRoot(opts, cwd = process.cwd(), env = process.env) {
|
|
40
|
+
return resolveRootFolder({ explicit: opts.projectDir, envVar: "C3_PROJECT_DIR", marker: PROJECT_MANIFEST_FILE, cwd }, env);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=locations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locations.js","sourceRoot":"","sources":["../../src/adapters/locations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAqB,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC;AAkBnC,SAAS,cAAc,CAAC,CAAS;IAC/B,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAAqB,EACrB,WAAmB,EACnB,YAA0B,GAAG,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC;IAEzF,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM;QAC5B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC;QACxC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,oBAAoB,CAAC,CAAC;IAEjD,IAAI,YAAoB,CAAC;IACzB,IAAI,kBAA2B,CAAC;IAEhC,IAAI,IAAI,CAAC,SAAS,KAAK,YAAY,EAAE,CAAC;QACpC,YAAY,GAAG,SAAS,EAAE,CAAC;QAC3B,kBAAkB,GAAG,IAAI,CAAC;IAC5B,CAAC;SAAM,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QAC1B,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACzD,kBAAkB,GAAG,KAAK,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACnD,kBAAkB,GAAG,KAAK,CAAC;IAC7B,CAAC;IAED,MAAM,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAEhE,OAAO;QACL,WAAW;QACX,UAAU;QACV,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QACnC,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QACzC,YAAY;QACZ,kBAAkB;QAClB,cAAc;KACf,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,IAA6B,EAC7B,MAAc,OAAO,CAAC,GAAG,EAAE,EAC3B,MAAyB,OAAO,CAAC,GAAG;IAEpC,OAAO,iBAAiB,CACtB,EAAE,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,EAC3F,GAAG,CACJ,CAAC;AACJ,CAAC"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync, rmSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import yargs from "yargs";
|
|
6
|
+
import { hideBin } from "yargs/helpers";
|
|
7
|
+
import { generateDomainIndex, loadConfig } from "./domain/domainGenerator.js";
|
|
8
|
+
import { listUncategorized, listStaleOverrides } from "./domain/domainAnalysis.js";
|
|
9
|
+
import { validateEditorStrictness, formatEditorStrictnessReport } from "./domain/editorValidation.js";
|
|
10
|
+
import { resolveLocations, resolveProjectRoot } from "./adapters/locations.js";
|
|
11
|
+
import { isMcpError } from "@genvidtech/mcp-utils";
|
|
12
|
+
function resolveRootOrExit(projectDir) {
|
|
13
|
+
const rooted = resolveProjectRoot({ projectDir });
|
|
14
|
+
if (isMcpError(rooted)) {
|
|
15
|
+
const msg = (rooted.content ?? [])
|
|
16
|
+
.map((c) => (typeof c.text === "string" ? c.text : ""))
|
|
17
|
+
.join("\n")
|
|
18
|
+
.trim();
|
|
19
|
+
console.error(msg || "Failed to resolve project root.");
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
return rooted.path;
|
|
23
|
+
}
|
|
24
|
+
// Resolve this package's own package.json relative to the compiled module
|
|
25
|
+
// (dist/cli.js → ../package.json), NOT process.cwd() which is the target project.
|
|
26
|
+
const PKG_PATH = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
27
|
+
const { version: PKG_VERSION } = JSON.parse(readFileSync(PKG_PATH, "utf-8"));
|
|
28
|
+
yargs(hideBin(process.argv))
|
|
29
|
+
.command("server", "Start the c3-domain-manager MCP server", () => { }, async (argv) => {
|
|
30
|
+
const projectRoot = resolveRootOrExit(argv["project-dir"]);
|
|
31
|
+
const loc = resolveLocations({ config: argv.config, extracted: argv.extracted }, projectRoot);
|
|
32
|
+
const { startServer } = await import("./mcp/server.js");
|
|
33
|
+
await startServer(loc);
|
|
34
|
+
})
|
|
35
|
+
.command("generate", "Generate domain index", () => { }, async (argv) => {
|
|
36
|
+
const projectRoot = resolveRootOrExit(argv["project-dir"]);
|
|
37
|
+
const loc = resolveLocations({ config: argv.config, extracted: argv.extracted }, projectRoot);
|
|
38
|
+
try {
|
|
39
|
+
await generateDomainIndex(loc.projectRoot, loc.extractedDir, loc.configDir, loc.configFileName, console.log);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
if (loc.extractedEphemeral) {
|
|
43
|
+
rmSync(loc.extractedDir, { recursive: true, force: true });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
.command("list-uncategorized", "List files not mapped to any domain in domain-config.json", () => { }, async (argv) => {
|
|
48
|
+
const projectRoot = resolveRootOrExit(argv["project-dir"]);
|
|
49
|
+
const loc = resolveLocations({ config: argv.config }, projectRoot);
|
|
50
|
+
const config = await loadConfig(loc.configDir, loc.configFileName);
|
|
51
|
+
const files = listUncategorized(loc.projectRoot, config);
|
|
52
|
+
if (files.length === 0) {
|
|
53
|
+
console.log("All files are categorized.");
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
console.log(`${files.length} uncategorized file(s):\n`);
|
|
57
|
+
for (const f of files)
|
|
58
|
+
console.log(f);
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
.command("list-stale-overrides", "List stale file overrides in domain-config.json", () => { }, async (argv) => {
|
|
62
|
+
const projectRoot = resolveRootOrExit(argv["project-dir"]);
|
|
63
|
+
const loc = resolveLocations({ config: argv.config }, projectRoot);
|
|
64
|
+
const config = await loadConfig(loc.configDir, loc.configFileName);
|
|
65
|
+
const stale = listStaleOverrides(loc.projectRoot, config);
|
|
66
|
+
if (stale.length === 0) {
|
|
67
|
+
console.log("No stale overrides.");
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.log(`${stale.length} stale override(s):\n`);
|
|
71
|
+
for (const s of stale)
|
|
72
|
+
console.log(s);
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
.command("validate-editor", "Report event sheets the C3 editor would reject (editor-strictness validation)", () => { }, async (argv) => {
|
|
76
|
+
const projectRoot = resolveRootOrExit(argv["project-dir"]);
|
|
77
|
+
const loc = resolveLocations({ config: argv.config }, projectRoot);
|
|
78
|
+
const config = await loadConfig(loc.configDir, loc.configFileName);
|
|
79
|
+
const report = validateEditorStrictness(loc.projectRoot, config);
|
|
80
|
+
console.log(formatEditorStrictnessReport(report));
|
|
81
|
+
})
|
|
82
|
+
.option("project-dir", {
|
|
83
|
+
type: "string",
|
|
84
|
+
describe: "Path to the C3 project root to analyze (default: auto-detected — the current directory or an immediate child containing project.c3proj, else the current directory). Honors the C3_PROJECT_DIR env var. Relative paths resolve from the current directory.",
|
|
85
|
+
})
|
|
86
|
+
.option("config", {
|
|
87
|
+
type: "string",
|
|
88
|
+
describe: "Path to domain-config.json (default: <project-root>/domain-config.json). Relative paths resolve from the project root; absolute paths are used as-is.",
|
|
89
|
+
})
|
|
90
|
+
.option("extracted", {
|
|
91
|
+
type: "string",
|
|
92
|
+
describe: 'Output directory for the generated domain index (default: <project-root>/extracted). Use "none" for an ephemeral temp dir auto-cleaned on exit.',
|
|
93
|
+
})
|
|
94
|
+
.demandCommand(1, "Please specify a subcommand. Use --help for available commands.")
|
|
95
|
+
.strict()
|
|
96
|
+
.version(PKG_VERSION)
|
|
97
|
+
.help()
|
|
98
|
+
.parse();
|
|
99
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DomainConfig } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Classify a file into a domain by checking overrides first, then directory arrays.
|
|
4
|
+
* Checks both domains and sharedSubdomains.
|
|
5
|
+
* Returns the domain name or null if unclassified.
|
|
6
|
+
*/
|
|
7
|
+
export declare function classifyFile(relativePath: string, fileType: "eventSheet" | "layout" | "script", config: DomainConfig): string | null;
|
|
8
|
+
//# sourceMappingURL=classification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classification.d.ts","sourceRoot":"","sources":["../../src/domain/classification.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,YAAY,CAAC;AAgBjE;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,YAAY,GAAG,QAAQ,GAAG,QAAQ,EAC5C,MAAM,EAAE,YAAY,GACnB,MAAM,GAAG,IAAI,CAoDf"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** File type root directories. */
|
|
2
|
+
const FILE_TYPE_ROOTS = {
|
|
3
|
+
eventSheet: "eventSheets/",
|
|
4
|
+
layout: "layouts/",
|
|
5
|
+
script: "scripts/",
|
|
6
|
+
};
|
|
7
|
+
/** Dir array key per file type. */
|
|
8
|
+
const DIR_KEYS = {
|
|
9
|
+
eventSheet: "eventSheetDirs",
|
|
10
|
+
layout: "layoutDirs",
|
|
11
|
+
script: "scriptDirs",
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Classify a file into a domain by checking overrides first, then directory arrays.
|
|
15
|
+
* Checks both domains and sharedSubdomains.
|
|
16
|
+
* Returns the domain name or null if unclassified.
|
|
17
|
+
*/
|
|
18
|
+
export function classifyFile(relativePath, fileType, config) {
|
|
19
|
+
// 1. Check overrides (exact match, highest priority)
|
|
20
|
+
if (config.overrides && relativePath in config.overrides) {
|
|
21
|
+
return config.overrides[relativePath];
|
|
22
|
+
}
|
|
23
|
+
// 2. Strip the file type root prefix to get the inner path
|
|
24
|
+
const root = FILE_TYPE_ROOTS[fileType];
|
|
25
|
+
if (!relativePath.startsWith(root)) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const innerPath = relativePath.slice(root.length); // e.g. "Login/LoginEvents.json"
|
|
29
|
+
// 3. Check domain directory arrays — longest prefix wins
|
|
30
|
+
const dirKey = DIR_KEYS[fileType];
|
|
31
|
+
let bestMatch = null;
|
|
32
|
+
let bestLength = -1;
|
|
33
|
+
// Check regular domains
|
|
34
|
+
for (const [domainName, domainDef] of Object.entries(config.domains)) {
|
|
35
|
+
const dirs = domainDef[dirKey];
|
|
36
|
+
if (!dirs)
|
|
37
|
+
continue;
|
|
38
|
+
for (const dir of dirs) {
|
|
39
|
+
// dir is relative to the file type root, e.g. "Login" or "Main Menu/Shop"
|
|
40
|
+
// Match innerPath that starts with dir + "/" (file inside dir)
|
|
41
|
+
// or exactly equals dir (directory entry without trailing slash)
|
|
42
|
+
const prefix = dir + "/";
|
|
43
|
+
if ((innerPath.startsWith(prefix) || innerPath === dir) && dir.length > bestLength) {
|
|
44
|
+
bestMatch = domainName;
|
|
45
|
+
bestLength = dir.length;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Check shared subdomains
|
|
50
|
+
if (config.sharedSubdomains) {
|
|
51
|
+
for (const [subdomainName, subdomainDef] of Object.entries(config.sharedSubdomains)) {
|
|
52
|
+
const dirs = subdomainDef[dirKey];
|
|
53
|
+
if (!dirs)
|
|
54
|
+
continue;
|
|
55
|
+
for (const dir of dirs) {
|
|
56
|
+
const prefix = dir + "/";
|
|
57
|
+
if ((innerPath.startsWith(prefix) || innerPath === dir) && dir.length > bestLength) {
|
|
58
|
+
bestMatch = subdomainName;
|
|
59
|
+
bestLength = dir.length;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return bestMatch;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=classification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classification.js","sourceRoot":"","sources":["../../src/domain/classification.ts"],"names":[],"mappings":"AAEA,kCAAkC;AAClC,MAAM,eAAe,GAA2B;IAC9C,UAAU,EAAE,cAAc;IAC1B,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,UAAU;CACnB,CAAC;AAEF,mCAAmC;AACnC,MAAM,QAAQ,GAA2C;IACvD,UAAU,EAAE,gBAAgB;IAC5B,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;CACrB,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,YAAoB,EACpB,QAA4C,EAC5C,MAAoB;IAEpB,qDAAqD;IACrD,IAAI,MAAM,CAAC,SAAS,IAAI,YAAY,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACzD,OAAO,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IACxC,CAAC;IAED,2DAA2D;IAC3D,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,gCAAgC;IAEnF,yDAAyD;IACzD,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,SAAS,GAAkB,IAAI,CAAC;IACpC,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC;IAEpB,wBAAwB;IACxB,KAAK,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAyB,CAAC;QACvD,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,0EAA0E;YAC1E,+DAA+D;YAC/D,iEAAiE;YACjE,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC;YACzB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,SAAS,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;gBACnF,SAAS,GAAG,UAAU,CAAC;gBACvB,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACpF,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAyB,CAAC;YAC1D,IAAI,CAAC,IAAI;gBAAE,SAAS;YAEpB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC;gBACzB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,SAAS,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;oBACnF,SAAS,GAAG,aAAa,CAAC;oBAC1B,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DomainConfig, DomainData } from "./types.js";
|
|
2
|
+
export interface ContextMapOptions {
|
|
3
|
+
format: "text" | "mermaid";
|
|
4
|
+
domain?: string;
|
|
5
|
+
includeObserved?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function generateContextMap(domains: DomainData[], config: DomainConfig, opts: ContextMapOptions): string;
|
|
8
|
+
//# sourceMappingURL=contextMap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextMap.d.ts","sourceRoot":"","sources":["../../src/domain/contextMap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAgB,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAiND,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,UAAU,EAAE,EACrB,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,iBAAiB,GACtB,MAAM,CAUR"}
|