Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
960 changes: 960 additions & 0 deletions coverage/app/config.js.html

Large diffs are not rendered by default.

294 changes: 294 additions & 0 deletions coverage/app/connectors/cloudflare/client.js.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@

<!doctype html>
<html lang="en">

<head>
<title>Code coverage report for app/connectors/cloudflare/client.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>

<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="../../../index.html">All files</a> / <a href="index.html">app/connectors/cloudflare</a> client.js</h1>
<div class='clearfix'>

<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/23</span>
</div>


<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/43</span>
</div>


<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/4</span>
</div>


<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/21</span>
</div>


</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a>
<a name='L70'></a><a href='#L70'>70</a>
<a name='L71'></a><a href='#L71'>71</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">// ---------------------------------------------------------------------------
// connectors/cloudflare/client.js
// Thin wrapper around the Cloudflare REST API (api.cloudflare.com/client/v4),
// scoped to a single account. Mirrors the auth/error pattern used by the
// GitHub connector's client.js.
// ---------------------------------------------------------------------------
&nbsp;
import { CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API } from "../../config.js";
&nbsp;
function <span class="fstat-no" title="function not covered" >assertConfigured(</span>) {
<span class="cstat-no" title="statement not covered" > if (!CLOUDFLARE_API_TOKEN) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error(</span>
"CLOUDFLARE_API_TOKEN is not set. Add it as an environment variable on the madmcp server."
);
}
<span class="cstat-no" title="statement not covered" > if (!CLOUDFLARE_ACCOUNT_ID) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error(</span>
"CLOUDFLARE_ACCOUNT_ID is not set. Add it as an environment variable on the madmcp server."
);
}
}
&nbsp;
// Generic request against any Cloudflare API path (not account-scoped).
export async function <span class="fstat-no" title="function not covered" >cfRequest(</span>path, { method = <span class="branch-0 cbranch-no" title="branch not covered" >"GET",</span> body, accept } = <span class="branch-0 cbranch-no" title="branch not covered" >{})</span> {
<span class="cstat-no" title="statement not covered" > assertConfigured();</span>
const res = <span class="cstat-no" title="statement not covered" >await fetch(`${CLOUDFLARE_API}${path}`, {</span>
method,
headers: {
Authorization: `Bearer ${CLOUDFLARE_API_TOKEN}`,
Accept: accept || "application/json",
"Content-Type": "application/json",
"User-Agent": "madmcp-server",
},
body: body !== undefined ? JSON.stringify(body) : undefined,
});
&nbsp;
const contentType = <span class="cstat-no" title="statement not covered" >res.headers.get("content-type") || "";</span>
const text = <span class="cstat-no" title="statement not covered" >await res.text();</span>
&nbsp;
// Non-JSON responses (e.g. raw worker script source) are returned as-is.
<span class="cstat-no" title="statement not covered" > if (!contentType.includes("application/json")) {</span>
<span class="cstat-no" title="statement not covered" > if (!res.ok) {</span>
<span class="cstat-no" title="statement not covered" > throw new Error(`Cloudflare API error (${res.status}): ${text || res.statusText}`);</span>
}
<span class="cstat-no" title="statement not covered" > return text;</span>
}
&nbsp;
let data;
<span class="cstat-no" title="statement not covered" > try { <span class="cstat-no" title="statement not covered" >data = text ? JSON.parse(text) : null; </span>} catch { <span class="cstat-no" title="statement not covered" >data = text; </span>}</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > if (!res.ok || (data &amp;&amp; data.success === false)) {</span>
const errorList = <span class="cstat-no" title="statement not covered" >data &amp;&amp; Array.isArray(data.errors) ? data.errors : [];</span>
const errors = <span class="cstat-no" title="statement not covered" >errorList.length</span>
? errorList.map(<span class="fstat-no" title="function not covered" >e </span>=&gt; <span class="cstat-no" title="statement not covered" >`${e.message}${e.code ? ` (code ${e.code})` : ""}${e.error_chain ? ` [chain: ${JSON.stringify(e.error_chain)}]` : ""}`)</span>.join("; ")
: null;
// When Cloudflare returns an empty errors array (common on 400s from the
// observability query/values endpoints), fall back to the raw response
// body so the actual validation failure isn't swallowed.
const fallback = <span class="cstat-no" title="statement not covered" >errors || (data ? JSON.stringify(data) : null) || text || res.statusText;</span>
<span class="cstat-no" title="statement not covered" > throw new Error(`Cloudflare API error (${res.status}): ${fallback}`);</span>
}
&nbsp;
// Cloudflare wraps successful payloads as { success, result, result_info }.
<span class="cstat-no" title="statement not covered" > return data &amp;&amp; Object.prototype.hasOwnProperty.call(data, "result") ? data.result : data;</span>
}
&nbsp;
// Convenience helper for the common case: paths under /accounts/{account_id}/...
export function <span class="fstat-no" title="function not covered" >cfAccountRequest(</span>subpath, opts) {
<span class="cstat-no" title="statement not covered" > return cfRequest(`/accounts/${CLOUDFLARE_ACCOUNT_ID}${subpath}`, opts);</span>
}
&nbsp;</pre></td></tr></table></pre>

<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2026-08-07T17:58:05.095Z
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="../../../sorter.js"></script>
<script src="../../../block-navigation.js"></script>
</body>
</html>
Loading