confluence-tools 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 +150 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +243 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/auth.d.ts +7 -0
- package/dist/core/auth.d.ts.map +1 -0
- package/dist/core/auth.js +25 -0
- package/dist/core/auth.js.map +1 -0
- package/dist/core/client.d.ts +17 -0
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js +124 -0
- package/dist/core/client.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +5 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/markdown.d.ts +15 -0
- package/dist/core/markdown.d.ts.map +1 -0
- package/dist/core/markdown.js +83 -0
- package/dist/core/markdown.js.map +1 -0
- package/dist/core/types.d.ts +67 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +12 -0
- package/dist/core/types.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +178 -0
- package/dist/mcp/index.js.map +1 -0
- package/package.json +45 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shadowgandor
|
|
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,150 @@
|
|
|
1
|
+
# confluence-tools
|
|
2
|
+
|
|
3
|
+
CLI and MCP server for Atlassian Confluence. Read, create, update, and delete pages from your terminal or AI agent.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **CLI** — `confluence` command with full CRUD operations, interactive confirmation prompts, coloured output
|
|
8
|
+
- **MCP server** — Expose the same operations as tools for AI agents (Claude Code, etc.)
|
|
9
|
+
- **Shared core** — Both interfaces use the same TypeScript client; bug fixes and features land in one place
|
|
10
|
+
- **Markdown support** — Automatically converts `.md` files to Confluence storage format
|
|
11
|
+
- **Secure by design** — Credentials are read from environment variables only, never written to disk
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g confluence-tools
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or run without installing:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx confluence-tools confluence auth
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Environment variables
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
export CONFLUENCE_URL="https://your-instance.atlassian.net/wiki"
|
|
29
|
+
export CONFLUENCE_EMAIL="you@example.com"
|
|
30
|
+
export CONFLUENCE_TOKEN="your-api-token"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Generate an API token at https://id.atlassian.com/manage-profile/security/api-tokens
|
|
34
|
+
|
|
35
|
+
## CLI usage
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Verify connection
|
|
39
|
+
confluence auth
|
|
40
|
+
|
|
41
|
+
# List spaces
|
|
42
|
+
confluence spaces
|
|
43
|
+
|
|
44
|
+
# Read a page
|
|
45
|
+
confluence read 12345678
|
|
46
|
+
confluence read 12345678 --json
|
|
47
|
+
|
|
48
|
+
# Search pages in a space
|
|
49
|
+
confluence search -s DEV -t "Architecture"
|
|
50
|
+
|
|
51
|
+
# Create a page (prompts for confirmation)
|
|
52
|
+
confluence create -s DEV -t "New RFC" -f proposal.md
|
|
53
|
+
|
|
54
|
+
# Update a page
|
|
55
|
+
confluence update 12345678 -f updated.md -m "Revised section 3"
|
|
56
|
+
|
|
57
|
+
# Delete a page
|
|
58
|
+
confluence delete 12345678
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
All write/delete commands prompt for confirmation. Pass `-y` to skip (useful in scripts).
|
|
62
|
+
|
|
63
|
+
## MCP server usage
|
|
64
|
+
|
|
65
|
+
Add to your Claude Code config (`~/.claude.json` or project `.mcp.json`):
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"confluence": {
|
|
71
|
+
"command": "confluence-mcp",
|
|
72
|
+
"env": {
|
|
73
|
+
"CONFLUENCE_URL": "https://your-instance.atlassian.net/wiki",
|
|
74
|
+
"CONFLUENCE_EMAIL": "you@example.com",
|
|
75
|
+
"CONFLUENCE_TOKEN": "your-api-token"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Or without a global install:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"mcpServers": {
|
|
87
|
+
"confluence": {
|
|
88
|
+
"command": "npx",
|
|
89
|
+
"args": ["--package=confluence-tools", "-y", "confluence-mcp"],
|
|
90
|
+
"env": {
|
|
91
|
+
"CONFLUENCE_URL": "https://your-instance.atlassian.net/wiki",
|
|
92
|
+
"CONFLUENCE_EMAIL": "you@example.com",
|
|
93
|
+
"CONFLUENCE_TOKEN": "your-api-token"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Available tools
|
|
101
|
+
|
|
102
|
+
| Tool | Description | Confirmation needed |
|
|
103
|
+
|----------------------------|--------------------------------------|---------------------|
|
|
104
|
+
| `confluence_auth` | Verify connection | No |
|
|
105
|
+
| `confluence_list_spaces` | List spaces | No |
|
|
106
|
+
| `confluence_read_page` | Read page content by ID | No |
|
|
107
|
+
| `confluence_search_pages` | Search by space key and title | No |
|
|
108
|
+
| `confluence_create_page` | Create a new page | **Yes** |
|
|
109
|
+
| `confluence_update_page` | Update an existing page | **Yes** |
|
|
110
|
+
| `confluence_delete_page` | Delete a page | **Yes** |
|
|
111
|
+
|
|
112
|
+
## Project structure
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
src/
|
|
116
|
+
├── core/ # Shared library
|
|
117
|
+
│ ├── client.ts # Confluence REST API client
|
|
118
|
+
│ ├── auth.ts # Environment-based config loader
|
|
119
|
+
│ ├── markdown.ts # Markdown → storage format converter
|
|
120
|
+
│ ├── types.ts # TypeScript interfaces
|
|
121
|
+
│ └── index.ts # Barrel export
|
|
122
|
+
├── cli/
|
|
123
|
+
│ └── index.ts # Commander.js CLI
|
|
124
|
+
└── mcp/
|
|
125
|
+
└── index.ts # MCP server (stdio transport)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Development
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# Run CLI in dev mode (no build step)
|
|
132
|
+
npm run dev:cli -- auth
|
|
133
|
+
npm run dev:cli -- search -s DEV -t "RFC"
|
|
134
|
+
|
|
135
|
+
# Run MCP server in dev mode
|
|
136
|
+
npm run dev:mcp
|
|
137
|
+
|
|
138
|
+
# Build
|
|
139
|
+
npm run build
|
|
140
|
+
|
|
141
|
+
# Test
|
|
142
|
+
npm test
|
|
143
|
+
|
|
144
|
+
# Lint
|
|
145
|
+
npm run lint
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT — GeeveeH Software
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { ConfluenceClient, loadConfigFromEnv, ConfluenceApiError } from "../core/index.js";
|
|
5
|
+
import { resolveBody } from "../core/markdown.js";
|
|
6
|
+
// ── Helpers ────────────────────────────────────────────────────────
|
|
7
|
+
function createClient() {
|
|
8
|
+
const config = loadConfigFromEnv();
|
|
9
|
+
return new ConfluenceClient(config);
|
|
10
|
+
}
|
|
11
|
+
function formatPage(page) {
|
|
12
|
+
return `${chalk.bold(page.title)} ${chalk.dim(`(id: ${page.id}, v${page.version?.number ?? "?"}, ${page.status})`)}`;
|
|
13
|
+
}
|
|
14
|
+
function handleError(err) {
|
|
15
|
+
if (err instanceof ConfluenceApiError) {
|
|
16
|
+
console.error(chalk.red(`✗ API error ${err.statusCode}: ${err.message}`));
|
|
17
|
+
if (err.data)
|
|
18
|
+
console.error(chalk.dim(JSON.stringify(err.data, null, 2)));
|
|
19
|
+
}
|
|
20
|
+
else if (err instanceof Error) {
|
|
21
|
+
console.error(chalk.red(`✗ ${err.message}`));
|
|
22
|
+
}
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
// ── Program ────────────────────────────────────────────────────────
|
|
26
|
+
const program = new Command()
|
|
27
|
+
.name("confluence")
|
|
28
|
+
.description("CLI for Atlassian Confluence — create, read, update, delete pages")
|
|
29
|
+
.version("0.1.0");
|
|
30
|
+
// ── auth ────────────────────────────────────────────────────────────
|
|
31
|
+
program
|
|
32
|
+
.command("auth")
|
|
33
|
+
.description("Verify your Confluence connection")
|
|
34
|
+
.action(async () => {
|
|
35
|
+
try {
|
|
36
|
+
const client = createClient();
|
|
37
|
+
const spaces = await client.verifyConnection();
|
|
38
|
+
console.log(chalk.green("✓ Connected successfully."));
|
|
39
|
+
console.log(` Found ${spaces.length} space(s):`);
|
|
40
|
+
for (const s of spaces) {
|
|
41
|
+
console.log(` • ${chalk.bold(s.name)} ${chalk.dim(`[${s.key}]`)}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
handleError(err);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
// ── spaces ──────────────────────────────────────────────────────────
|
|
49
|
+
program
|
|
50
|
+
.command("spaces")
|
|
51
|
+
.description("List available spaces")
|
|
52
|
+
.option("-l, --limit <n>", "Max spaces to return", "25")
|
|
53
|
+
.action(async (opts) => {
|
|
54
|
+
try {
|
|
55
|
+
const client = createClient();
|
|
56
|
+
const spaces = await client.listSpaces(Number(opts.limit));
|
|
57
|
+
for (const s of spaces) {
|
|
58
|
+
console.log(`${chalk.bold(s.name)} ${chalk.dim(`[${s.key}] id:${s.id}`)}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
handleError(err);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
// ── read ────────────────────────────────────────────────────────────
|
|
66
|
+
program
|
|
67
|
+
.command("read <pageId>")
|
|
68
|
+
.description("Read a page by ID")
|
|
69
|
+
.option("--json", "Output raw JSON")
|
|
70
|
+
.action(async (pageId, opts) => {
|
|
71
|
+
try {
|
|
72
|
+
const client = createClient();
|
|
73
|
+
const page = await client.getPage(pageId);
|
|
74
|
+
if (opts.json) {
|
|
75
|
+
console.log(JSON.stringify(page, null, 2));
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
console.log(formatPage(page));
|
|
79
|
+
if (page.body?.storage?.value) {
|
|
80
|
+
console.log(chalk.dim("─".repeat(60)));
|
|
81
|
+
console.log(page.body.storage.value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
handleError(err);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
// ── search ──────────────────────────────────────────────────────────
|
|
90
|
+
program
|
|
91
|
+
.command("search")
|
|
92
|
+
.description("Search for pages in a space")
|
|
93
|
+
.requiredOption("-s, --space <key>", "Space key")
|
|
94
|
+
.option("-t, --title <title>", "Filter by title")
|
|
95
|
+
.option("-l, --limit <n>", "Max results", "25")
|
|
96
|
+
.action(async (opts) => {
|
|
97
|
+
try {
|
|
98
|
+
const client = createClient();
|
|
99
|
+
const pages = await client.searchPages({
|
|
100
|
+
spaceKey: opts.space,
|
|
101
|
+
title: opts.title,
|
|
102
|
+
limit: Number(opts.limit),
|
|
103
|
+
});
|
|
104
|
+
if (pages.length === 0) {
|
|
105
|
+
console.log(chalk.yellow("No pages found."));
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
for (const p of pages) {
|
|
109
|
+
console.log(formatPage(p));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
handleError(err);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
// ── create ──────────────────────────────────────────────────────────
|
|
117
|
+
program
|
|
118
|
+
.command("create")
|
|
119
|
+
.description("Create a new page")
|
|
120
|
+
.requiredOption("-s, --space <key>", "Space key")
|
|
121
|
+
.requiredOption("-t, --title <title>", "Page title")
|
|
122
|
+
.requiredOption("-f, --file <path>", "Content file (.md, .html) or inline string")
|
|
123
|
+
.option("-p, --parent <id>", "Parent page ID")
|
|
124
|
+
.option("--draft", "Create as draft")
|
|
125
|
+
.option("-y, --yes", "Skip confirmation prompt")
|
|
126
|
+
.action(async (opts) => {
|
|
127
|
+
try {
|
|
128
|
+
const client = createClient();
|
|
129
|
+
// Resolve space key → space ID
|
|
130
|
+
const space = await client.getSpaceByKey(opts.space);
|
|
131
|
+
const body = await resolveBody(opts.file);
|
|
132
|
+
if (!opts.yes) {
|
|
133
|
+
console.log(chalk.yellow("⚠ About to create page:"));
|
|
134
|
+
console.log(` Space: ${space.name} [${space.key}]`);
|
|
135
|
+
console.log(` Title: ${opts.title}`);
|
|
136
|
+
if (opts.parent)
|
|
137
|
+
console.log(` Parent: ${opts.parent}`);
|
|
138
|
+
console.log(` Status: ${opts.draft ? "draft" : "published"}`);
|
|
139
|
+
console.log();
|
|
140
|
+
const ok = await confirm("Proceed?");
|
|
141
|
+
if (!ok) {
|
|
142
|
+
console.log(chalk.dim("Cancelled."));
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const page = await client.createPage({
|
|
147
|
+
spaceId: space.id,
|
|
148
|
+
title: opts.title,
|
|
149
|
+
body,
|
|
150
|
+
parentId: opts.parent,
|
|
151
|
+
status: opts.draft ? "draft" : "current",
|
|
152
|
+
});
|
|
153
|
+
console.log(chalk.green(`✓ Created: ${formatPage(page)}`));
|
|
154
|
+
console.log(` ${chalk.cyan(pageUrl(page))}`);
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
handleError(err);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
// ── update ──────────────────────────────────────────────────────────
|
|
161
|
+
program
|
|
162
|
+
.command("update <pageId>")
|
|
163
|
+
.description("Update an existing page")
|
|
164
|
+
.option("-t, --title <title>", "New title")
|
|
165
|
+
.option("-f, --file <path>", "New content file (.md, .html) or inline string")
|
|
166
|
+
.option("-m, --message <msg>", "Version message")
|
|
167
|
+
.option("-y, --yes", "Skip confirmation prompt")
|
|
168
|
+
.action(async (pageId, opts) => {
|
|
169
|
+
try {
|
|
170
|
+
const client = createClient();
|
|
171
|
+
const current = await client.getPage(pageId);
|
|
172
|
+
const body = opts.file ? await resolveBody(opts.file) : undefined;
|
|
173
|
+
if (!opts.yes) {
|
|
174
|
+
console.log(chalk.yellow("⚠ About to update page:"));
|
|
175
|
+
console.log(` Page: ${formatPage(current)}`);
|
|
176
|
+
if (opts.title)
|
|
177
|
+
console.log(` Title: ${current.title} → ${opts.title}`);
|
|
178
|
+
if (body)
|
|
179
|
+
console.log(` Body: will be replaced`);
|
|
180
|
+
console.log();
|
|
181
|
+
const ok = await confirm("Proceed?");
|
|
182
|
+
if (!ok) {
|
|
183
|
+
console.log(chalk.dim("Cancelled."));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const updated = await client.updatePage({
|
|
188
|
+
pageId,
|
|
189
|
+
title: opts.title,
|
|
190
|
+
body,
|
|
191
|
+
versionMessage: opts.message,
|
|
192
|
+
});
|
|
193
|
+
console.log(chalk.green(`✓ Updated: ${formatPage(updated)}`));
|
|
194
|
+
console.log(` ${chalk.cyan(pageUrl(updated))}`);
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
handleError(err);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
// ── delete ──────────────────────────────────────────────────────────
|
|
201
|
+
program
|
|
202
|
+
.command("delete <pageId>")
|
|
203
|
+
.description("Delete a page")
|
|
204
|
+
.option("-y, --yes", "Skip confirmation prompt")
|
|
205
|
+
.action(async (pageId, opts) => {
|
|
206
|
+
try {
|
|
207
|
+
const client = createClient();
|
|
208
|
+
const page = await client.getPage(pageId);
|
|
209
|
+
if (!opts.yes) {
|
|
210
|
+
console.log(chalk.red("⚠ About to DELETE page:"));
|
|
211
|
+
console.log(` ${formatPage(page)}`);
|
|
212
|
+
console.log();
|
|
213
|
+
const ok = await confirm("This cannot be undone. Proceed?");
|
|
214
|
+
if (!ok) {
|
|
215
|
+
console.log(chalk.dim("Cancelled."));
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
await client.deletePage(pageId);
|
|
220
|
+
console.log(chalk.green(`✓ Deleted page "${page.title}" (id: ${pageId})`));
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
handleError(err);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
// ── Utilities ───────────────────────────────────────────────────────
|
|
227
|
+
function pageUrl(page) {
|
|
228
|
+
const base = page._links?.base ?? process.env.CONFLUENCE_URL ?? "";
|
|
229
|
+
return `${base}/pages/${page.id}`;
|
|
230
|
+
}
|
|
231
|
+
async function confirm(question) {
|
|
232
|
+
const { createInterface } = await import("node:readline");
|
|
233
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
234
|
+
return new Promise((resolve) => {
|
|
235
|
+
rl.question(`${question} [y/N] `, (answer) => {
|
|
236
|
+
rl.close();
|
|
237
|
+
resolve(answer.trim().toLowerCase().startsWith("y"));
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
// ── Run ─────────────────────────────────────────────────────────────
|
|
242
|
+
program.parse();
|
|
243
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,gBAAgB,CAqBpD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve Confluence config from environment variables.
|
|
3
|
+
* Throws a clear error if any are missing.
|
|
4
|
+
*/
|
|
5
|
+
export function loadConfigFromEnv() {
|
|
6
|
+
const baseUrl = process.env.CONFLUENCE_URL;
|
|
7
|
+
const email = process.env.CONFLUENCE_EMAIL;
|
|
8
|
+
const token = process.env.CONFLUENCE_TOKEN;
|
|
9
|
+
const missing = [];
|
|
10
|
+
if (!baseUrl)
|
|
11
|
+
missing.push("CONFLUENCE_URL");
|
|
12
|
+
if (!email)
|
|
13
|
+
missing.push("CONFLUENCE_EMAIL");
|
|
14
|
+
if (!token)
|
|
15
|
+
missing.push("CONFLUENCE_TOKEN");
|
|
16
|
+
if (missing.length > 0) {
|
|
17
|
+
throw new Error(`Missing required environment variable(s): ${missing.join(", ")}.\n` +
|
|
18
|
+
`Set them in your shell or .zshrc:\n` +
|
|
19
|
+
` export CONFLUENCE_URL="https://your-instance.atlassian.net/wiki"\n` +
|
|
20
|
+
` export CONFLUENCE_EMAIL="you@example.com"\n` +
|
|
21
|
+
` export CONFLUENCE_TOKEN="your-api-token"`);
|
|
22
|
+
}
|
|
23
|
+
return { baseUrl: baseUrl, email: email, token: token };
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAE3C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO;QAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAE7C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,6CAA6C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YAClE,qCAAqC;YACrC,sEAAsE;YACtE,+CAA+C;YAC/C,4CAA4C,CAC/C,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAQ,EAAE,KAAK,EAAE,KAAM,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ConfluenceConfig, ConfluencePage, ConfluenceSpace, PageCreateInput, PageUpdateInput, PageSearchOptions } from "./types.js";
|
|
2
|
+
export declare class ConfluenceClient {
|
|
3
|
+
private readonly baseUrl;
|
|
4
|
+
private readonly authHeader;
|
|
5
|
+
constructor(config: ConfluenceConfig);
|
|
6
|
+
private request;
|
|
7
|
+
verifyConnection(): Promise<ConfluenceSpace[]>;
|
|
8
|
+
listSpaces(limit?: number): Promise<ConfluenceSpace[]>;
|
|
9
|
+
getSpaceByKey(spaceKey: string): Promise<ConfluenceSpace>;
|
|
10
|
+
getPage(pageId: string): Promise<ConfluencePage>;
|
|
11
|
+
listPages(spaceId: string, limit?: number): Promise<ConfluencePage[]>;
|
|
12
|
+
searchPages(options: PageSearchOptions): Promise<ConfluencePage[]>;
|
|
13
|
+
createPage(input: PageCreateInput): Promise<ConfluencePage>;
|
|
14
|
+
updatePage(input: PageUpdateInput): Promise<ConfluencePage>;
|
|
15
|
+
deletePage(pageId: string): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,eAAe,EAEf,eAAe,EACf,eAAe,EACf,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAEpB,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,MAAM,EAAE,gBAAgB;YAStB,OAAO;IAkCf,gBAAgB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAS9C,UAAU,CAAC,KAAK,SAAK,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAOlD,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAYzD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAMhD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAOjE,WAAW,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAkBlE,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAsB3D,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IA0B3D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAKhD"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { ConfluenceApiError, } from "./types.js";
|
|
2
|
+
export class ConfluenceClient {
|
|
3
|
+
baseUrl;
|
|
4
|
+
authHeader;
|
|
5
|
+
constructor(config) {
|
|
6
|
+
// Strip trailing slash
|
|
7
|
+
this.baseUrl = config.baseUrl.replace(/\/+$/, "");
|
|
8
|
+
const encoded = Buffer.from(`${config.email}:${config.token}`).toString("base64");
|
|
9
|
+
this.authHeader = `Basic ${encoded}`;
|
|
10
|
+
}
|
|
11
|
+
// ── Low-level request helper ─────────────────────────────────────
|
|
12
|
+
async request(path, options = {}) {
|
|
13
|
+
const url = path.startsWith("http") ? path : `${this.baseUrl}${path}`;
|
|
14
|
+
const response = await fetch(url, {
|
|
15
|
+
...options,
|
|
16
|
+
headers: {
|
|
17
|
+
Authorization: this.authHeader,
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
Accept: "application/json",
|
|
20
|
+
...options.headers,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
let errorData;
|
|
25
|
+
try {
|
|
26
|
+
errorData = await response.json();
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
errorData = await response.text();
|
|
30
|
+
}
|
|
31
|
+
throw new ConfluenceApiError(response.status, response.statusText, errorData);
|
|
32
|
+
}
|
|
33
|
+
// 204 No Content (e.g. delete)
|
|
34
|
+
if (response.status === 204)
|
|
35
|
+
return undefined;
|
|
36
|
+
return response.json();
|
|
37
|
+
}
|
|
38
|
+
// ── Authentication check ─────────────────────────────────────────
|
|
39
|
+
async verifyConnection() {
|
|
40
|
+
const result = await this.request("/api/v2/spaces?limit=5");
|
|
41
|
+
return result.results;
|
|
42
|
+
}
|
|
43
|
+
// ── Spaces ───────────────────────────────────────────────────────
|
|
44
|
+
async listSpaces(limit = 25) {
|
|
45
|
+
const result = await this.request(`/api/v2/spaces?limit=${limit}`);
|
|
46
|
+
return result.results;
|
|
47
|
+
}
|
|
48
|
+
async getSpaceByKey(spaceKey) {
|
|
49
|
+
const result = await this.request(`/api/v2/spaces?keys=${encodeURIComponent(spaceKey)}`);
|
|
50
|
+
if (result.results.length === 0) {
|
|
51
|
+
throw new ConfluenceApiError(404, `Space with key "${spaceKey}" not found`);
|
|
52
|
+
}
|
|
53
|
+
return result.results[0];
|
|
54
|
+
}
|
|
55
|
+
// ── Read ─────────────────────────────────────────────────────────
|
|
56
|
+
async getPage(pageId) {
|
|
57
|
+
return this.request(`/api/v2/pages/${pageId}?body-format=storage`);
|
|
58
|
+
}
|
|
59
|
+
async listPages(spaceId, limit = 25) {
|
|
60
|
+
const result = await this.request(`/api/v2/spaces/${spaceId}/pages?limit=${limit}`);
|
|
61
|
+
return result.results;
|
|
62
|
+
}
|
|
63
|
+
async searchPages(options) {
|
|
64
|
+
const params = new URLSearchParams({
|
|
65
|
+
spaceKey: options.spaceKey,
|
|
66
|
+
expand: "body.storage,version",
|
|
67
|
+
limit: String(options.limit ?? 25),
|
|
68
|
+
});
|
|
69
|
+
if (options.title) {
|
|
70
|
+
params.set("title", options.title);
|
|
71
|
+
}
|
|
72
|
+
// CQL-based search uses v1 API
|
|
73
|
+
const result = await this.request(`/rest/api/content?${params.toString()}`);
|
|
74
|
+
return result.results;
|
|
75
|
+
}
|
|
76
|
+
// ── Create ───────────────────────────────────────────────────────
|
|
77
|
+
async createPage(input) {
|
|
78
|
+
const payload = {
|
|
79
|
+
spaceId: input.spaceId,
|
|
80
|
+
status: input.status ?? "current",
|
|
81
|
+
title: input.title,
|
|
82
|
+
body: {
|
|
83
|
+
representation: "storage",
|
|
84
|
+
value: input.body,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
if (input.parentId) {
|
|
88
|
+
payload.parentId = input.parentId;
|
|
89
|
+
}
|
|
90
|
+
return this.request("/api/v2/pages", {
|
|
91
|
+
method: "POST",
|
|
92
|
+
body: JSON.stringify(payload),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// ── Update ───────────────────────────────────────────────────────
|
|
96
|
+
async updatePage(input) {
|
|
97
|
+
// Fetch current version first
|
|
98
|
+
const current = await this.getPage(input.pageId);
|
|
99
|
+
const payload = {
|
|
100
|
+
id: input.pageId,
|
|
101
|
+
status: "current",
|
|
102
|
+
title: input.title ?? current.title,
|
|
103
|
+
body: {
|
|
104
|
+
representation: "storage",
|
|
105
|
+
value: input.body ?? current.body?.storage?.value ?? "",
|
|
106
|
+
},
|
|
107
|
+
version: {
|
|
108
|
+
number: current.version.number + 1,
|
|
109
|
+
message: input.versionMessage ?? "Updated via confluence-tools",
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
return this.request(`/api/v2/pages/${input.pageId}`, {
|
|
113
|
+
method: "PUT",
|
|
114
|
+
body: JSON.stringify(payload),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// ── Delete ───────────────────────────────────────────────────────
|
|
118
|
+
async deletePage(pageId) {
|
|
119
|
+
await this.request(`/api/v2/pages/${pageId}`, {
|
|
120
|
+
method: "DELETE",
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC/D,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC/D,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight Markdown → Confluence storage format converter.
|
|
3
|
+
*
|
|
4
|
+
* Handles the most common patterns. For full fidelity, consider
|
|
5
|
+
* adding a proper parser (e.g. marked/remark) later.
|
|
6
|
+
*/
|
|
7
|
+
export declare function markdownToStorage(md: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Read content from a file path or treat as inline content.
|
|
10
|
+
* If the string ends in .md, read the file and convert.
|
|
11
|
+
* If it ends in .html or .xml, read the file as-is (assume storage format).
|
|
12
|
+
* Otherwise treat it as inline markdown and convert.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveBody(input: string): Promise<string>;
|
|
15
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/core/markdown.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CA6EpD;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBhE"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight Markdown → Confluence storage format converter.
|
|
3
|
+
*
|
|
4
|
+
* Handles the most common patterns. For full fidelity, consider
|
|
5
|
+
* adding a proper parser (e.g. marked/remark) later.
|
|
6
|
+
*/
|
|
7
|
+
export function markdownToStorage(md) {
|
|
8
|
+
let html = md;
|
|
9
|
+
// Code blocks (fenced) — must come before inline processing
|
|
10
|
+
html = html.replace(/```(\w+)?\n([\s\S]*?)```/g, (_match, lang, code) => {
|
|
11
|
+
const langAttr = lang
|
|
12
|
+
? `<ac:parameter ac:name="language">${lang}</ac:parameter>`
|
|
13
|
+
: "";
|
|
14
|
+
return (`<ac:structured-macro ac:name="code">` +
|
|
15
|
+
`${langAttr}<ac:plain-text-body><![CDATA[${code.trimEnd()}]]></ac:plain-text-body>` +
|
|
16
|
+
`</ac:structured-macro>`);
|
|
17
|
+
});
|
|
18
|
+
// Headings
|
|
19
|
+
html = html.replace(/^######\s+(.+)$/gm, "<h6>$1</h6>");
|
|
20
|
+
html = html.replace(/^#####\s+(.+)$/gm, "<h5>$1</h5>");
|
|
21
|
+
html = html.replace(/^####\s+(.+)$/gm, "<h4>$1</h4>");
|
|
22
|
+
html = html.replace(/^###\s+(.+)$/gm, "<h3>$1</h3>");
|
|
23
|
+
html = html.replace(/^##\s+(.+)$/gm, "<h2>$1</h2>");
|
|
24
|
+
html = html.replace(/^#\s+(.+)$/gm, "<h1>$1</h1>");
|
|
25
|
+
// Bold & italic
|
|
26
|
+
html = html.replace(/\*\*\*(.+?)\*\*\*/g, "<strong><em>$1</em></strong>");
|
|
27
|
+
html = html.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
|
|
28
|
+
html = html.replace(/\*(.+?)\*/g, "<em>$1</em>");
|
|
29
|
+
// Inline code
|
|
30
|
+
html = html.replace(/`([^`]+)`/g, "<code>$1</code>");
|
|
31
|
+
// Links
|
|
32
|
+
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
|
|
33
|
+
// Unordered list items (simple, non-nested)
|
|
34
|
+
html = html.replace(/^(?:- |\* )(.+)$/gm, "<li>$1</li>");
|
|
35
|
+
// Wrap consecutive <li> in <ul>
|
|
36
|
+
html = html.replace(/(<li>.*<\/li>\n?)+/g, (match) => `<ul>\n${match}</ul>\n`);
|
|
37
|
+
// Paragraphs: wrap remaining plain lines
|
|
38
|
+
const lines = html.split("\n");
|
|
39
|
+
const result = [];
|
|
40
|
+
for (const line of lines) {
|
|
41
|
+
const trimmed = line.trim();
|
|
42
|
+
if (trimmed === "" ||
|
|
43
|
+
trimmed.startsWith("<h") ||
|
|
44
|
+
trimmed.startsWith("<ul") ||
|
|
45
|
+
trimmed.startsWith("</ul") ||
|
|
46
|
+
trimmed.startsWith("<li") ||
|
|
47
|
+
trimmed.startsWith("<ac:") ||
|
|
48
|
+
trimmed.startsWith("</ac:") ||
|
|
49
|
+
trimmed.startsWith("<p>") ||
|
|
50
|
+
trimmed.startsWith("<table")) {
|
|
51
|
+
result.push(line);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
result.push(`<p>${trimmed}</p>`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return result
|
|
58
|
+
.join("\n")
|
|
59
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
60
|
+
.trim();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Read content from a file path or treat as inline content.
|
|
64
|
+
* If the string ends in .md, read the file and convert.
|
|
65
|
+
* If it ends in .html or .xml, read the file as-is (assume storage format).
|
|
66
|
+
* Otherwise treat it as inline markdown and convert.
|
|
67
|
+
*/
|
|
68
|
+
export async function resolveBody(input) {
|
|
69
|
+
const { readFile } = await import("node:fs/promises");
|
|
70
|
+
if (input.endsWith(".md")) {
|
|
71
|
+
const content = await readFile(input, "utf-8");
|
|
72
|
+
return markdownToStorage(content);
|
|
73
|
+
}
|
|
74
|
+
if (input.endsWith(".html") || input.endsWith(".xml")) {
|
|
75
|
+
return readFile(input, "utf-8");
|
|
76
|
+
}
|
|
77
|
+
// Inline content — if it looks like HTML, pass through; otherwise convert
|
|
78
|
+
if (input.trimStart().startsWith("<")) {
|
|
79
|
+
return input;
|
|
80
|
+
}
|
|
81
|
+
return markdownToStorage(input);
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/core/markdown.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,IAAI,IAAI,GAAG,EAAE,CAAC;IAEd,4DAA4D;IAC5D,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,2BAA2B,EAC3B,CAAC,MAAM,EAAE,IAAwB,EAAE,IAAY,EAAE,EAAE;QACjD,MAAM,QAAQ,GAAG,IAAI;YACnB,CAAC,CAAC,oCAAoC,IAAI,iBAAiB;YAC3D,CAAC,CAAC,EAAE,CAAC;QACP,OAAO,CACL,sCAAsC;YACtC,GAAG,QAAQ,gCAAgC,IAAI,CAAC,OAAO,EAAE,0BAA0B;YACnF,wBAAwB,CACzB,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,WAAW;IACX,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;IACxD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;IACvD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;IACtD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;IACrD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;IACpD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;IAEnD,gBAAgB;IAChB,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,8BAA8B,CAAC,CAAC;IAC1E,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,CAAC;IAC7D,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IAEjD,cAAc;IACd,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;IAErD,QAAQ;IACR,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,0BAA0B,EAC1B,qBAAqB,CACtB,CAAC;IAEF,4CAA4C;IAC5C,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,oBAAoB,EACpB,aAAa,CACd,CAAC;IACF,gCAAgC;IAChC,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,qBAAqB,EACrB,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,KAAK,SAAS,CACnC,CAAC;IAEF,yCAAyC;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IACE,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;YACxB,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;YACzB,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;YAC1B,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;YACzB,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;YAC1B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;YAC3B,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;YACzB,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAC5B,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,MAAM,OAAO,MAAM,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,OAAO,MAAM;SACV,IAAI,CAAC,IAAI,CAAC;SACV,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;SAC1B,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAa;IAC7C,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAEtD,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,OAAO,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,0EAA0E;IAC1E,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export interface ConfluenceConfig {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
email: string;
|
|
4
|
+
token: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ConfluencePage {
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
status: string;
|
|
10
|
+
spaceId: string;
|
|
11
|
+
version: {
|
|
12
|
+
number: number;
|
|
13
|
+
message?: string;
|
|
14
|
+
createdAt?: string;
|
|
15
|
+
};
|
|
16
|
+
body?: {
|
|
17
|
+
storage?: {
|
|
18
|
+
value: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
_links?: {
|
|
22
|
+
webui?: string;
|
|
23
|
+
base?: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface ConfluenceSpace {
|
|
27
|
+
id: string;
|
|
28
|
+
key: string;
|
|
29
|
+
name: string;
|
|
30
|
+
type: string;
|
|
31
|
+
status: string;
|
|
32
|
+
}
|
|
33
|
+
export interface PageCreateInput {
|
|
34
|
+
spaceId: string;
|
|
35
|
+
title: string;
|
|
36
|
+
body: string;
|
|
37
|
+
parentId?: string;
|
|
38
|
+
status?: "current" | "draft";
|
|
39
|
+
}
|
|
40
|
+
export interface PageUpdateInput {
|
|
41
|
+
pageId: string;
|
|
42
|
+
title?: string;
|
|
43
|
+
body?: string;
|
|
44
|
+
versionMessage?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface PageSearchOptions {
|
|
47
|
+
spaceKey: string;
|
|
48
|
+
title?: string;
|
|
49
|
+
limit?: number;
|
|
50
|
+
}
|
|
51
|
+
export interface PaginatedResponse<T> {
|
|
52
|
+
results: T[];
|
|
53
|
+
_links?: {
|
|
54
|
+
next?: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export interface ApiError {
|
|
58
|
+
statusCode: number;
|
|
59
|
+
message: string;
|
|
60
|
+
data?: unknown;
|
|
61
|
+
}
|
|
62
|
+
export declare class ConfluenceApiError extends Error {
|
|
63
|
+
statusCode: number;
|
|
64
|
+
data?: unknown | undefined;
|
|
65
|
+
constructor(statusCode: number, message: string, data?: unknown | undefined);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACvC,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAElC,UAAU,EAAE,MAAM;IAElB,IAAI,CAAC,EAAE,OAAO;gBAFd,UAAU,EAAE,MAAM,EACzB,OAAO,EAAE,MAAM,EACR,IAAI,CAAC,EAAE,OAAO,YAAA;CAKxB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// ── Confluence API types ──────────────────────────────────────────────
|
|
2
|
+
export class ConfluenceApiError extends Error {
|
|
3
|
+
statusCode;
|
|
4
|
+
data;
|
|
5
|
+
constructor(statusCode, message, data) {
|
|
6
|
+
super(`Confluence API ${statusCode}: ${message}`);
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
this.data = data;
|
|
9
|
+
this.name = "ConfluenceApiError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,yEAAyE;AA4DzE,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAElC;IAEA;IAHT,YACS,UAAkB,EACzB,OAAe,EACR,IAAc;QAErB,KAAK,CAAC,kBAAkB,UAAU,KAAK,OAAO,EAAE,CAAC,CAAC;QAJ3C,eAAU,GAAV,UAAU,CAAQ;QAElB,SAAI,GAAJ,IAAI,CAAU;QAGrB,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { ConfluenceClient, loadConfigFromEnv, ConfluenceApiError } from "../core/index.js";
|
|
6
|
+
import { resolveBody } from "../core/markdown.js";
|
|
7
|
+
// ── Client singleton ───────────────────────────────────────────────
|
|
8
|
+
let _client = null;
|
|
9
|
+
function getClient() {
|
|
10
|
+
if (!_client) {
|
|
11
|
+
const config = loadConfigFromEnv();
|
|
12
|
+
_client = new ConfluenceClient(config);
|
|
13
|
+
}
|
|
14
|
+
return _client;
|
|
15
|
+
}
|
|
16
|
+
function formatError(err) {
|
|
17
|
+
if (err instanceof ConfluenceApiError) {
|
|
18
|
+
return `Confluence API error ${err.statusCode}: ${err.message}${err.data ? "\n" + JSON.stringify(err.data, null, 2) : ""}`;
|
|
19
|
+
}
|
|
20
|
+
if (err instanceof Error)
|
|
21
|
+
return err.message;
|
|
22
|
+
return String(err);
|
|
23
|
+
}
|
|
24
|
+
// ── Server setup ───────────────────────────────────────────────────
|
|
25
|
+
const server = new McpServer({
|
|
26
|
+
name: "confluence",
|
|
27
|
+
version: "0.1.0",
|
|
28
|
+
});
|
|
29
|
+
// ── Tools ──────────────────────────────────────────────────────────
|
|
30
|
+
server.tool("confluence_auth", "Verify the Confluence connection and list accessible spaces", {}, async () => {
|
|
31
|
+
try {
|
|
32
|
+
const spaces = await getClient().verifyConnection();
|
|
33
|
+
const text = [
|
|
34
|
+
"Connected successfully.",
|
|
35
|
+
`Found ${spaces.length} space(s):`,
|
|
36
|
+
...spaces.map((s) => `• ${s.name} [${s.key}] (id: ${s.id})`),
|
|
37
|
+
].join("\n");
|
|
38
|
+
return { content: [{ type: "text", text }] };
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
return { content: [{ type: "text", text: formatError(err) }], isError: true };
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
server.tool("confluence_list_spaces", "List available Confluence spaces", { limit: z.number().optional().describe("Max number of spaces to return (default 25)") }, async ({ limit }) => {
|
|
45
|
+
try {
|
|
46
|
+
const spaces = await getClient().listSpaces(limit ?? 25);
|
|
47
|
+
const text = spaces
|
|
48
|
+
.map((s) => `${s.name} [${s.key}] (id: ${s.id}, ${s.status})`)
|
|
49
|
+
.join("\n");
|
|
50
|
+
return { content: [{ type: "text", text: text || "No spaces found." }] };
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
return { content: [{ type: "text", text: formatError(err) }], isError: true };
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
server.tool("confluence_read_page", "Read a Confluence page by its ID, returning title, metadata, and body content", { pageId: z.string().describe("The Confluence page ID") }, async ({ pageId }) => {
|
|
57
|
+
try {
|
|
58
|
+
const page = await getClient().getPage(pageId);
|
|
59
|
+
const text = [
|
|
60
|
+
`Title: ${page.title}`,
|
|
61
|
+
`ID: ${page.id}`,
|
|
62
|
+
`Status: ${page.status}`,
|
|
63
|
+
`Version: ${page.version.number}`,
|
|
64
|
+
`Space ID: ${page.spaceId}`,
|
|
65
|
+
"",
|
|
66
|
+
"--- Body (storage format) ---",
|
|
67
|
+
page.body?.storage?.value ?? "(empty)",
|
|
68
|
+
].join("\n");
|
|
69
|
+
return { content: [{ type: "text", text }] };
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
return { content: [{ type: "text", text: formatError(err) }], isError: true };
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
server.tool("confluence_search_pages", "Search for pages in a Confluence space by title", {
|
|
76
|
+
spaceKey: z.string().describe("The space key (e.g. 'DEV', 'HR')"),
|
|
77
|
+
title: z.string().optional().describe("Filter by page title (partial match)"),
|
|
78
|
+
limit: z.number().optional().describe("Max results (default 25)"),
|
|
79
|
+
}, async ({ spaceKey, title, limit }) => {
|
|
80
|
+
try {
|
|
81
|
+
const pages = await getClient().searchPages({ spaceKey, title, limit });
|
|
82
|
+
if (pages.length === 0) {
|
|
83
|
+
return { content: [{ type: "text", text: "No pages found." }] };
|
|
84
|
+
}
|
|
85
|
+
const text = pages
|
|
86
|
+
.map((p) => `${p.title} (id: ${p.id}, v${p.version?.number ?? "?"})`)
|
|
87
|
+
.join("\n");
|
|
88
|
+
return { content: [{ type: "text", text }] };
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
return { content: [{ type: "text", text: formatError(err) }], isError: true };
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
server.tool("confluence_create_page", "Create a new Confluence page. IMPORTANT: Ask the user for confirmation before calling this tool.", {
|
|
95
|
+
spaceKey: z.string().describe("The space key to create the page in"),
|
|
96
|
+
title: z.string().describe("Page title"),
|
|
97
|
+
body: z.string().describe("Page content in Markdown or Confluence storage format (XHTML)"),
|
|
98
|
+
parentId: z.string().optional().describe("Parent page ID (omit for top-level)"),
|
|
99
|
+
draft: z.boolean().optional().describe("Create as draft instead of published"),
|
|
100
|
+
}, async ({ spaceKey, title, body, parentId, draft }) => {
|
|
101
|
+
try {
|
|
102
|
+
const client = getClient();
|
|
103
|
+
const space = await client.getSpaceByKey(spaceKey);
|
|
104
|
+
const resolvedBody = await resolveBody(body);
|
|
105
|
+
const page = await client.createPage({
|
|
106
|
+
spaceId: space.id,
|
|
107
|
+
title,
|
|
108
|
+
body: resolvedBody,
|
|
109
|
+
parentId,
|
|
110
|
+
status: draft ? "draft" : "current",
|
|
111
|
+
});
|
|
112
|
+
const text = [
|
|
113
|
+
`✓ Page created successfully.`,
|
|
114
|
+
` Title: ${page.title}`,
|
|
115
|
+
` ID: ${page.id}`,
|
|
116
|
+
` Space: ${space.name} [${space.key}]`,
|
|
117
|
+
` Status: ${page.status}`,
|
|
118
|
+
` URL: ${process.env.CONFLUENCE_URL}/pages/${page.id}`,
|
|
119
|
+
].join("\n");
|
|
120
|
+
return { content: [{ type: "text", text }] };
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
return { content: [{ type: "text", text: formatError(err) }], isError: true };
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
server.tool("confluence_update_page", "Update an existing Confluence page. IMPORTANT: Ask the user for confirmation before calling this tool.", {
|
|
127
|
+
pageId: z.string().describe("The page ID to update"),
|
|
128
|
+
title: z.string().optional().describe("New title (omit to keep current)"),
|
|
129
|
+
body: z.string().optional().describe("New content in Markdown or Confluence storage format"),
|
|
130
|
+
versionMessage: z.string().optional().describe("Version change message"),
|
|
131
|
+
}, async ({ pageId, title, body, versionMessage }) => {
|
|
132
|
+
try {
|
|
133
|
+
const resolvedBody = body ? await resolveBody(body) : undefined;
|
|
134
|
+
const page = await getClient().updatePage({
|
|
135
|
+
pageId,
|
|
136
|
+
title,
|
|
137
|
+
body: resolvedBody,
|
|
138
|
+
versionMessage,
|
|
139
|
+
});
|
|
140
|
+
const text = [
|
|
141
|
+
`✓ Page updated successfully.`,
|
|
142
|
+
` Title: ${page.title}`,
|
|
143
|
+
` ID: ${page.id}`,
|
|
144
|
+
` Version: ${page.version.number}`,
|
|
145
|
+
` URL: ${process.env.CONFLUENCE_URL}/pages/${page.id}`,
|
|
146
|
+
].join("\n");
|
|
147
|
+
return { content: [{ type: "text", text }] };
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
return { content: [{ type: "text", text: formatError(err) }], isError: true };
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
server.tool("confluence_delete_page", "Delete a Confluence page. IMPORTANT: Ask the user for confirmation before calling this tool.", { pageId: z.string().describe("The page ID to delete") }, async ({ pageId }) => {
|
|
154
|
+
try {
|
|
155
|
+
// Fetch page info first so we can report what was deleted
|
|
156
|
+
const page = await getClient().getPage(pageId);
|
|
157
|
+
await getClient().deletePage(pageId);
|
|
158
|
+
return {
|
|
159
|
+
content: [
|
|
160
|
+
{ type: "text", text: `✓ Deleted page "${page.title}" (id: ${pageId})` },
|
|
161
|
+
],
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
return { content: [{ type: "text", text: formatError(err) }], isError: true };
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
// ── Start ──────────────────────────────────────────────────────────
|
|
169
|
+
async function main() {
|
|
170
|
+
const transport = new StdioServerTransport();
|
|
171
|
+
await server.connect(transport);
|
|
172
|
+
console.error("Confluence MCP server running on stdio");
|
|
173
|
+
}
|
|
174
|
+
main().catch((err) => {
|
|
175
|
+
console.error("Fatal:", err);
|
|
176
|
+
process.exit(1);
|
|
177
|
+
});
|
|
178
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "confluence-tools",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI and MCP server for Atlassian Confluence — read, create, update, and delete pages from your terminal or AI agent.",
|
|
5
|
+
"author": "GeeveeH Software",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"confluence": "./dist/cli/index.js",
|
|
10
|
+
"confluence-mcp": "./dist/mcp/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"exports": {
|
|
18
|
+
".": "./dist/core/index.js",
|
|
19
|
+
"./mcp": "./dist/mcp/index.js"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"dev:cli": "tsx src/cli/index.ts",
|
|
24
|
+
"dev:mcp": "tsx src/mcp/index.ts",
|
|
25
|
+
"lint": "eslint src/",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"prepublishOnly": "npm run build"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"commander": "^13.1.0",
|
|
31
|
+
"chalk": "^5.4.1",
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
33
|
+
"zod": "^3.24.4"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^22.15.0",
|
|
37
|
+
"tsx": "^4.19.0",
|
|
38
|
+
"typescript": "^5.8.0",
|
|
39
|
+
"vitest": "^3.1.0",
|
|
40
|
+
"eslint": "^9.20.0"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20"
|
|
44
|
+
}
|
|
45
|
+
}
|