brewpage-mcp 1.16.4 → 1.16.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -8
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +48 -41
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Choosing a host? See how BrewPage compares with GitHub Pages, Netlify Drop, Tiin
|
|
|
17
17
|
## Quick Start
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
npx -y brewpage-mcp@1.16.
|
|
20
|
+
npx -y brewpage-mcp@1.16.6
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Requires Node.js 20 or newer. This starts the stdio server for an MCP client.
|
|
@@ -50,7 +50,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
50
50
|
"mcpServers": {
|
|
51
51
|
"brewpage": {
|
|
52
52
|
"command": "npx",
|
|
53
|
-
"args": ["-y", "brewpage-mcp@1.16.
|
|
53
|
+
"args": ["-y", "brewpage-mcp@1.16.6"]
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -61,7 +61,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
61
61
|
Register a project-scoped stdio server:
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
-
claude mcp add --transport stdio --scope project brewpage -- npx -y brewpage-mcp@1.16.
|
|
64
|
+
claude mcp add --transport stdio --scope project brewpage -- npx -y brewpage-mcp@1.16.6
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
This writes `.mcp.json` in the project root. Use `--scope user` for user-scoped registration. See the [official Claude Code MCP guide](https://code.claude.com/docs/en/mcp).
|
|
@@ -75,7 +75,7 @@ Open **Settings > MCP** and add:
|
|
|
75
75
|
"mcpServers": {
|
|
76
76
|
"brewpage": {
|
|
77
77
|
"command": "npx",
|
|
78
|
-
"args": ["-y", "brewpage-mcp@1.16.
|
|
78
|
+
"args": ["-y", "brewpage-mcp@1.16.6"]
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -89,7 +89,7 @@ Open the Cline MCP settings panel and add:
|
|
|
89
89
|
{
|
|
90
90
|
"brewpage": {
|
|
91
91
|
"command": "npx",
|
|
92
|
-
"args": ["-y", "brewpage-mcp@1.16.
|
|
92
|
+
"args": ["-y", "brewpage-mcp@1.16.6"]
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
```
|
|
@@ -97,7 +97,7 @@ Open the Cline MCP settings panel and add:
|
|
|
97
97
|
### Global Install
|
|
98
98
|
|
|
99
99
|
```bash
|
|
100
|
-
npm install -g brewpage-mcp@1.16.
|
|
100
|
+
npm install -g brewpage-mcp@1.16.6
|
|
101
101
|
brewpage-mcp
|
|
102
102
|
```
|
|
103
103
|
|
|
@@ -176,7 +176,7 @@ publish_html(content="<h1>Report</h1>...", format="HTML", ttlDays=15)
|
|
|
176
176
|
|
|
177
177
|
Update an existing HTML or Markdown page in place, preserving its short URL. Requires the original `ownerToken` returned at creation.
|
|
178
178
|
|
|
179
|
-
Parameters: `namespace` (string), `id` (string), `content` (string, the new body), `ownerToken` (string), `format` (optional HTML/Markdown alias or supported code language such as `json`, `yaml`, or `typescript`; omitted preserves the stored format).
|
|
179
|
+
Parameters: `namespace` (string), `id` (string), `content` (string, the new body), `ownerToken` (string), `format` (optional HTML/Markdown alias or supported code language such as `json`, `yaml`, or `typescript`; omitted preserves the stored format), `tags` (optional; replace the stored tags, `[]` clears, omitted keeps them).
|
|
180
180
|
|
|
181
181
|
An update never changes the link or delivery mode; an advisory `deliveryModeReason` and `Delivery notice:` line are printed when the server returns them.
|
|
182
182
|
|
|
@@ -250,7 +250,7 @@ publish_site(files=[{"path": "index.html", "content": "..."}, {"path": "style.cs
|
|
|
250
250
|
|
|
251
251
|
Replace an owned site's complete file set at the same ID and primary link. Files absent from the new bundle are removed; matching files are overwritten and new files added. Hosting stays unchanged. The `publish_site` limits and status codes apply.
|
|
252
252
|
|
|
253
|
-
Parameters: `namespace`, `id`, `ownerToken`, exactly one of `entryContent` or a non-empty `files` array of `{path, content}`, optional `entry` (default `index.html`), `ttlDays` (ignored; existing expiry is preserved and a `ttl-ignored` notice is returned), and `tags
|
|
253
|
+
Parameters: `namespace`, `id`, `ownerToken`, exactly one of `entryContent` or a non-empty `files` array of `{path, content}`, optional `entry` (default `index.html`), `ttlDays` (ignored; existing expiry is preserved and a `ttl-ignored` notice is returned), and `tags` (optional; replace the stored tags, `[]` clears, omitted keeps them).
|
|
254
254
|
|
|
255
255
|
```text
|
|
256
256
|
republish_site(namespace="public", id="aBcDeFgHiJ", ownerToken="tok_...", files=[{"path":"index.html","content":"<h1>Updated site</h1>"}])
|
|
@@ -530,6 +530,14 @@ Every publish response includes an **owner token** -- the only credential that a
|
|
|
530
530
|
|
|
531
531
|
## Changelog
|
|
532
532
|
|
|
533
|
+
## 1.16.6 -- 2026-10-31
|
|
534
|
+
|
|
535
|
+
- `publish_html`, `publish_file` and `publish_site` descriptions lead with `namespace=public` to be found (gallery + Google, Bing & AI search; omitted: private); the `namespace` input names what to publish publicly (docs, guides, demos, portfolios, reports, landing pages) and the generated `priv-*` default; the private result line says how to be found. Shorter texts, no new facts.
|
|
536
|
+
|
|
537
|
+
## 1.16.5 -- 2026-10-30
|
|
538
|
+
|
|
539
|
+
- `update_html` takes optional `tags` (sent as `?tags=a,b`); `update_html` and `republish_site` tags replace the stored tags, `[]` clears them, omitted keeps them. A 429 on any write prints the server's `Retry-After` beside the verbatim body (`retryAfterSeconds`).
|
|
540
|
+
|
|
533
541
|
## 1.16.4 -- 2026-10-30
|
|
534
542
|
|
|
535
543
|
- Owner update tools (`update_html`, `republish_site`, `update_json`, `set_kv`) answer a 404 with the server body plus which publish tool makes a new copy; `delete_resource` relays the 404 unchanged.
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
2
2
|
export declare const DEFAULT_BASE_URL = "https://brewpage.app";
|
|
3
|
-
export declare const USER_AGENT = "brewpage-mcp/1.16.
|
|
3
|
+
export declare const USER_AGENT = "brewpage-mcp/1.16.6";
|
|
4
4
|
export declare const OWNER_TOKEN_ENV = "BREWPAGE_OWNER_TOKEN";
|
|
5
5
|
export interface ServerOptions {
|
|
6
6
|
/** BrewPage origin for API calls; default https://brewpage.app. */
|
package/dist/tools.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
export const DEFAULT_BASE_URL = "https://brewpage.app";
|
|
4
|
-
export const USER_AGENT = "brewpage-mcp/1.16.
|
|
4
|
+
export const USER_AGENT = "brewpage-mcp/1.16.6";
|
|
5
5
|
export const OWNER_TOKEN_ENV = "BREWPAGE_OWNER_TOKEN";
|
|
6
6
|
const READ_ONLY = { readOnlyHint: true };
|
|
7
7
|
const DESTRUCTIVE = { readOnlyHint: false, destructiveHint: true };
|
|
@@ -54,9 +54,9 @@ function maskToken(token) {
|
|
|
54
54
|
function textResult(text, isError = false) {
|
|
55
55
|
return isError ? { content: [{ type: "text", text }], isError: true } : { content: [{ type: "text", text }] };
|
|
56
56
|
}
|
|
57
|
-
/** ` Retry-After: <value>.` for a busy 503 that sends the header, else empty. */
|
|
57
|
+
/** ` Retry-After: <value>.` for a 429 or busy 503 that sends the header, else empty. */
|
|
58
58
|
function retryAfterText(status, headers) {
|
|
59
|
-
const after = status === 503 ? headers?.get("retry-after") : null;
|
|
59
|
+
const after = status === 429 || status === 503 ? headers?.get("retry-after") : null;
|
|
60
60
|
return after ? ` Retry-After: ${after}.` : "";
|
|
61
61
|
}
|
|
62
62
|
/** Create tool for each content update: a 404 update means the row is gone, so the agent publishes anew. */
|
|
@@ -99,17 +99,19 @@ function resolveNamespace(namespace) {
|
|
|
99
99
|
return namespace && namespace.length > 0 ? namespace : defaultPrivateNamespace();
|
|
100
100
|
}
|
|
101
101
|
const UNLISTED_NOTICE = "Private: not listed. Anyone with the link can open it.";
|
|
102
|
-
const LISTABLE_HINT = "
|
|
102
|
+
const LISTABLE_HINT = " To be found, send namespace=public: gallery + Google, Bing & AI search.";
|
|
103
103
|
const PROTECTED_UNLISTED_NOTICE = "Password: link + password. Not listed.";
|
|
104
|
-
const PUBLIC_NAMESPACE_LEAD = "namespace=public
|
|
105
|
-
"
|
|
104
|
+
const PUBLIC_NAMESPACE_LEAD = "Send namespace=public for anything meant to be found or shared (docs, guides, demos, portfolios, reports, landing pages): " +
|
|
105
|
+
"listed in the public gallery and sitemap, so Google, Bing and AI search index it and people discover it. ";
|
|
106
106
|
const PUBLIC_NAMESPACE_TAIL = " Anyone can find and read a public page, so it is unsuitable for secrets, tokens or personal data. " +
|
|
107
|
-
"Omit (default): private
|
|
107
|
+
"Omit (default): private, a generated priv-* namespace; unlisted, not indexed; the link still opens it. ";
|
|
108
|
+
/** Tool-description lead for listable publish tools. */
|
|
109
|
+
const PUBLIC_HINT = "Send namespace=public to be found: gallery + Google, Bing & AI search. Omitted: private. ";
|
|
108
110
|
const NAMESPACE_FORMAT = "Lowercase only: 1-32 of a-z, 0-9, hyphen.";
|
|
109
111
|
/** `namespace` for publish_html and publish_file. */
|
|
110
112
|
const NAMESPACE_DESCRIPTION = PUBLIC_NAMESPACE_LEAD +
|
|
111
|
-
"Public pages are served
|
|
112
|
-
"
|
|
113
|
+
"Public pages are served on the brewpage.app domain itself, for the strongest search reach; " +
|
|
114
|
+
"code that needs its own origin (cookies, storage) gets its own subdomain automatically." +
|
|
113
115
|
PUBLIC_NAMESPACE_TAIL + NAMESPACE_FORMAT;
|
|
114
116
|
const SITE_NAMESPACE_DESCRIPTION = PUBLIC_NAMESPACE_LEAD + "A site always gets its own subdomain." +
|
|
115
117
|
PUBLIC_NAMESPACE_TAIL + NAMESPACE_FORMAT;
|
|
@@ -123,9 +125,9 @@ const DELIVERY_MODE_SCHEMA = z.enum(["path", "subdomain"]).optional().describe("
|
|
|
123
125
|
"Everything else in any namespace (Markdown, code/text, files, JSON, KV, public HTML) defaults to path (Promotion); public HTML may automatically choose subdomain for browser features. " +
|
|
124
126
|
"When creation returns an existing publication, it keeps its actual mode and URL.");
|
|
125
127
|
/** Site upload rules shared by publish_site and republish_site; current values come from get_limits. */
|
|
126
|
-
const SITE_LIMITS_TEXT = "Default limits (current
|
|
127
|
-
"
|
|
128
|
-
"or
|
|
128
|
+
const SITE_LIMITS_TEXT = "Default limits (current: GET /api/limits): request 25 MiB; site 200 files, 5 MiB per file, 20 MiB total; " +
|
|
129
|
+
"path 380 characters. System files (.DS_Store, __MACOSX/ and similar) are skipped and never count; files with an unsupported extension " +
|
|
130
|
+
"or too-long path are skipped and listed in notices. Entry: `entry`, else root index.html, else the shallowest HTML file. " +
|
|
129
131
|
"Errors: 400 = a site limit exceeded (the message names it), invalid path, no HTML file, or a PDF/Office file unreadable " +
|
|
130
132
|
"or password-protected; 413 = request over 25 MiB, too many files and form fields, or a file name/path too long; " +
|
|
131
133
|
"422 = no servable file left; 503 = busy, retry after Retry-After seconds.";
|
|
@@ -216,7 +218,7 @@ export function createServer(options = {}) {
|
|
|
216
218
|
const apiFetch = options.fetch ?? fetch;
|
|
217
219
|
const server = new McpServer({
|
|
218
220
|
name: "brewpage-mcp",
|
|
219
|
-
version: "1.16.
|
|
221
|
+
version: "1.16.6",
|
|
220
222
|
});
|
|
221
223
|
/** Caller argument first, then the configured default; `fromEnv` marks the configured one. */
|
|
222
224
|
function ownerTokenFor(argument) {
|
|
@@ -291,9 +293,10 @@ export function createServer(options = {}) {
|
|
|
291
293
|
}
|
|
292
294
|
server.registerTool("publish_html", {
|
|
293
295
|
...toolMeta("Publish HTML, Markdown, code or JSON page", ADDITIVE),
|
|
294
|
-
description: "Publish HTML, Markdown, code or JSON
|
|
295
|
-
"
|
|
296
|
-
"
|
|
296
|
+
description: "Publish HTML, Markdown, code or JSON to BrewPage (max 5 MiB). " + PUBLIC_HINT +
|
|
297
|
+
"Format omitted -> server detects it. Returns its primary share link and owner token. Optional password, TTL, filename, top toolbar (showTopBar). " +
|
|
298
|
+
"A `public` page without deliveryMode may get its own subdomain if it needs browser features a BrewPage link lacks; " +
|
|
299
|
+
"the result then has deliveryModeReason and a delivery notice. Markdown raw HTML is allowlisted: scripts, styles, event handlers, forms, embeds removed. " +
|
|
297
300
|
MANAGE_URL_TEXT + " " + SECRETS,
|
|
298
301
|
inputSchema: {
|
|
299
302
|
content: z.string().describe("HTML, Markdown, code or JSON to publish"),
|
|
@@ -362,7 +365,7 @@ export function createServer(options = {}) {
|
|
|
362
365
|
});
|
|
363
366
|
server.registerTool("publish_file", {
|
|
364
367
|
...toolMeta("Publish file from URL", ADDITIVE),
|
|
365
|
-
description: "Upload a file
|
|
368
|
+
description: "Upload a file from a URL. " + PUBLIC_HINT + "Max 5 MiB, video 20 MiB; no password or TTL. Returns its primary share link and owner token. " +
|
|
366
369
|
MANAGE_URL_TEXT + " " + SECRETS,
|
|
367
370
|
inputSchema: {
|
|
368
371
|
url: z.string().url().describe("URL of the file to upload"),
|
|
@@ -427,9 +430,9 @@ export function createServer(options = {}) {
|
|
|
427
430
|
if (!auth.token)
|
|
428
431
|
return textResult(NO_OWNER_TOKEN, true);
|
|
429
432
|
const path = apiPath(TYPE_SEGMENTS[type], namespace, id, "hosting");
|
|
430
|
-
const { ok, status, data } = await apiRequest("PATCH", path, { deliveryMode, expectedVersion }, { "X-Owner-Token": auth.token });
|
|
433
|
+
const { ok, status, data, headers: answerHeaders } = await apiRequest("PATCH", path, { deliveryMode, expectedVersion }, { "X-Owner-Token": auth.token });
|
|
431
434
|
if (!ok)
|
|
432
|
-
return ownerFailure("update hosting", status, data, auth.fromEnv);
|
|
435
|
+
return ownerFailure("update hosting", status, data, auth.fromEnv, answerHeaders);
|
|
433
436
|
return {
|
|
434
437
|
content: [{ type: "text", text: formatUpdateResponse(data) }],
|
|
435
438
|
};
|
|
@@ -450,9 +453,9 @@ export function createServer(options = {}) {
|
|
|
450
453
|
if (!auth.token)
|
|
451
454
|
return textResult(NO_OWNER_TOKEN, true);
|
|
452
455
|
const path = apiPath(TYPE_SEGMENTS[type], namespace, id);
|
|
453
|
-
const { ok, status, data } = await apiRequest("DELETE", path, undefined, { "X-Owner-Token": auth.token });
|
|
456
|
+
const { ok, status, data, headers: answerHeaders } = await apiRequest("DELETE", path, undefined, { "X-Owner-Token": auth.token });
|
|
454
457
|
if (!ok)
|
|
455
|
-
return ownerFailure("delete", status, data, auth.fromEnv);
|
|
458
|
+
return ownerFailure("delete", status, data, auth.fromEnv, answerHeaders);
|
|
456
459
|
return {
|
|
457
460
|
content: [
|
|
458
461
|
{
|
|
@@ -545,8 +548,8 @@ export function createServer(options = {}) {
|
|
|
545
548
|
});
|
|
546
549
|
server.registerTool("publish_site", {
|
|
547
550
|
...toolMeta("Publish site", ADDITIVE),
|
|
548
|
-
description: "Publish an HTML site to BrewPage. Single-page: `entryContent`. Multi-page: `files` (
|
|
549
|
-
"Static
|
|
551
|
+
description: "Publish an HTML site to BrewPage. " + PUBLIC_HINT + "Single-page: `entryContent`. Multi-page: `files` (`{path, content}` array). Optional `entry` overrides `index.html`. Returns its primary share link and owner token. " +
|
|
552
|
+
"Static only: HTML, CSS, JS (incl. built React/Vue bundles) run in the browser; server code (PHP etc.) never runs. " + SITE_LIMITS_TEXT +
|
|
550
553
|
" " + MANAGE_URL_TEXT + " " + SECRETS,
|
|
551
554
|
inputSchema: {
|
|
552
555
|
deliveryMode: DELIVERY_MODE_SCHEMA,
|
|
@@ -677,7 +680,7 @@ export function createServer(options = {}) {
|
|
|
677
680
|
tags: z
|
|
678
681
|
.array(z.string())
|
|
679
682
|
.optional()
|
|
680
|
-
.describe("Optional tags
|
|
683
|
+
.describe("Optional tags; replace the site's stored tags. Omit to keep them."),
|
|
681
684
|
},
|
|
682
685
|
}, async ({ namespace, id, ownerToken, entryContent, files, entry, ttlDays, tags }) => {
|
|
683
686
|
const hasEntry = typeof entryContent === "string";
|
|
@@ -711,7 +714,7 @@ export function createServer(options = {}) {
|
|
|
711
714
|
return textResult(NO_OWNER_TOKEN, true);
|
|
712
715
|
const headers = { "X-Owner-Token": auth.token };
|
|
713
716
|
const url = baseUrl + withQuery(apiPath("sites", namespace, id), [["entry", entry || undefined],
|
|
714
|
-
["ttl", ttlDays || undefined], ["tags", tags
|
|
717
|
+
["ttl", ttlDays || undefined], ["tags", tags?.join(",")]]);
|
|
715
718
|
const res = await bpFetch(url, { method: "PUT", headers, body: formData });
|
|
716
719
|
const data = await res.json().catch(() => null);
|
|
717
720
|
if (!res.ok)
|
|
@@ -758,20 +761,24 @@ export function createServer(options = {}) {
|
|
|
758
761
|
.string()
|
|
759
762
|
.optional()
|
|
760
763
|
.describe("Content format. Accepts (case-insensitive on html/markdown): 'html', 'markdown'/'md', or a code language — yaml, json, xml, csv, tsv, log, toml, ini, sql, sh, bat, env, javascript, typescript, tsx, jsx, css, properties, docker, txt. Omit to preserve the stored format."),
|
|
764
|
+
tags: z
|
|
765
|
+
.array(z.string())
|
|
766
|
+
.optional()
|
|
767
|
+
.describe("Optional tags; replace the page's stored tags ([] clears). Omit to keep them."),
|
|
761
768
|
},
|
|
762
|
-
}, async ({ namespace, id, content, ownerToken, format }) => {
|
|
769
|
+
}, async ({ namespace, id, content, ownerToken, format, tags }) => {
|
|
763
770
|
const body = { content };
|
|
764
771
|
if (format)
|
|
765
772
|
body.format = format;
|
|
766
773
|
const auth = ownerTokenFor(ownerToken);
|
|
767
774
|
if (!auth.token)
|
|
768
775
|
return textResult(NO_OWNER_TOKEN, true);
|
|
769
|
-
const path = apiPath("html", namespace, id);
|
|
770
|
-
const { ok, status, data } = await apiRequest("PUT", path, body, {
|
|
776
|
+
const path = withQuery(apiPath("html", namespace, id), [["tags", tags?.join(",")]]);
|
|
777
|
+
const { ok, status, data, headers: answerHeaders } = await apiRequest("PUT", path, body, {
|
|
771
778
|
"X-Owner-Token": auth.token,
|
|
772
779
|
});
|
|
773
780
|
if (!ok)
|
|
774
|
-
return ownerFailure("update HTML", status, data, auth.fromEnv);
|
|
781
|
+
return ownerFailure("update HTML", status, data, auth.fromEnv, answerHeaders);
|
|
775
782
|
return {
|
|
776
783
|
content: [
|
|
777
784
|
{
|
|
@@ -828,7 +835,7 @@ export function createServer(options = {}) {
|
|
|
828
835
|
content: [
|
|
829
836
|
{
|
|
830
837
|
type: "text",
|
|
831
|
-
text: `Failed to publish JSON (${res.status}): ${JSON.stringify(data)}`,
|
|
838
|
+
text: `Failed to publish JSON (${res.status}): ${JSON.stringify(data)}${retryAfterText(res.status, res.headers)}`,
|
|
832
839
|
},
|
|
833
840
|
],
|
|
834
841
|
isError: true,
|
|
@@ -907,7 +914,7 @@ export function createServer(options = {}) {
|
|
|
907
914
|
});
|
|
908
915
|
const data = await res.json().catch(() => null);
|
|
909
916
|
if (!res.ok)
|
|
910
|
-
return ownerFailure("update JSON", res.status, data, auth.fromEnv);
|
|
917
|
+
return ownerFailure("update JSON", res.status, data, auth.fromEnv, res.headers);
|
|
911
918
|
return {
|
|
912
919
|
content: [
|
|
913
920
|
{
|
|
@@ -952,13 +959,13 @@ export function createServer(options = {}) {
|
|
|
952
959
|
headers["X-Owner-Token"] = owner;
|
|
953
960
|
if (deliveryMode)
|
|
954
961
|
headers["X-Delivery-Mode"] = deliveryMode;
|
|
955
|
-
const { ok, status, data } = await apiRequest("POST", path, body, headers);
|
|
962
|
+
const { ok, status, data, headers: answerHeaders } = await apiRequest("POST", path, body, headers);
|
|
956
963
|
if (!ok) {
|
|
957
964
|
return {
|
|
958
965
|
content: [
|
|
959
966
|
{
|
|
960
967
|
type: "text",
|
|
961
|
-
text: `Failed to publish KV (${status}): ${JSON.stringify(data)}`,
|
|
968
|
+
text: `Failed to publish KV (${status}): ${JSON.stringify(data)}${retryAfterText(status, answerHeaders)}`,
|
|
962
969
|
},
|
|
963
970
|
],
|
|
964
971
|
isError: true,
|
|
@@ -989,11 +996,11 @@ export function createServer(options = {}) {
|
|
|
989
996
|
if (!auth.token)
|
|
990
997
|
return textResult(NO_OWNER_TOKEN, true);
|
|
991
998
|
const path = apiPath("kv", namespace, id, key);
|
|
992
|
-
const { ok, status, data } = await apiRequest("PUT", path, body, {
|
|
999
|
+
const { ok, status, data, headers: answerHeaders } = await apiRequest("PUT", path, body, {
|
|
993
1000
|
"X-Owner-Token": auth.token,
|
|
994
1001
|
});
|
|
995
1002
|
if (!ok)
|
|
996
|
-
return ownerFailure("set KV", status, data, auth.fromEnv);
|
|
1003
|
+
return ownerFailure("set KV", status, data, auth.fromEnv, answerHeaders);
|
|
997
1004
|
return {
|
|
998
1005
|
content: [
|
|
999
1006
|
{
|
|
@@ -1150,9 +1157,9 @@ export function createServer(options = {}) {
|
|
|
1150
1157
|
if (!auth.token)
|
|
1151
1158
|
return textResult(NO_OWNER_TOKEN, true);
|
|
1152
1159
|
const path = apiPath(TYPE_SEGMENTS[type], namespace, id, "visibility");
|
|
1153
|
-
const { ok, status, data } = await apiRequest("POST", path, { listed }, { "X-Owner-Token": auth.token });
|
|
1160
|
+
const { ok, status, data, headers: answerHeaders } = await apiRequest("POST", path, { listed }, { "X-Owner-Token": auth.token });
|
|
1154
1161
|
if (!ok)
|
|
1155
|
-
return ownerFailure("set visibility", status, data, auth.fromEnv);
|
|
1162
|
+
return ownerFailure("set visibility", status, data, auth.fromEnv, answerHeaders);
|
|
1156
1163
|
const result = data;
|
|
1157
1164
|
return textResult([...credentialAlertLines(result), `LISTED: ${result.listed} · link unchanged`, ...noticeLines(result)].join("\n"));
|
|
1158
1165
|
});
|
|
@@ -1167,9 +1174,9 @@ export function createServer(options = {}) {
|
|
|
1167
1174
|
const auth = ownerTokenFor(ownerToken);
|
|
1168
1175
|
if (!auth.token)
|
|
1169
1176
|
return textResult(NO_OWNER_TOKEN, true);
|
|
1170
|
-
const { ok, status, data } = await apiRequest("POST", "/api/owner-token/bind", { token }, { "X-Owner-Token": auth.token });
|
|
1177
|
+
const { ok, status, data, headers: answerHeaders } = await apiRequest("POST", "/api/owner-token/bind", { token }, { "X-Owner-Token": auth.token });
|
|
1171
1178
|
if (!ok)
|
|
1172
|
-
return textResult(`Failed to bind token (${status}): ${JSON.stringify(data)}`, true);
|
|
1179
|
+
return textResult(`Failed to bind token (${status}): ${JSON.stringify(data)}${retryAfterText(status, answerHeaders)}`, true);
|
|
1173
1180
|
const result = data;
|
|
1174
1181
|
return textResult(`BOUND ${maskToken(token)} · ${result.active}/${result.max} active`);
|
|
1175
1182
|
});
|
|
@@ -1186,9 +1193,9 @@ export function createServer(options = {}) {
|
|
|
1186
1193
|
const auth = ownerTokenFor(ownerToken);
|
|
1187
1194
|
if (!auth.token)
|
|
1188
1195
|
return textResult(NO_OWNER_TOKEN, true);
|
|
1189
|
-
const { ok, status, data } = await apiRequest("POST", "/api/owner-token/mint", { label, scope, expiresIn }, { "X-Owner-Token": auth.token });
|
|
1196
|
+
const { ok, status, data, headers: answerHeaders } = await apiRequest("POST", "/api/owner-token/mint", { label, scope, expiresIn }, { "X-Owner-Token": auth.token });
|
|
1190
1197
|
if (!ok)
|
|
1191
|
-
return textResult(`Failed to mint token (${status}): ${JSON.stringify(data)}`, true);
|
|
1198
|
+
return textResult(`Failed to mint token (${status}): ${JSON.stringify(data)}${retryAfterText(status, answerHeaders)}`, true);
|
|
1192
1199
|
const result = data;
|
|
1193
1200
|
return textResult([
|
|
1194
1201
|
`MINTED · ${result.scope} · expires ${result.expiresAt ?? "never"}`,
|
package/package.json
CHANGED