@mwturnbull/papi-mcp 0.1.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/LICENSE +21 -0
- package/README.md +320 -0
- package/dist/config/assembler.d.ts +6 -0
- package/dist/config/assembler.d.ts.map +1 -0
- package/dist/config/assembler.js +56 -0
- package/dist/config/assembler.js.map +1 -0
- package/dist/config/parser.d.ts +6 -0
- package/dist/config/parser.d.ts.map +1 -0
- package/dist/config/parser.js +79 -0
- package/dist/config/parser.js.map +1 -0
- package/dist/config/snippets.d.ts +12 -0
- package/dist/config/snippets.d.ts.map +1 -0
- package/dist/config/snippets.js +75 -0
- package/dist/config/snippets.js.map +1 -0
- package/dist/git/git-ops.d.ts +16 -0
- package/dist/git/git-ops.d.ts.map +1 -0
- package/dist/git/git-ops.js +64 -0
- package/dist/git/git-ops.js.map +1 -0
- package/dist/git/github.d.ts +12 -0
- package/dist/git/github.d.ts.map +1 -0
- package/dist/git/github.js +83 -0
- package/dist/git/github.js.map +1 -0
- package/dist/git/gitlab.d.ts +11 -0
- package/dist/git/gitlab.d.ts.map +1 -0
- package/dist/git/gitlab.js +65 -0
- package/dist/git/gitlab.js.map +1 -0
- package/dist/git/provider.d.ts +33 -0
- package/dist/git/provider.d.ts.map +1 -0
- package/dist/git/provider.js +49 -0
- package/dist/git/provider.js.map +1 -0
- package/dist/papi/auth.d.ts +12 -0
- package/dist/papi/auth.d.ts.map +1 -0
- package/dist/papi/auth.js +74 -0
- package/dist/papi/auth.js.map +1 -0
- package/dist/papi/client.d.ts +19 -0
- package/dist/papi/client.d.ts.map +1 -0
- package/dist/papi/client.js +115 -0
- package/dist/papi/client.js.map +1 -0
- package/dist/papi/types.d.ts +487 -0
- package/dist/papi/types.d.ts.map +1 -0
- package/dist/papi/types.js +94 -0
- package/dist/papi/types.js.map +1 -0
- package/dist/redaction/redactor.d.ts +25 -0
- package/dist/redaction/redactor.d.ts.map +1 -0
- package/dist/redaction/redactor.js +128 -0
- package/dist/redaction/redactor.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +219 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/activate.d.ts +16 -0
- package/dist/tools/activate.d.ts.map +1 -0
- package/dist/tools/activate.js +59 -0
- package/dist/tools/activate.js.map +1 -0
- package/dist/tools/diff-configs.d.ts +3 -0
- package/dist/tools/diff-configs.d.ts.map +1 -0
- package/dist/tools/diff-configs.js +152 -0
- package/dist/tools/diff-configs.js.map +1 -0
- package/dist/tools/get-property-config.d.ts +9 -0
- package/dist/tools/get-property-config.d.ts.map +1 -0
- package/dist/tools/get-property-config.js +53 -0
- package/dist/tools/get-property-config.js.map +1 -0
- package/dist/tools/pipeline.d.ts +11 -0
- package/dist/tools/pipeline.d.ts.map +1 -0
- package/dist/tools/pipeline.js +9 -0
- package/dist/tools/pipeline.js.map +1 -0
- package/dist/tools/sync-property.d.ts +9 -0
- package/dist/tools/sync-property.d.ts.map +1 -0
- package/dist/tools/sync-property.js +65 -0
- package/dist/tools/sync-property.js.map +1 -0
- package/dist/tools/write-snippet.d.ts +30 -0
- package/dist/tools/write-snippet.d.ts.map +1 -0
- package/dist/tools/write-snippet.js +92 -0
- package/dist/tools/write-snippet.js.map +1 -0
- package/dist/validation/local.d.ts +3 -0
- package/dist/validation/local.d.ts.map +1 -0
- package/dist/validation/local.js +290 -0
- package/dist/validation/local.js.map +1 -0
- package/dist/validation/papi.d.ts +6 -0
- package/dist/validation/papi.d.ts.map +1 -0
- package/dist/validation/papi.js +59 -0
- package/dist/validation/papi.js.map +1 -0
- package/package.json +55 -0
- package/src/skill/system-prompt.md +205 -0
- package/templates/.gitkeep +0 -0
- package/templates/CLAUDE.md +115 -0
- package/templates/copilot-instructions.md +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 m-w-turnbull
|
|
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, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# papi-mcp
|
|
2
|
+
|
|
3
|
+
MCP server for Akamai Property Manager (PAPI) configurations. Gives AI assistants structured access to read, validate, modify, and activate Akamai CDN properties.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **14 tools** across read, validate, write, activate, and pipeline workflows
|
|
8
|
+
- **Config-driven redaction** — no hardcoded secrets
|
|
9
|
+
- **GitLab + GitHub** — pluggable git provider with auto-detection
|
|
10
|
+
- **Activation safety** — staging/production split with explicit risk acknowledgement
|
|
11
|
+
- **7 local validation checks** + optional PAPI API validation
|
|
12
|
+
- **LLM-optimized parsing** — flat, breadcrumb-based rule tree representation
|
|
13
|
+
- **Snippet-based configs** — large rule trees split with #include: directives
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install
|
|
21
|
+
npm run build
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Claude Code
|
|
25
|
+
|
|
26
|
+
Add to your MCP settings (`.cursor/claude_config.json` or Claude settings):
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"mcpServers": {
|
|
31
|
+
"papi-mcp": {
|
|
32
|
+
"command": "node",
|
|
33
|
+
"args": ["path/to/papi-mcp/dist/server.js"]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### VS Code Copilot Chat
|
|
40
|
+
|
|
41
|
+
Add the same MCP configuration to your VS Code settings.
|
|
42
|
+
|
|
43
|
+
### Claude Desktop
|
|
44
|
+
|
|
45
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"papi-mcp": {
|
|
51
|
+
"command": "node",
|
|
52
|
+
"args": ["path/to/papi-mcp/dist/server.js"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Tools
|
|
59
|
+
|
|
60
|
+
### Read & Analyse (5 tools)
|
|
61
|
+
|
|
62
|
+
| Tool | Description |
|
|
63
|
+
|------|-------------|
|
|
64
|
+
| `get_property_config` | Fetch current property rule tree via PAPI API. Requires `propertyId` or auto-detects from `envInfo.json` in repo. |
|
|
65
|
+
| `read_snippets` | Read local config snippet files or list all snippets. Snippets live in `config-snippets/` directory. |
|
|
66
|
+
| `parse_rule_tree` | Parse PAPI JSON into LLM-optimised flat representation. Accepts either `repoPath` (assembles from disk) or raw `ruleTree` JSON. |
|
|
67
|
+
| `assemble_rule_tree` | Resolve all #include: directives into a complete rule tree. Validates that all includes exist. |
|
|
68
|
+
| `sync_property` | Compare local config against live PAPI version using version-number comparison. |
|
|
69
|
+
|
|
70
|
+
### Validate & Diff (2 tools)
|
|
71
|
+
|
|
72
|
+
| Tool | Description |
|
|
73
|
+
|------|-------------|
|
|
74
|
+
| `validate_config` | Run 7 validation checks: JSON syntax, required fields, include resolution, orphan detection, variable references, duplicate names, no-op rules. Optional `apiValidation: true` for PAPI schema compliance. |
|
|
75
|
+
| `diff_configs` | Structured diff between two rule tree versions. Shows behavior-level and criteria-level changes. |
|
|
76
|
+
|
|
77
|
+
### Write & Ship (4 tools)
|
|
78
|
+
|
|
79
|
+
| Tool | Description |
|
|
80
|
+
|------|-------------|
|
|
81
|
+
| `write_snippet` | Create or update a config snippet file. Validates against PapiRule schema. |
|
|
82
|
+
| `apply_behavior` | Add or modify a single behavior in an existing snippet. Useful for targeted changes. |
|
|
83
|
+
| `create_branch` | Create git branch following `akamai/<type>/<description>` naming convention. Types: feature, fix, refactor, chore. |
|
|
84
|
+
| `create_merge_request` | Commit changes, push branch, and open a GitLab MR or GitHub PR. Auto-detects git provider. |
|
|
85
|
+
|
|
86
|
+
### Activate & Pipeline (3 tools)
|
|
87
|
+
|
|
88
|
+
| Tool | Description |
|
|
89
|
+
|------|-------------|
|
|
90
|
+
| `activate_staging` | Activate property version to Akamai staging network. Returns immediately; check status via polling. |
|
|
91
|
+
| `activate_production` | Activate to production. Requires `acknowledgeProductionRisk: true` and at least one `contactEmails` entry. |
|
|
92
|
+
| `trigger_pipeline` | Trigger CI/CD pipeline for current branch. Useful for automated testing. |
|
|
93
|
+
|
|
94
|
+
## Configuration
|
|
95
|
+
|
|
96
|
+
### Akamai Credentials
|
|
97
|
+
|
|
98
|
+
Option 1: `.edgerc` file (default location: `~/.edgerc`):
|
|
99
|
+
|
|
100
|
+
```ini
|
|
101
|
+
[default]
|
|
102
|
+
client_secret = xxxx
|
|
103
|
+
host = xxxx.luna.akamaiapis.net
|
|
104
|
+
access_token = xxxx
|
|
105
|
+
client_token = xxxx
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Option 2: Environment variables:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
export AKAMAI_CLIENT_SECRET=xxxx
|
|
112
|
+
export AKAMAI_HOST=xxxx.luna.akamaiapis.net
|
|
113
|
+
export AKAMAI_ACCESS_TOKEN=xxxx
|
|
114
|
+
export AKAMAI_CLIENT_TOKEN=xxxx
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Get credentials from Akamai Control Center or ask your team administrator.
|
|
118
|
+
|
|
119
|
+
### Redaction Config (.papi-mcp.json)
|
|
120
|
+
|
|
121
|
+
Create `.papi-mcp.json` in your project root to configure sensitive field redaction:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"redact": {
|
|
126
|
+
"sensitiveVariables": true,
|
|
127
|
+
"fields": ["options.hostname", "options.headerValue"],
|
|
128
|
+
"sensitiveHeaders": ["authorization", "x-api-key"]
|
|
129
|
+
},
|
|
130
|
+
"gitProvider": {
|
|
131
|
+
"type": "gitlab",
|
|
132
|
+
"host": "gitlab.internal.example.com"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Redaction prevents secrets from appearing in logs and AI outputs.
|
|
138
|
+
|
|
139
|
+
### Git Provider
|
|
140
|
+
|
|
141
|
+
Auto-detected from git remote URL. Override in `.papi-mcp.json` for custom domains.
|
|
142
|
+
|
|
143
|
+
**GitLab:**
|
|
144
|
+
|
|
145
|
+
Set one of: `GITLAB_TOKEN`, `GITLAB_PERSONAL_ACCESS_TOKEN`, or `CI_JOB_TOKEN`
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
export GITLAB_TOKEN=glpat-xxxx
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**GitHub:**
|
|
152
|
+
|
|
153
|
+
Set one of: `GITHUB_TOKEN` or `GH_TOKEN`
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
export GITHUB_TOKEN=ghp_xxxx
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Property Metadata (envInfo.json)
|
|
160
|
+
|
|
161
|
+
Auto-detected from property repo structure. Place in `{propertyName}/envInfo.json`:
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"name": "my-property",
|
|
166
|
+
"propertyId": 12345,
|
|
167
|
+
"propertyName": "my-property",
|
|
168
|
+
"groupId": 67890,
|
|
169
|
+
"isSecure": false,
|
|
170
|
+
"latestVersionInfo": {
|
|
171
|
+
"propertyVersion": 5,
|
|
172
|
+
"productionStatus": "ACTIVE",
|
|
173
|
+
"stagingStatus": "ACTIVE",
|
|
174
|
+
"ruleFormat": "v2024-02-12"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Recommended Workflow
|
|
180
|
+
|
|
181
|
+
1. **Understand current state**: `read_snippets` → `parse_rule_tree`
|
|
182
|
+
2. **Create branch**: `create_branch` with type and description
|
|
183
|
+
3. **Make changes**: `write_snippet` or `apply_behavior`
|
|
184
|
+
4. **Validate**: `validate_config` to check for issues
|
|
185
|
+
5. **Review changes**: `diff_configs` to compare
|
|
186
|
+
6. **Open for review**: `create_merge_request` to create MR/PR
|
|
187
|
+
7. **After approval, activate**:
|
|
188
|
+
- `activate_staging` to test on staging
|
|
189
|
+
- `activate_production` to go live
|
|
190
|
+
|
|
191
|
+
## Architecture
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
src/
|
|
195
|
+
├── server.ts # MCP server entry (14 tool registrations)
|
|
196
|
+
├── papi/
|
|
197
|
+
│ ├── types.ts # Zod schemas and TypeScript types
|
|
198
|
+
│ ├── auth.ts # EdgeGrid credential resolution
|
|
199
|
+
│ └── client.ts # PAPI HTTP client
|
|
200
|
+
├── config/
|
|
201
|
+
│ ├── snippets.ts # Snippet file I/O operations
|
|
202
|
+
│ ├── assembler.ts # #include: directive resolution
|
|
203
|
+
│ └── parser.ts # LLM-optimized rule tree parser
|
|
204
|
+
├── validation/
|
|
205
|
+
│ ├── local.ts # 7 local validation checks
|
|
206
|
+
│ └── papi.ts # PAPI API validation wrapper
|
|
207
|
+
├── tools/
|
|
208
|
+
│ ├── get-property-config.ts # Fetch property from PAPI
|
|
209
|
+
│ ├── read-snippets.ts # Read local config files
|
|
210
|
+
│ ├── diff-configs.ts # Structured config diffing
|
|
211
|
+
│ ├── sync-property.ts # Local vs live comparison
|
|
212
|
+
│ ├── write-snippet.ts # Create/update config files
|
|
213
|
+
│ ├── activate.ts # Staging/production activation
|
|
214
|
+
│ └── pipeline.ts # CI/CD pipeline triggering
|
|
215
|
+
├── git/
|
|
216
|
+
│ ├── git-ops.ts # Core git operations
|
|
217
|
+
│ ├── provider.ts # GitProvider interface + factory
|
|
218
|
+
│ ├── gitlab.ts # GitLab API client
|
|
219
|
+
│ └── github.ts # GitHub API client
|
|
220
|
+
├── redaction/
|
|
221
|
+
│ └── redactor.ts # Config-driven field redaction
|
|
222
|
+
└── skill/
|
|
223
|
+
└── system-prompt.md # AI domain knowledge layer
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Development
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
npm install # Install dependencies
|
|
230
|
+
npm run build # TypeScript compilation
|
|
231
|
+
npm test # Run all tests
|
|
232
|
+
npm run test:watch # Watch mode
|
|
233
|
+
npm run test:coverage # Coverage report
|
|
234
|
+
npm run dev # Dev mode with tsx
|
|
235
|
+
npm run lint # Type checking
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Testing
|
|
239
|
+
|
|
240
|
+
Run the full test suite:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
npm test
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Watch mode for development:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
npm run test:watch
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Coverage report:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
npm run test:coverage
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Test fixtures are in `tests/fixtures/`:
|
|
259
|
+
|
|
260
|
+
- `sample-property/` — valid property configuration with snippets
|
|
261
|
+
- `api-responses/` — mock PAPI API responses
|
|
262
|
+
- `invalid-configs/` — invalid configs for validation testing
|
|
263
|
+
|
|
264
|
+
## Best Practices
|
|
265
|
+
|
|
266
|
+
- Use descriptive snippet names: `CORS_Policy.json`, `API_Caching.json`, `Origins.json`
|
|
267
|
+
- Use variables for environment-specific values (hostnames, API keys)
|
|
268
|
+
- Mark sensitive variables as `hidden: true, sensitive: true`
|
|
269
|
+
- Run validation after every change
|
|
270
|
+
- Review diffs before creating merge requests
|
|
271
|
+
- Always activate staging before production
|
|
272
|
+
- Document rule purposes in rule names
|
|
273
|
+
- Group related rules under descriptive parent rules
|
|
274
|
+
|
|
275
|
+
## Validation Checks
|
|
276
|
+
|
|
277
|
+
The `validate_config` tool runs 7 checks:
|
|
278
|
+
|
|
279
|
+
1. **JSON syntax** — all files must be valid JSON (error)
|
|
280
|
+
2. **Required fields** — name, children, behaviors, criteria, criteriaMustSatisfy (error)
|
|
281
|
+
3. **Include resolution** — all #include: targets must exist (error)
|
|
282
|
+
4. **Orphan detection** — unreferenced snippets (warning)
|
|
283
|
+
5. **Variable references** — PMUSER_ vars must be declared (warning)
|
|
284
|
+
6. **Duplicate rule names** — siblings with same name (warning)
|
|
285
|
+
7. **No-op rules** — empty behaviors + criteria + children (info)
|
|
286
|
+
|
|
287
|
+
Use `apiValidation: true` to also check PAPI schema compliance.
|
|
288
|
+
|
|
289
|
+
## Troubleshooting
|
|
290
|
+
|
|
291
|
+
### Credentials Not Found
|
|
292
|
+
|
|
293
|
+
Make sure one of:
|
|
294
|
+
|
|
295
|
+
- `~/.edgerc` exists with [default] section
|
|
296
|
+
- Environment variables are set: `AKAMAI_CLIENT_SECRET`, `AKAMAI_HOST`, `AKAMAI_ACCESS_TOKEN`, `AKAMAI_CLIENT_TOKEN`
|
|
297
|
+
|
|
298
|
+
### Property Not Found
|
|
299
|
+
|
|
300
|
+
Verify:
|
|
301
|
+
|
|
302
|
+
- `propertyId` is correct (e.g., `prp_12345`)
|
|
303
|
+
- `groupId` is correct (auto-detected from `envInfo.json`)
|
|
304
|
+
- Account has access to the property
|
|
305
|
+
|
|
306
|
+
### Git Provider Not Detected
|
|
307
|
+
|
|
308
|
+
Make sure:
|
|
309
|
+
|
|
310
|
+
- Git remote is set: `git remote -v`
|
|
311
|
+
- Git token is set: `GITLAB_TOKEN` or `GITHUB_TOKEN`
|
|
312
|
+
- `.papi-mcp.json` is configured if using custom domain
|
|
313
|
+
|
|
314
|
+
### Validation Errors
|
|
315
|
+
|
|
316
|
+
Run `validate_config` with `apiValidation: true` to get PAPI schema validation details.
|
|
317
|
+
|
|
318
|
+
## License
|
|
319
|
+
|
|
320
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assembler.d.ts","sourceRoot":"","sources":["../../src/config/assembler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE3D,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkB1E"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { findPmDirectory } from './snippets.js';
|
|
4
|
+
export class AssemblerError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'AssemblerError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export async function assembleRuleTree(repoPath) {
|
|
11
|
+
const pmDir = await findPmDirectory(repoPath);
|
|
12
|
+
const mainPath = resolve(pmDir, 'config-snippets', 'main.json');
|
|
13
|
+
const mainContent = await readFile(mainPath, 'utf-8');
|
|
14
|
+
const mainJson = JSON.parse(mainContent);
|
|
15
|
+
// main.json has the { rules: { ... } } envelope
|
|
16
|
+
const rootRule = mainJson.rules;
|
|
17
|
+
// Resolve #include: directives in children
|
|
18
|
+
const snippetsDir = resolve(pmDir, 'config-snippets');
|
|
19
|
+
const resolved = await resolveIncludes(rootRule, snippetsDir, new Set());
|
|
20
|
+
return {
|
|
21
|
+
rules: resolved,
|
|
22
|
+
ruleFormat: undefined, // Will come from envInfo if needed
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
async function resolveIncludes(rule, snippetsDir, visited) {
|
|
26
|
+
const resolvedChildren = [];
|
|
27
|
+
for (const child of rule.children) {
|
|
28
|
+
if (typeof child === 'string' && child.startsWith('#include:')) {
|
|
29
|
+
const filename = child.slice('#include:'.length);
|
|
30
|
+
if (visited.has(filename)) {
|
|
31
|
+
throw new AssemblerError(`Circular include detected: ${filename} (chain: ${[...visited].join(' → ')} → ${filename})`);
|
|
32
|
+
}
|
|
33
|
+
const filePath = resolve(snippetsDir, filename);
|
|
34
|
+
let content;
|
|
35
|
+
try {
|
|
36
|
+
content = await readFile(filePath, 'utf-8');
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
throw new AssemblerError(`Missing include target: ${filename} (expected at ${filePath})`);
|
|
40
|
+
}
|
|
41
|
+
const snippet = JSON.parse(content);
|
|
42
|
+
visited.add(filename);
|
|
43
|
+
const resolved = await resolveIncludes(snippet, snippetsDir, visited);
|
|
44
|
+
visited.delete(filename);
|
|
45
|
+
resolvedChildren.push(resolved);
|
|
46
|
+
}
|
|
47
|
+
else if (typeof child === 'object') {
|
|
48
|
+
resolvedChildren.push(await resolveIncludes(child, snippetsDir, visited));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
...rule,
|
|
53
|
+
children: resolvedChildren,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=assembler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assembler.js","sourceRoot":"","sources":["../../src/config/assembler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/config/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwB,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAG7E,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,cAAc,CAAC,CAuC1B"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { assembleRuleTree } from './assembler.js';
|
|
2
|
+
export async function parseRuleTree(options) {
|
|
3
|
+
let rootRule;
|
|
4
|
+
let ruleFormat;
|
|
5
|
+
if (options.repoPath) {
|
|
6
|
+
const tree = await assembleRuleTree(options.repoPath);
|
|
7
|
+
rootRule = tree.rules;
|
|
8
|
+
ruleFormat = tree.ruleFormat;
|
|
9
|
+
}
|
|
10
|
+
else if (options.ruleTree) {
|
|
11
|
+
const parsed = JSON.parse(options.ruleTree);
|
|
12
|
+
// Handle both { rules: {...} } envelope and bare rule
|
|
13
|
+
rootRule = (parsed['rules'] ?? parsed);
|
|
14
|
+
ruleFormat = parsed['ruleFormat'];
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
throw new Error('Either repoPath or ruleTree must be provided');
|
|
18
|
+
}
|
|
19
|
+
const rules = [];
|
|
20
|
+
let totalBehaviors = 0;
|
|
21
|
+
flattenRule(rootRule, '', rules);
|
|
22
|
+
for (const r of rules) {
|
|
23
|
+
totalBehaviors += r.behaviors.length;
|
|
24
|
+
}
|
|
25
|
+
const variables = (rootRule.variables ?? []).map(v => ({
|
|
26
|
+
name: v.name,
|
|
27
|
+
value: v.value,
|
|
28
|
+
description: v.description,
|
|
29
|
+
sensitive: v.sensitive,
|
|
30
|
+
}));
|
|
31
|
+
return {
|
|
32
|
+
rules,
|
|
33
|
+
variables,
|
|
34
|
+
ruleFormat,
|
|
35
|
+
totalRules: rules.length,
|
|
36
|
+
totalBehaviors,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function flattenRule(rule, parentPath, result) {
|
|
40
|
+
const path = parentPath ? `${parentPath} > ${rule.name}` : rule.name;
|
|
41
|
+
result.push({
|
|
42
|
+
path,
|
|
43
|
+
name: rule.name,
|
|
44
|
+
behaviors: rule.behaviors.map(b => ({
|
|
45
|
+
name: b.name,
|
|
46
|
+
keyOptions: summarizeOptions(b.options),
|
|
47
|
+
})),
|
|
48
|
+
criteria: rule.criteria.map(c => ({
|
|
49
|
+
name: c.name,
|
|
50
|
+
matchType: c.options['matchOperator'] ?? 'IS',
|
|
51
|
+
values: c.options['value'] ?? c.options['values'] ?? null,
|
|
52
|
+
})),
|
|
53
|
+
comments: rule.comments,
|
|
54
|
+
childCount: rule.children.length,
|
|
55
|
+
});
|
|
56
|
+
for (const child of rule.children) {
|
|
57
|
+
if (typeof child === 'object') {
|
|
58
|
+
flattenRule(child, path, result);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function summarizeOptions(options) {
|
|
63
|
+
const summary = {};
|
|
64
|
+
for (const [key, value] of Object.entries(options)) {
|
|
65
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
66
|
+
// For nested objects, just include key fields
|
|
67
|
+
const nested = value;
|
|
68
|
+
if ('id' in nested)
|
|
69
|
+
summary[key] = { id: nested['id'] };
|
|
70
|
+
else
|
|
71
|
+
summary[key] = '[object]';
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
summary[key] = value;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return summary;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/config/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PapiRule, EnvInfo, ProjectInfo, HostnameEntry } from '../papi/types.js';
|
|
2
|
+
export declare function findPmDirectory(repoPath: string): Promise<string>;
|
|
3
|
+
export declare function listSnippets(repoPath: string): Promise<string[]>;
|
|
4
|
+
export declare function readSnippet(repoPath: string, snippetName: string): Promise<PapiRule>;
|
|
5
|
+
export declare function readAllSnippets(repoPath: string): Promise<Map<string, PapiRule>>;
|
|
6
|
+
export declare function writeSnippet(repoPath: string, snippetName: string, content: PapiRule): Promise<void>;
|
|
7
|
+
export declare function readMetadata(repoPath: string): Promise<{
|
|
8
|
+
envInfo: EnvInfo;
|
|
9
|
+
projectInfo: ProjectInfo;
|
|
10
|
+
hostnames: HostnameEntry[];
|
|
11
|
+
}>;
|
|
12
|
+
//# sourceMappingURL=snippets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippets.d.ts","sourceRoot":"","sources":["../../src/config/snippets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtF,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBvE;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAKtE;AAED,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAK1F;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAYtF;AAED,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5D,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B,CAAC,CAcD"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { readdir, readFile, writeFile, mkdir, access } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
export async function findPmDirectory(repoPath) {
|
|
4
|
+
const entries = await readdir(repoPath, { withFileTypes: true });
|
|
5
|
+
const dirs = entries.filter(e => e.isDirectory());
|
|
6
|
+
// Primary: find a directory containing a config-snippets/ subdirectory
|
|
7
|
+
for (const dir of dirs) {
|
|
8
|
+
const candidate = resolve(repoPath, dir.name, 'config-snippets');
|
|
9
|
+
try {
|
|
10
|
+
await access(candidate);
|
|
11
|
+
return resolve(repoPath, dir.name);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
// no config-snippets here, continue
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
throw new Error(`No Akamai property directory found in ${repoPath}. ` +
|
|
18
|
+
`Expected a directory containing config-snippets/ (Akamai CLI layout).`);
|
|
19
|
+
}
|
|
20
|
+
export async function listSnippets(repoPath) {
|
|
21
|
+
const pmDir = await findPmDirectory(repoPath);
|
|
22
|
+
const snippetsDir = resolve(pmDir, 'config-snippets');
|
|
23
|
+
const entries = await readdir(snippetsDir);
|
|
24
|
+
return entries.filter(f => f.endsWith('.json'));
|
|
25
|
+
}
|
|
26
|
+
export async function readSnippet(repoPath, snippetName) {
|
|
27
|
+
const pmDir = await findPmDirectory(repoPath);
|
|
28
|
+
const filePath = resolve(pmDir, 'config-snippets', snippetName);
|
|
29
|
+
const content = await readFile(filePath, 'utf-8');
|
|
30
|
+
return JSON.parse(content);
|
|
31
|
+
}
|
|
32
|
+
export async function readAllSnippets(repoPath) {
|
|
33
|
+
const names = await listSnippets(repoPath);
|
|
34
|
+
const pmDir = await findPmDirectory(repoPath);
|
|
35
|
+
const snippetsDir = resolve(pmDir, 'config-snippets');
|
|
36
|
+
const result = new Map();
|
|
37
|
+
for (const name of names) {
|
|
38
|
+
const content = await readFile(resolve(snippetsDir, name), 'utf-8');
|
|
39
|
+
result.set(name, JSON.parse(content));
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
export async function writeSnippet(repoPath, snippetName, content) {
|
|
44
|
+
const requiredFields = [
|
|
45
|
+
'name',
|
|
46
|
+
'children',
|
|
47
|
+
'behaviors',
|
|
48
|
+
'criteria',
|
|
49
|
+
'criteriaMustSatisfy',
|
|
50
|
+
];
|
|
51
|
+
for (const field of requiredFields) {
|
|
52
|
+
if (!(field in content)) {
|
|
53
|
+
throw new Error(`Missing required PapiRule field: ${field}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const pmDir = await findPmDirectory(repoPath);
|
|
57
|
+
const snippetsDir = resolve(pmDir, 'config-snippets');
|
|
58
|
+
await mkdir(snippetsDir, { recursive: true });
|
|
59
|
+
const filePath = resolve(snippetsDir, snippetName);
|
|
60
|
+
await writeFile(filePath, JSON.stringify(content, null, 2) + '\n', 'utf-8');
|
|
61
|
+
}
|
|
62
|
+
export async function readMetadata(repoPath) {
|
|
63
|
+
const pmDir = await findPmDirectory(repoPath);
|
|
64
|
+
const [envRaw, projRaw, hostRaw] = await Promise.all([
|
|
65
|
+
readFile(resolve(pmDir, 'envInfo.json'), 'utf-8'),
|
|
66
|
+
readFile(resolve(pmDir, 'projectInfo.json'), 'utf-8'),
|
|
67
|
+
readFile(resolve(pmDir, 'hostnames.json'), 'utf-8'),
|
|
68
|
+
]);
|
|
69
|
+
return {
|
|
70
|
+
envInfo: JSON.parse(envRaw),
|
|
71
|
+
projectInfo: JSON.parse(projRaw),
|
|
72
|
+
hostnames: JSON.parse(hostRaw),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=snippets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippets.js","sourceRoot":"","sources":["../../src/config/snippets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare class GitError extends Error {
|
|
2
|
+
readonly exitCode?: number | undefined;
|
|
3
|
+
constructor(message: string, exitCode?: number | undefined);
|
|
4
|
+
}
|
|
5
|
+
export interface RemoteInfo {
|
|
6
|
+
host: string;
|
|
7
|
+
owner: string;
|
|
8
|
+
repo: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function createBranch(repoPath: string, branchName: string): Promise<void>;
|
|
11
|
+
export declare function commitAndPush(repoPath: string, message: string, files?: string[]): Promise<void>;
|
|
12
|
+
export declare function getCurrentBranch(repoPath: string): Promise<string>;
|
|
13
|
+
export declare function getRemoteUrl(repoPath: string): Promise<string>;
|
|
14
|
+
export declare function parseRemoteUrl(url: string): RemoteInfo;
|
|
15
|
+
export declare function buildBranchName(type: string, description: string): string;
|
|
16
|
+
//# sourceMappingURL=git-ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-ops.d.ts","sourceRoot":"","sources":["../../src/git/git-ops.ts"],"names":[],"mappings":"AAKA,qBAAa,QAAS,SAAQ,KAAK;aACY,QAAQ,CAAC,EAAE,MAAM;gBAAlD,OAAO,EAAE,MAAM,EAAkB,QAAQ,CAAC,EAAE,MAAM,YAAA;CAI/D;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtF;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAStG;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGxE;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGpE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CActD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAOzE"}
|