chore: initialize project repository with core extension files

- Add .gitignore to exclude node_modules, dist, logs, and system files
- Add comprehensive project documentation including README, deployment guide, and development setup
- Add .kiro project specifications for amazon-product-bar-extension, appwrite-cloud-storage, appwrite-userid-repair, blacklist-feature, and enhanced-item-management
- Add .kiro steering documents for product, structure, styling, and tech guidelines
- Add VSCode settings configuration for consistent development environment
- Add manifest.json and babel/vite configuration for extension build setup
- Add complete source code implementation including AppWrite integration, storage managers, UI components, and services
- Add comprehensive test suite with Jest configuration and 30+ test files covering all major modules
- Add test HTML files for integration testing and validation
- Add coverage reports and build validation scripts
- Add AppWrite setup and repair documentation for database schema management
- Add migration guides and responsive accessibility implementation documentation
- Establish foundation for Amazon product bar extension with full feature set including blacklist management, enhanced item workflows, and real-time synchronization
This commit is contained in:
2026-01-12 17:46:42 +01:00
commit 216a972fef
180 changed files with 88019 additions and 0 deletions

67
coverage/clover.xml Normal file
View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1768165652704" clover="3.2.0">
<project timestamp="1768165652704" name="All files">
<metrics statements="43" coveredstatements="20" conditionals="4" coveredconditionals="2" methods="33" coveredmethods="10" elements="80" coveredelements="32" complexity="0" loc="43" ncloc="43" packages="1" files="6" classes="6"/>
<file name="AppWriteRepairController.js" path="A:\developer\GitHub-desktop\ebaysnipeextension\src\AppWriteRepairController.js">
<metrics statements="10" coveredstatements="5" conditionals="1" coveredconditionals="0" methods="6" coveredmethods="1"/>
<line num="30" count="2" type="stmt"/>
<line num="31" count="2" type="stmt"/>
<line num="32" count="2" type="stmt"/>
<line num="33" count="2" type="stmt"/>
<line num="34" count="2" type="stmt"/>
<line num="46" count="0" type="stmt"/>
<line num="56" count="0" type="stmt"/>
<line num="66" count="0" type="stmt"/>
<line num="75" count="0" type="stmt"/>
<line num="85" count="0" type="stmt"/>
</file>
<file name="AppWriteRepairInterface.js" path="A:\developer\GitHub-desktop\ebaysnipeextension\src\AppWriteRepairInterface.js">
<metrics statements="9" coveredstatements="4" conditionals="1" coveredconditionals="0" methods="6" coveredmethods="1"/>
<line num="15" count="1" type="stmt"/>
<line num="16" count="1" type="stmt"/>
<line num="17" count="1" type="stmt"/>
<line num="18" count="1" type="stmt"/>
<line num="28" count="0" type="stmt"/>
<line num="39" count="0" type="stmt"/>
<line num="48" count="0" type="stmt"/>
<line num="59" count="0" type="stmt"/>
<line num="69" count="0" type="stmt"/>
</file>
<file name="AppWriteRepairTypes.js" path="A:\developer\GitHub-desktop\ebaysnipeextension\src\AppWriteRepairTypes.js">
<metrics statements="6" coveredstatements="6" conditionals="2" coveredconditionals="2" methods="5" coveredmethods="5"/>
<line num="159" count="1" type="stmt"/>
<line num="161" count="405" type="cond" truecount="2" falsecount="0"/>
<line num="162" count="105" type="stmt"/>
<line num="163" count="104" type="stmt"/>
<line num="164" count="104" type="stmt"/>
<line num="165" count="4" type="stmt"/>
</file>
<file name="AppWriteSchemaAnalyzer.js" path="A:\developer\GitHub-desktop\ebaysnipeextension\src\AppWriteSchemaAnalyzer.js">
<metrics statements="5" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="5" coveredmethods="1"/>
<line num="42" count="3" type="stmt"/>
<line num="52" count="0" type="stmt"/>
<line num="61" count="0" type="stmt"/>
<line num="71" count="0" type="stmt"/>
<line num="81" count="0" type="stmt"/>
</file>
<file name="AppWriteSchemaRepairer.js" path="A:\developer\GitHub-desktop\ebaysnipeextension\src\AppWriteSchemaRepairer.js">
<metrics statements="8" coveredstatements="3" conditionals="0" coveredconditionals="0" methods="6" coveredmethods="1"/>
<line num="25" count="3" type="stmt"/>
<line num="26" count="3" type="stmt"/>
<line num="27" count="3" type="stmt"/>
<line num="38" count="0" type="stmt"/>
<line num="48" count="0" type="stmt"/>
<line num="58" count="0" type="stmt"/>
<line num="68" count="0" type="stmt"/>
<line num="79" count="0" type="stmt"/>
</file>
<file name="AppWriteSchemaValidator.js" path="A:\developer\GitHub-desktop\ebaysnipeextension\src\AppWriteSchemaValidator.js">
<metrics statements="5" coveredstatements="1" conditionals="0" coveredconditionals="0" methods="5" coveredmethods="1"/>
<line num="25" count="3" type="stmt"/>
<line num="35" count="0" type="stmt"/>
<line num="45" count="0" type="stmt"/>
<line num="55" count="0" type="stmt"/>
<line num="65" count="0" type="stmt"/>
</file>
</project>
</coverage>

View File

@@ -0,0 +1,7 @@
{"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteRepairController.js": {"path":"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteRepairController.js","statementMap":{"0":{"start":{"line":30,"column":8},"end":{"line":30,"column":47}},"1":{"start":{"line":31,"column":8},"end":{"line":31,"column":39}},"2":{"start":{"line":32,"column":8},"end":{"line":32,"column":39}},"3":{"start":{"line":33,"column":8},"end":{"line":33,"column":41}},"4":{"start":{"line":34,"column":8},"end":{"line":34,"column":27}},"5":{"start":{"line":46,"column":8},"end":{"line":46,"column":54}},"6":{"start":{"line":56,"column":8},"end":{"line":56,"column":54}},"7":{"start":{"line":66,"column":8},"end":{"line":66,"column":54}},"8":{"start":{"line":75,"column":8},"end":{"line":75,"column":54}},"9":{"start":{"line":85,"column":8},"end":{"line":85,"column":54}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":29,"column":4},"end":{"line":29,"column":5}},"loc":{"start":{"line":29,"column":82},"end":{"line":35,"column":5}},"line":29},"1":{"name":"(anonymous_1)","decl":{"start":{"line":44,"column":4},"end":{"line":44,"column":5}},"loc":{"start":{"line":44,"column":43},"end":{"line":47,"column":5}},"line":44},"2":{"name":"(anonymous_2)","decl":{"start":{"line":54,"column":4},"end":{"line":54,"column":5}},"loc":{"start":{"line":54,"column":39},"end":{"line":57,"column":5}},"line":54},"3":{"name":"(anonymous_3)","decl":{"start":{"line":64,"column":4},"end":{"line":64,"column":5}},"loc":{"start":{"line":64,"column":37},"end":{"line":67,"column":5}},"line":64},"4":{"name":"(anonymous_4)","decl":{"start":{"line":73,"column":4},"end":{"line":73,"column":5}},"loc":{"start":{"line":73,"column":27},"end":{"line":76,"column":5}},"line":73},"5":{"name":"(anonymous_5)","decl":{"start":{"line":83,"column":4},"end":{"line":83,"column":5}},"loc":{"start":{"line":83,"column":37},"end":{"line":86,"column":5}},"line":83}},"branchMap":{"0":{"loc":{"start":{"line":44,"column":29},"end":{"line":44,"column":41}},"type":"default-arg","locations":[{"start":{"line":44,"column":39},"end":{"line":44,"column":41}}],"line":44}},"s":{"0":2,"1":2,"2":2,"3":2,"4":2,"5":0,"6":0,"7":0,"8":0,"9":0},"f":{"0":2,"1":0,"2":0,"3":0,"4":0,"5":0},"b":{"0":[0]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"115e9b67b8ec6d614dc8471080fa9245d7bd5407"}
,"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteRepairInterface.js": {"path":"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteRepairInterface.js","statementMap":{"0":{"start":{"line":15,"column":8},"end":{"line":15,"column":43}},"1":{"start":{"line":16,"column":8},"end":{"line":16,"column":30}},"2":{"start":{"line":17,"column":8},"end":{"line":17,"column":38}},"3":{"start":{"line":18,"column":8},"end":{"line":18,"column":37}},"4":{"start":{"line":28,"column":8},"end":{"line":28,"column":54}},"5":{"start":{"line":39,"column":8},"end":{"line":39,"column":54}},"6":{"start":{"line":48,"column":8},"end":{"line":48,"column":54}},"7":{"start":{"line":59,"column":8},"end":{"line":59,"column":54}},"8":{"start":{"line":69,"column":8},"end":{"line":69,"column":54}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":14,"column":4},"end":{"line":14,"column":5}},"loc":{"start":{"line":14,"column":34},"end":{"line":19,"column":5}},"line":14},"1":{"name":"(anonymous_1)","decl":{"start":{"line":26,"column":4},"end":{"line":26,"column":5}},"loc":{"start":{"line":26,"column":26},"end":{"line":29,"column":5}},"line":26},"2":{"name":"(anonymous_2)","decl":{"start":{"line":37,"column":4},"end":{"line":37,"column":5}},"loc":{"start":{"line":37,"column":47},"end":{"line":40,"column":5}},"line":37},"3":{"name":"(anonymous_3)","decl":{"start":{"line":46,"column":4},"end":{"line":46,"column":5}},"loc":{"start":{"line":46,"column":27},"end":{"line":49,"column":5}},"line":46},"4":{"name":"(anonymous_4)","decl":{"start":{"line":57,"column":4},"end":{"line":57,"column":5}},"loc":{"start":{"line":57,"column":40},"end":{"line":60,"column":5}},"line":57},"5":{"name":"(anonymous_5)","decl":{"start":{"line":67,"column":4},"end":{"line":67,"column":5}},"loc":{"start":{"line":67,"column":37},"end":{"line":70,"column":5}},"line":67}},"branchMap":{"0":{"loc":{"start":{"line":37,"column":33},"end":{"line":37,"column":45}},"type":"default-arg","locations":[{"start":{"line":37,"column":43},"end":{"line":37,"column":45}}],"line":37}},"s":{"0":1,"1":1,"2":1,"3":1,"4":0,"5":0,"6":0,"7":0,"8":0},"f":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0},"b":{"0":[0]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"db9d4d52f4af865b81c2e2b3115f76e1a86644a1"}
,"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteRepairTypes.js": {"path":"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteRepairTypes.js","statementMap":{"0":{"start":{"line":159,"column":27},"end":{"line":181,"column":1}},"1":{"start":{"line":161,"column":33},"end":{"line":161,"column":72}},"2":{"start":{"line":162,"column":35},"end":{"line":162,"column":85}},"3":{"start":{"line":163,"column":36},"end":{"line":163,"column":99}},"4":{"start":{"line":164,"column":31},"end":{"line":164,"column":75}},"5":{"start":{"line":165,"column":38},"end":{"line":165,"column":87}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":161,"column":25},"end":{"line":161,"column":26}},"loc":{"start":{"line":161,"column":33},"end":{"line":161,"column":72}},"line":161},"1":{"name":"(anonymous_1)","decl":{"start":{"line":162,"column":21},"end":{"line":162,"column":22}},"loc":{"start":{"line":162,"column":35},"end":{"line":162,"column":85}},"line":162},"2":{"name":"(anonymous_2)","decl":{"start":{"line":163,"column":26},"end":{"line":163,"column":27}},"loc":{"start":{"line":163,"column":36},"end":{"line":163,"column":99}},"line":163},"3":{"name":"(anonymous_3)","decl":{"start":{"line":164,"column":19},"end":{"line":164,"column":20}},"loc":{"start":{"line":164,"column":31},"end":{"line":164,"column":75}},"line":164},"4":{"name":"(anonymous_4)","decl":{"start":{"line":165,"column":26},"end":{"line":165,"column":27}},"loc":{"start":{"line":165,"column":38},"end":{"line":165,"column":87}},"line":165}},"branchMap":{"0":{"loc":{"start":{"line":161,"column":33},"end":{"line":161,"column":72}},"type":"binary-expr","locations":[{"start":{"line":161,"column":33},"end":{"line":161,"column":55}},{"start":{"line":161,"column":59},"end":{"line":161,"column":72}}],"line":161}},"s":{"0":1,"1":405,"2":105,"3":104,"4":104,"5":4},"f":{"0":405,"1":105,"2":104,"3":104,"4":4},"b":{"0":[405,403]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"d77f88a885b52e30964ab0820d9d31fc99ed8b11"}
,"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteSchemaAnalyzer.js": {"path":"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteSchemaAnalyzer.js","statementMap":{"0":{"start":{"line":42,"column":8},"end":{"line":42,"column":47}},"1":{"start":{"line":52,"column":8},"end":{"line":52,"column":54}},"2":{"start":{"line":61,"column":8},"end":{"line":61,"column":54}},"3":{"start":{"line":71,"column":8},"end":{"line":71,"column":54}},"4":{"start":{"line":81,"column":8},"end":{"line":81,"column":54}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":41,"column":4},"end":{"line":41,"column":5}},"loc":{"start":{"line":41,"column":33},"end":{"line":43,"column":5}},"line":41},"1":{"name":"(anonymous_1)","decl":{"start":{"line":50,"column":4},"end":{"line":50,"column":5}},"loc":{"start":{"line":50,"column":42},"end":{"line":53,"column":5}},"line":50},"2":{"name":"(anonymous_2)","decl":{"start":{"line":59,"column":4},"end":{"line":59,"column":5}},"loc":{"start":{"line":59,"column":34},"end":{"line":62,"column":5}},"line":59},"3":{"name":"(anonymous_3)","decl":{"start":{"line":69,"column":4},"end":{"line":69,"column":5}},"loc":{"start":{"line":69,"column":49},"end":{"line":72,"column":5}},"line":69},"4":{"name":"(anonymous_4)","decl":{"start":{"line":79,"column":4},"end":{"line":79,"column":5}},"loc":{"start":{"line":79,"column":41},"end":{"line":82,"column":5}},"line":79}},"branchMap":{},"s":{"0":3,"1":0,"2":0,"3":0,"4":0},"f":{"0":3,"1":0,"2":0,"3":0,"4":0},"b":{},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"607fe155d078af23c5c41b8822b2c37ecb5dbed8"}
,"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteSchemaRepairer.js": {"path":"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteSchemaRepairer.js","statementMap":{"0":{"start":{"line":25,"column":8},"end":{"line":25,"column":47}},"1":{"start":{"line":26,"column":8},"end":{"line":26,"column":28}},"2":{"start":{"line":27,"column":8},"end":{"line":27,"column":30}},"3":{"start":{"line":38,"column":8},"end":{"line":38,"column":54}},"4":{"start":{"line":48,"column":8},"end":{"line":48,"column":54}},"5":{"start":{"line":58,"column":8},"end":{"line":58,"column":54}},"6":{"start":{"line":68,"column":8},"end":{"line":68,"column":54}},"7":{"start":{"line":79,"column":8},"end":{"line":79,"column":54}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":24,"column":4},"end":{"line":24,"column":5}},"loc":{"start":{"line":24,"column":33},"end":{"line":28,"column":5}},"line":24},"1":{"name":"(anonymous_1)","decl":{"start":{"line":36,"column":4},"end":{"line":36,"column":5}},"loc":{"start":{"line":36,"column":49},"end":{"line":39,"column":5}},"line":36},"2":{"name":"(anonymous_2)","decl":{"start":{"line":46,"column":4},"end":{"line":46,"column":5}},"loc":{"start":{"line":46,"column":43},"end":{"line":49,"column":5}},"line":46},"3":{"name":"(anonymous_3)","decl":{"start":{"line":56,"column":4},"end":{"line":56,"column":5}},"loc":{"start":{"line":56,"column":49},"end":{"line":59,"column":5}},"line":56},"4":{"name":"(anonymous_4)","decl":{"start":{"line":66,"column":4},"end":{"line":66,"column":5}},"loc":{"start":{"line":66,"column":37},"end":{"line":69,"column":5}},"line":66},"5":{"name":"(anonymous_5)","decl":{"start":{"line":77,"column":4},"end":{"line":77,"column":5}},"loc":{"start":{"line":77,"column":53},"end":{"line":80,"column":5}},"line":77}},"branchMap":{},"s":{"0":3,"1":3,"2":3,"3":0,"4":0,"5":0,"6":0,"7":0},"f":{"0":3,"1":0,"2":0,"3":0,"4":0,"5":0},"b":{},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"98aba059d78d703144517b17a7374a2603e9e77b"}
,"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteSchemaValidator.js": {"path":"A:\\developer\\GitHub-desktop\\ebaysnipeextension\\src\\AppWriteSchemaValidator.js","statementMap":{"0":{"start":{"line":25,"column":8},"end":{"line":25,"column":47}},"1":{"start":{"line":35,"column":8},"end":{"line":35,"column":54}},"2":{"start":{"line":45,"column":8},"end":{"line":45,"column":54}},"3":{"start":{"line":55,"column":8},"end":{"line":55,"column":54}},"4":{"start":{"line":65,"column":8},"end":{"line":65,"column":54}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":24,"column":4},"end":{"line":24,"column":5}},"loc":{"start":{"line":24,"column":33},"end":{"line":26,"column":5}},"line":24},"1":{"name":"(anonymous_1)","decl":{"start":{"line":33,"column":4},"end":{"line":33,"column":5}},"loc":{"start":{"line":33,"column":43},"end":{"line":36,"column":5}},"line":33},"2":{"name":"(anonymous_2)","decl":{"start":{"line":43,"column":4},"end":{"line":43,"column":5}},"loc":{"start":{"line":43,"column":40},"end":{"line":46,"column":5}},"line":43},"3":{"name":"(anonymous_3)","decl":{"start":{"line":53,"column":4},"end":{"line":53,"column":5}},"loc":{"start":{"line":53,"column":40},"end":{"line":56,"column":5}},"line":53},"4":{"name":"(anonymous_4)","decl":{"start":{"line":63,"column":4},"end":{"line":63,"column":5}},"loc":{"start":{"line":63,"column":44},"end":{"line":66,"column":5}},"line":63}},"branchMap":{},"s":{"0":3,"1":0,"2":0,"3":0,"4":0},"f":{"0":3,"1":0,"2":0,"3":0,"4":0},"b":{},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"46c564b456a15d8931c3d745922bb0f95eb798bb"}
}

View File

@@ -0,0 +1,343 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for AppWriteRepairController.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> AppWriteRepairController.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">50% </span>
<span class="quiet">Statements</span>
<span class='fraction'>5/10</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">16.66% </span>
<span class="quiet">Functions</span>
<span class='fraction'>1/6</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">50% </span>
<span class="quiet">Lines</span>
<span class='fraction'>5/10</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 medium'></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>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a>
<a name='L78'></a><a href='#L78'>78</a>
<a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</a>
<a name='L82'></a><a href='#L82'>82</a>
<a name='L83'></a><a href='#L83'>83</a>
<a name='L84'></a><a href='#L84'>84</a>
<a name='L85'></a><a href='#L85'>85</a>
<a name='L86'></a><a href='#L86'>86</a>
<a name='L87'></a><a href='#L87'>87</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-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-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-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</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-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-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-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-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-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-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Repair Controller for AppWrite Schema Repair System
*
* Orchestrates the entire repair process and manages component interactions.
* Provides main entry points for repair operations and comprehensive reporting.
*
* Requirements: 5.5, 6.3, 7.1, 7.2, 7.3, 7.4, 7.5
*/
&nbsp;
/**
* @typedef {Object} ComprehensiveReport
* @property {Date} timestamp - When report was generated
* @property {number} collectionsAnalyzed - Number of collections analyzed
* @property {number} collectionsRepaired - Number of collections repaired
* @property {number} collectionsValidated - Number of collections validated
* @property {'success'|'partial'|'failed'} overallStatus - Overall operation status
* @property {Object} collections - Per-collection results
* @property {Object} summary - Summary statistics
* @property {string[]} recommendations - Overall recommendations
*/
&nbsp;
export class RepairController {
/**
* @param {Object} appWriteManager - AppWrite manager instance
* @param {Object} schemaAnalyzer - Schema analyzer instance
* @param {Object} schemaRepairer - Schema repairer instance
* @param {Object} schemaValidator - Schema validator instance
*/
constructor(appWriteManager, schemaAnalyzer, schemaRepairer, schemaValidator) {
this.appWriteManager = appWriteManager;
this.analyzer = schemaAnalyzer;
this.repairer = schemaRepairer;
this.validator = schemaValidator;
this.auditLog = [];
}
&nbsp;
/**
* Main entry point for repair operations
* @param {Object} options - Repair options
* @param {boolean} options.analysisOnly - Whether to run analysis only
* @param {string[]} options.collections - Specific collections to process
* @returns {Promise&lt;ComprehensiveReport&gt;} Comprehensive repair report
*/
<span class="fstat-no" title="function not covered" > as</span>ync startRepairProcess(options = <span class="branch-0 cbranch-no" title="branch not covered" >{})</span> {
// Implementation will be added in task 7.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Runs analysis only without making changes
* @param {string[]} collections - Collections to analyze
* @returns {Promise&lt;Object&gt;} Analysis report
*/
<span class="fstat-no" title="function not covered" > as</span>ync runAnalysisOnly(collections) {
// Implementation will be added in task 7.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Runs complete repair cycle (analysis, repair, validation)
* @param {string[]} collections - Collections to process
* @returns {Promise&lt;ComprehensiveReport&gt;} Complete repair report
*/
<span class="fstat-no" title="function not covered" > as</span>ync runFullRepair(collections) {
// Implementation will be added in task 7.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Generates comprehensive report of all operations
* @returns {Promise&lt;ComprehensiveReport&gt;} Generated report
*/
<span class="fstat-no" title="function not covered" > as</span>ync generateReport() {
// Implementation will be added in task 7.5
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Logs operation for audit purposes
* @param {string} operation - Operation description
* @param {Object} details - Operation details
*/
<span class="fstat-no" title="function not covered" > lo</span>gOperation(operation, details) {
// Implementation will be added in task 7.5
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
}</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-01-11T21:07:32.669Z
</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>

View File

@@ -0,0 +1,295 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for AppWriteRepairInterface.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> AppWriteRepairInterface.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">44.44% </span>
<span class="quiet">Statements</span>
<span class='fraction'>4/9</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/1</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">16.66% </span>
<span class="quiet">Functions</span>
<span class='fraction'>1/6</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">44.44% </span>
<span class="quiet">Lines</span>
<span class='fraction'>4/9</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-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-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</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-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-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-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-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-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Repair Interface for AppWrite Schema Repair System
*
* Provides user interface for monitoring and controlling the repair process.
* Handles progress display, result presentation, and user interactions.
*
* Requirements: 5.1, 5.2, 5.3, 5.4
*/
&nbsp;
export class RepairInterface {
/**
* @param {Object} repairController - Repair controller instance
*/
constructor(repairController) {
this.controller = repairController;
this.container = null;
this.progressContainer = null;
this.resultsContainer = null;
}
&nbsp;
/**
* Creates and renders the repair interface HTML
* @param {HTMLElement} parentElement - Parent element to render into
* @returns {HTMLElement} Created interface element
*/
<span class="fstat-no" title="function not covered" > re</span>nder(parentElement) {
// Implementation will be added in task 8.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Shows real-time progress updates during repair process
* @param {string} step - Current step description
* @param {number} progress - Progress percentage (0-100)
* @param {Object} details - Additional progress details
*/
<span class="fstat-no" title="function not covered" > sh</span>owProgress(step, progress, details = <span class="branch-0 cbranch-no" title="branch not covered" >{})</span> {
// Implementation will be added in task 8.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Displays final repair results and recommendations
* @param {Object} report - Comprehensive repair report
*/
<span class="fstat-no" title="function not covered" > di</span>splayResults(report) {
// Implementation will be added in task 8.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Handles user input and interactions
* @param {string} action - User action
* @param {Object} data - Action data
* @returns {Promise&lt;any&gt;} Action result
*/
<span class="fstat-no" title="function not covered" > as</span>ync handleUserInput(action, data) {
// Implementation will be added in task 8.5
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Generates operation summary with counts and instructions
* @param {Object} report - Repair report
* @returns {Object} Operation summary
*/
<span class="fstat-no" title="function not covered" > ge</span>nerateOperationSummary(report) {
// Implementation will be added in task 8.3
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
}</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-01-11T21:07:32.669Z
</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>

View File

@@ -0,0 +1,625 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for AppWriteRepairTypes.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> AppWriteRepairTypes.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Statements</span>
<span class='fraction'>6/6</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>2/2</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Functions</span>
<span class='fraction'>5/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Lines</span>
<span class='fraction'>6/6</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 high'></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>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a>
<a name='L78'></a><a href='#L78'>78</a>
<a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</a>
<a name='L82'></a><a href='#L82'>82</a>
<a name='L83'></a><a href='#L83'>83</a>
<a name='L84'></a><a href='#L84'>84</a>
<a name='L85'></a><a href='#L85'>85</a>
<a name='L86'></a><a href='#L86'>86</a>
<a name='L87'></a><a href='#L87'>87</a>
<a name='L88'></a><a href='#L88'>88</a>
<a name='L89'></a><a href='#L89'>89</a>
<a name='L90'></a><a href='#L90'>90</a>
<a name='L91'></a><a href='#L91'>91</a>
<a name='L92'></a><a href='#L92'>92</a>
<a name='L93'></a><a href='#L93'>93</a>
<a name='L94'></a><a href='#L94'>94</a>
<a name='L95'></a><a href='#L95'>95</a>
<a name='L96'></a><a href='#L96'>96</a>
<a name='L97'></a><a href='#L97'>97</a>
<a name='L98'></a><a href='#L98'>98</a>
<a name='L99'></a><a href='#L99'>99</a>
<a name='L100'></a><a href='#L100'>100</a>
<a name='L101'></a><a href='#L101'>101</a>
<a name='L102'></a><a href='#L102'>102</a>
<a name='L103'></a><a href='#L103'>103</a>
<a name='L104'></a><a href='#L104'>104</a>
<a name='L105'></a><a href='#L105'>105</a>
<a name='L106'></a><a href='#L106'>106</a>
<a name='L107'></a><a href='#L107'>107</a>
<a name='L108'></a><a href='#L108'>108</a>
<a name='L109'></a><a href='#L109'>109</a>
<a name='L110'></a><a href='#L110'>110</a>
<a name='L111'></a><a href='#L111'>111</a>
<a name='L112'></a><a href='#L112'>112</a>
<a name='L113'></a><a href='#L113'>113</a>
<a name='L114'></a><a href='#L114'>114</a>
<a name='L115'></a><a href='#L115'>115</a>
<a name='L116'></a><a href='#L116'>116</a>
<a name='L117'></a><a href='#L117'>117</a>
<a name='L118'></a><a href='#L118'>118</a>
<a name='L119'></a><a href='#L119'>119</a>
<a name='L120'></a><a href='#L120'>120</a>
<a name='L121'></a><a href='#L121'>121</a>
<a name='L122'></a><a href='#L122'>122</a>
<a name='L123'></a><a href='#L123'>123</a>
<a name='L124'></a><a href='#L124'>124</a>
<a name='L125'></a><a href='#L125'>125</a>
<a name='L126'></a><a href='#L126'>126</a>
<a name='L127'></a><a href='#L127'>127</a>
<a name='L128'></a><a href='#L128'>128</a>
<a name='L129'></a><a href='#L129'>129</a>
<a name='L130'></a><a href='#L130'>130</a>
<a name='L131'></a><a href='#L131'>131</a>
<a name='L132'></a><a href='#L132'>132</a>
<a name='L133'></a><a href='#L133'>133</a>
<a name='L134'></a><a href='#L134'>134</a>
<a name='L135'></a><a href='#L135'>135</a>
<a name='L136'></a><a href='#L136'>136</a>
<a name='L137'></a><a href='#L137'>137</a>
<a name='L138'></a><a href='#L138'>138</a>
<a name='L139'></a><a href='#L139'>139</a>
<a name='L140'></a><a href='#L140'>140</a>
<a name='L141'></a><a href='#L141'>141</a>
<a name='L142'></a><a href='#L142'>142</a>
<a name='L143'></a><a href='#L143'>143</a>
<a name='L144'></a><a href='#L144'>144</a>
<a name='L145'></a><a href='#L145'>145</a>
<a name='L146'></a><a href='#L146'>146</a>
<a name='L147'></a><a href='#L147'>147</a>
<a name='L148'></a><a href='#L148'>148</a>
<a name='L149'></a><a href='#L149'>149</a>
<a name='L150'></a><a href='#L150'>150</a>
<a name='L151'></a><a href='#L151'>151</a>
<a name='L152'></a><a href='#L152'>152</a>
<a name='L153'></a><a href='#L153'>153</a>
<a name='L154'></a><a href='#L154'>154</a>
<a name='L155'></a><a href='#L155'>155</a>
<a name='L156'></a><a href='#L156'>156</a>
<a name='L157'></a><a href='#L157'>157</a>
<a name='L158'></a><a href='#L158'>158</a>
<a name='L159'></a><a href='#L159'>159</a>
<a name='L160'></a><a href='#L160'>160</a>
<a name='L161'></a><a href='#L161'>161</a>
<a name='L162'></a><a href='#L162'>162</a>
<a name='L163'></a><a href='#L163'>163</a>
<a name='L164'></a><a href='#L164'>164</a>
<a name='L165'></a><a href='#L165'>165</a>
<a name='L166'></a><a href='#L166'>166</a>
<a name='L167'></a><a href='#L167'>167</a>
<a name='L168'></a><a href='#L168'>168</a>
<a name='L169'></a><a href='#L169'>169</a>
<a name='L170'></a><a href='#L170'>170</a>
<a name='L171'></a><a href='#L171'>171</a>
<a name='L172'></a><a href='#L172'>172</a>
<a name='L173'></a><a href='#L173'>173</a>
<a name='L174'></a><a href='#L174'>174</a>
<a name='L175'></a><a href='#L175'>175</a>
<a name='L176'></a><a href='#L176'>176</a>
<a name='L177'></a><a href='#L177'>177</a>
<a name='L178'></a><a href='#L178'>178</a>
<a name='L179'></a><a href='#L179'>179</a>
<a name='L180'></a><a href='#L180'>180</a>
<a name='L181'></a><a href='#L181'>181</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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">405x</span>
<span class="cline-any cline-yes">105x</span>
<span class="cline-any cline-yes">104x</span>
<span class="cline-any cline-yes">104x</span>
<span class="cline-any cline-yes">4x</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-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></td><td class="text"><pre class="prettyprint lang-js">/**
* TypeScript-style interfaces and type definitions for AppWrite Repair System
*
* This file defines all data models, interfaces, and type structures used
* throughout the AppWrite userId attribute repair system.
*
* Requirements: 1.1, 2.1, 4.1
*/
&nbsp;
/**
* Properties of a userId attribute in AppWrite
* @typedef {Object} UserIdAttributeProperties
* @property {string} type - Attribute type (should be 'string')
* @property {number} size - Maximum character length (should be 255)
* @property {boolean} required - Whether the attribute is required
* @property {boolean} array - Whether the attribute is an array
* @property {string} [key] - Attribute key/name
* @property {string} [status] - Attribute status
*/
&nbsp;
/**
* Collection permissions configuration
* @typedef {Object} CollectionPermissions
* @property {string[]} create - Create permissions array
* @property {string[]} read - Read permissions array
* @property {string[]} update - Update permissions array
* @property {string[]} delete - Delete permissions array
*/
&nbsp;
/**
* Result of analyzing a single collection
* @typedef {Object} CollectionAnalysisResult
* @property {string} collectionId - Collection identifier
* @property {boolean} exists - Whether the collection exists
* @property {boolean} hasUserId - Whether userId attribute exists
* @property {UserIdAttributeProperties|null} userIdProperties - Properties of userId attribute
* @property {CollectionPermissions} permissions - Current collection permissions
* @property {string[]} issues - List of identified issues
* @property {'critical'|'warning'|'info'} severity - Issue severity level
* @property {Date} analyzedAt - When analysis was performed
*/
&nbsp;
/**
* Result of a repair operation
* @typedef {Object} RepairOperationResult
* @property {string} collectionId - Collection identifier
* @property {'add_attribute'|'set_permissions'|'validate'} operation - Type of operation
* @property {boolean} success - Whether operation succeeded
* @property {string} [error] - Error message if operation failed
* @property {string} details - Operation details
* @property {Date} timestamp - When operation was performed
* @property {number} [retryCount] - Number of retries attempted
*/
&nbsp;
/**
* Result of validating a collection
* @typedef {Object} ValidationResult
* @property {string} collectionId - Collection identifier
* @property {boolean} userIdQueryTest - Whether userId query test passed
* @property {boolean} permissionTest - Whether permission test passed
* @property {'pass'|'fail'|'warning'} overallStatus - Overall validation status
* @property {string[]} issues - List of validation issues
* @property {string[]} recommendations - Recommended actions
* @property {Date} validatedAt - When validation was performed
*/
&nbsp;
/**
* Comprehensive report of all repair operations
* @typedef {Object} ComprehensiveReport
* @property {Date} timestamp - When report was generated
* @property {number} collectionsAnalyzed - Number of collections analyzed
* @property {number} collectionsRepaired - Number of collections repaired
* @property {number} collectionsValidated - Number of collections validated
* @property {'success'|'partial'|'failed'} overallStatus - Overall operation status
* @property {Object.&lt;string, CollectionReport&gt;} collections - Per-collection results
* @property {ReportSummary} summary - Summary statistics
* @property {string[]} recommendations - Overall recommendations
* @property {AuditLogEntry[]} auditLog - Complete audit trail
*/
&nbsp;
/**
* Report for a single collection
* @typedef {Object} CollectionReport
* @property {CollectionAnalysisResult} analysis - Analysis results
* @property {RepairOperationResult[]} repairs - Repair operation results
* @property {ValidationResult} validation - Validation results
* @property {'success'|'partial'|'failed'} status - Overall collection status
*/
&nbsp;
/**
* Summary statistics for the repair report
* @typedef {Object} ReportSummary
* @property {number} criticalIssues - Number of critical issues found
* @property {number} warningIssues - Number of warning issues found
* @property {number} successfulRepairs - Number of successful repairs
* @property {number} failedRepairs - Number of failed repairs
* @property {number} totalOperations - Total number of operations performed
* @property {number} duration - Total operation duration in milliseconds
*/
&nbsp;
/**
* Audit log entry for tracking operations
* @typedef {Object} AuditLogEntry
* @property {Date} timestamp - When operation occurred
* @property {'analysis'|'repair'|'validation'|'error'} type - Operation type
* @property {string} collectionId - Collection involved
* @property {string} operation - Operation description
* @property {Object} details - Operation details
* @property {boolean} success - Whether operation succeeded
* @property {string} [error] - Error message if failed
*/
&nbsp;
/**
* Configuration options for repair operations
* @typedef {Object} RepairOptions
* @property {boolean} analysisOnly - Whether to run analysis only
* @property {string[]} [collections] - Specific collections to process
* @property {boolean} [dryRun] - Whether to simulate operations without changes
* @property {boolean} [continueOnError] - Whether to continue after errors
* @property {number} [maxRetries] - Maximum retry attempts for failed operations
* @property {boolean} [verbose] - Whether to provide verbose logging
*/
&nbsp;
/**
* Progress information for UI updates
* @typedef {Object} ProgressInfo
* @property {string} step - Current step description
* @property {number} progress - Progress percentage (0-100)
* @property {string} collectionId - Current collection being processed
* @property {string} operation - Current operation
* @property {number} completed - Number of completed operations
* @property {number} total - Total number of operations
* @property {string} [message] - Additional progress message
*/
&nbsp;
/**
* Error information with recovery instructions
* @typedef {Object} RepairError
* @property {string} code - Error code
* @property {string} message - Error message
* @property {string} collectionId - Collection where error occurred
* @property {string} operation - Operation that failed
* @property {string[]} instructions - Manual fix instructions
* @property {boolean} recoverable - Whether error is recoverable
* @property {Date} timestamp - When error occurred
*/
&nbsp;
/**
* User interface state
* @typedef {Object} InterfaceState
* @property {'idle'|'analyzing'|'repairing'|'validating'|'complete'|'error'} status - Current status
* @property {ProgressInfo} [progress] - Current progress information
* @property {ComprehensiveReport} [report] - Final report
* @property {RepairError[]} errors - List of errors encountered
* @property {boolean} canCancel - Whether operation can be cancelled
*/
&nbsp;
// Export all types for use in other modules
export const RepairTypes = {
// Type validation functions
isValidCollectionId: (id) =&gt; typeof id === 'string' &amp;&amp; id.length &gt; 0,
isValidSeverity: (severity) =&gt; ['critical', 'warning', 'info'].includes(severity),
isValidOperationType: (type) =&gt; ['add_attribute', 'set_permissions', 'validate'].includes(type),
isValidStatus: (status) =&gt; ['pass', 'fail', 'warning'].includes(status),
isValidOverallStatus: (status) =&gt; ['success', 'partial', 'failed'].includes(status),
// Default values
defaultUserIdProperties: {
type: 'string',
size: 255,
required: true,
array: false
},
defaultPermissions: {
create: ['users'],
read: ['user:$userId'],
update: ['user:$userId'],
delete: ['user:$userId']
}
};</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-01-11T21:07:32.669Z
</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>

View File

@@ -0,0 +1,331 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for AppWriteSchemaAnalyzer.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> AppWriteSchemaAnalyzer.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">20% </span>
<span class="quiet">Statements</span>
<span class='fraction'>1/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">20% </span>
<span class="quiet">Functions</span>
<span class='fraction'>1/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">20% </span>
<span class="quiet">Lines</span>
<span class='fraction'>1/5</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>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a>
<a name='L78'></a><a href='#L78'>78</a>
<a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</a>
<a name='L82'></a><a href='#L82'>82</a>
<a name='L83'></a><a href='#L83'>83</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-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-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-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-neutral">&nbsp;</span>
<span class="cline-any cline-yes">3x</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-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-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-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-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Schema Analyzer for AppWrite Collections
*
* Analyzes AppWrite collections to identify missing userId attributes and permission issues.
* Validates attribute properties and provides comprehensive reporting.
*
* Requirements: 1.1, 1.5
*/
&nbsp;
/**
* @typedef {Object} UserIdAttributeProperties
* @property {string} type - Attribute type (should be 'string')
* @property {number} size - Maximum character length (should be 255)
* @property {boolean} required - Whether the attribute is required
* @property {boolean} array - Whether the attribute is an array
*/
&nbsp;
/**
* @typedef {Object} CollectionPermissions
* @property {string[]} create - Create permissions
* @property {string[]} read - Read permissions
* @property {string[]} update - Update permissions
* @property {string[]} delete - Delete permissions
*/
&nbsp;
/**
* @typedef {Object} CollectionAnalysisResult
* @property {string} collectionId - Collection identifier
* @property {boolean} exists - Whether the collection exists
* @property {boolean} hasUserId - Whether userId attribute exists
* @property {UserIdAttributeProperties|null} userIdProperties - Properties of userId attribute
* @property {CollectionPermissions} permissions - Current collection permissions
* @property {string[]} issues - List of identified issues
* @property {'critical'|'warning'|'info'} severity - Issue severity level
*/
&nbsp;
export class SchemaAnalyzer {
/**
* @param {Object} appWriteManager - AppWrite manager instance
*/
constructor(appWriteManager) {
this.appWriteManager = appWriteManager;
}
&nbsp;
/**
* Analyzes a single collection's schema for userId attribute and permissions
* @param {string} collectionId - Collection to analyze
* @returns {Promise&lt;CollectionAnalysisResult&gt;} Analysis result
*/
<span class="fstat-no" title="function not covered" > as</span>ync analyzeCollection(collectionId) {
// Implementation will be added in task 2.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Analyzes all required collections for schema issues
* @returns {Promise&lt;CollectionAnalysisResult[]&gt;} Array of analysis results
*/
<span class="fstat-no" title="function not covered" > as</span>ync analyzeAllCollections() {
// Implementation will be added in task 2.3
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Validates that userId attribute has correct properties
* @param {Object} attribute - Attribute object from AppWrite
* @returns {boolean} Whether attribute properties are correct
*/
<span class="fstat-no" title="function not covered" > as</span>ync validateAttributeProperties(attribute) {
// Implementation will be added in task 2.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Checks collection permissions for proper configuration
* @param {string} collectionId - Collection to check
* @returns {Promise&lt;CollectionPermissions&gt;} Current permissions
*/
<span class="fstat-no" title="function not covered" > as</span>ync checkPermissions(collectionId) {
// Implementation will be added in task 2.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
}</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-01-11T21:07:32.669Z
</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>

View File

@@ -0,0 +1,325 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for AppWriteSchemaRepairer.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> AppWriteSchemaRepairer.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">37.5% </span>
<span class="quiet">Statements</span>
<span class='fraction'>3/8</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">16.66% </span>
<span class="quiet">Functions</span>
<span class='fraction'>1/6</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">37.5% </span>
<span class="quiet">Lines</span>
<span class='fraction'>3/8</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>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a>
<a name='L78'></a><a href='#L78'>78</a>
<a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</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-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-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-yes">3x</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-yes">3x</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-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-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-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-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-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Schema Repairer for AppWrite Collections
*
* Automatically adds missing userId attributes and configures proper permissions.
* Handles error recovery and provides resilient operation handling.
*
* Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 6.2, 6.4
*/
&nbsp;
/**
* @typedef {Object} RepairOperationResult
* @property {string} collectionId - Collection identifier
* @property {'add_attribute'|'set_permissions'|'validate'} operation - Type of operation
* @property {boolean} success - Whether operation succeeded
* @property {string} [error] - Error message if operation failed
* @property {string} details - Operation details
* @property {Date} timestamp - When operation was performed
*/
&nbsp;
export class SchemaRepairer {
/**
* @param {Object} appWriteManager - AppWrite manager instance
*/
constructor(appWriteManager) {
this.appWriteManager = appWriteManager;
this.maxRetries = 3;
this.baseDelay = 1000; // 1 second base delay for exponential backoff
}
&nbsp;
/**
* Repairs a collection by adding userId attribute and setting permissions
* @param {string} collectionId - Collection to repair
* @param {string[]} issues - List of issues to fix
* @returns {Promise&lt;RepairOperationResult[]&gt;} Array of operation results
*/
<span class="fstat-no" title="function not covered" > as</span>ync repairCollection(collectionId, issues) {
// Implementation will be added in task 3.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Adds userId attribute with correct specifications to a collection
* @param {string} collectionId - Collection to modify
* @returns {Promise&lt;RepairOperationResult&gt;} Operation result
*/
<span class="fstat-no" title="function not covered" > as</span>ync addUserIdAttribute(collectionId) {
// Implementation will be added in task 3.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Sets proper permissions on a collection
* @param {string} collectionId - Collection to modify
* @returns {Promise&lt;RepairOperationResult&gt;} Operation result
*/
<span class="fstat-no" title="function not covered" > as</span>ync setCollectionPermissions(collectionId) {
// Implementation will be added in task 4.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Verifies that repair operations were successful
* @param {string} collectionId - Collection to verify
* @returns {Promise&lt;boolean&gt;} Whether repair was successful
*/
<span class="fstat-no" title="function not covered" > as</span>ync verifyRepair(collectionId) {
// Implementation will be added in task 3.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Executes an operation with retry logic and exponential backoff
* @param {Function} operation - Operation to execute
* @param {string} operationName - Name for logging
* @returns {Promise&lt;any&gt;} Operation result
*/
<span class="fstat-no" title="function not covered" > as</span>ync executeWithRetry(operation, operationName) {
// Implementation will be added in task 3.5
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
}</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-01-11T21:07:32.669Z
</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>

View File

@@ -0,0 +1,283 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for AppWriteSchemaValidator.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> AppWriteSchemaValidator.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">20% </span>
<span class="quiet">Statements</span>
<span class='fraction'>1/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/0</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">20% </span>
<span class="quiet">Functions</span>
<span class='fraction'>1/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">20% </span>
<span class="quiet">Lines</span>
<span class='fraction'>1/5</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></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-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-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-yes">3x</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-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-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-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-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
* Schema Validator for AppWrite Collections
*
* Tests repaired collections to ensure they work correctly with the extension.
* Validates query functionality and permission security.
*
* Requirements: 4.1, 4.2, 4.3, 4.4, 4.5
*/
&nbsp;
/**
* @typedef {Object} ValidationResult
* @property {string} collectionId - Collection identifier
* @property {boolean} userIdQueryTest - Whether userId query test passed
* @property {boolean} permissionTest - Whether permission test passed
* @property {'pass'|'fail'|'warning'} overallStatus - Overall validation status
* @property {string[]} issues - List of validation issues
* @property {string[]} recommendations - Recommended actions
*/
&nbsp;
export class SchemaValidator {
/**
* @param {Object} appWriteManager - AppWrite manager instance
*/
constructor(appWriteManager) {
this.appWriteManager = appWriteManager;
}
&nbsp;
/**
* Performs comprehensive validation of a collection's schema and permissions
* @param {string} collectionId - Collection to validate
* @returns {Promise&lt;ValidationResult&gt;} Validation result
*/
<span class="fstat-no" title="function not covered" > as</span>ync validateCollection(collectionId) {
// Implementation will be added in task 6.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Tests that userId queries work correctly on the collection
* @param {string} collectionId - Collection to test
* @returns {Promise&lt;boolean&gt;} Whether query test passed
*/
<span class="fstat-no" title="function not covered" > as</span>ync testUserIdQuery(collectionId) {
// Implementation will be added in task 6.1
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Tests that permissions properly restrict access
* @param {string} collectionId - Collection to test
* @returns {Promise&lt;boolean&gt;} Whether permission test passed
*/
<span class="fstat-no" title="function not covered" > as</span>ync testPermissions(collectionId) {
// Implementation will be added in task 6.3
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
&nbsp;
/**
* Generates comprehensive validation report for all collections
* @param {ValidationResult[]} results - Individual validation results
* @returns {Object} Comprehensive validation report
*/
<span class="fstat-no" title="function not covered" > as</span>ync generateValidationReport(results) {
// Implementation will be added in task 6.5
<span class="cstat-no" title="statement not covered" > throw new Error('Method not implemented yet');</span>
}
}</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-01-11T21:07:32.669Z
</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>

View File

@@ -0,0 +1,224 @@
body, html {
margin:0; padding: 0;
height: 100%;
}
body {
font-family: Helvetica Neue, Helvetica, Arial;
font-size: 14px;
color:#333;
}
.small { font-size: 12px; }
*, *:after, *:before {
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
h1 { font-size: 20px; margin: 0;}
h2 { font-size: 14px; }
pre {
font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
margin: 0;
padding: 0;
-moz-tab-size: 2;
-o-tab-size: 2;
tab-size: 2;
}
a { color:#0074D9; text-decoration:none; }
a:hover { text-decoration:underline; }
.strong { font-weight: bold; }
.space-top1 { padding: 10px 0 0 0; }
.pad2y { padding: 20px 0; }
.pad1y { padding: 10px 0; }
.pad2x { padding: 0 20px; }
.pad2 { padding: 20px; }
.pad1 { padding: 10px; }
.space-left2 { padding-left:55px; }
.space-right2 { padding-right:20px; }
.center { text-align:center; }
.clearfix { display:block; }
.clearfix:after {
content:'';
display:block;
height:0;
clear:both;
visibility:hidden;
}
.fl { float: left; }
@media only screen and (max-width:640px) {
.col3 { width:100%; max-width:100%; }
.hide-mobile { display:none!important; }
}
.quiet {
color: #7f7f7f;
color: rgba(0,0,0,0.5);
}
.quiet a { opacity: 0.7; }
.fraction {
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
font-size: 10px;
color: #555;
background: #E8E8E8;
padding: 4px 5px;
border-radius: 3px;
vertical-align: middle;
}
div.path a:link, div.path a:visited { color: #333; }
table.coverage {
border-collapse: collapse;
margin: 10px 0 0 0;
padding: 0;
}
table.coverage td {
margin: 0;
padding: 0;
vertical-align: top;
}
table.coverage td.line-count {
text-align: right;
padding: 0 5px 0 20px;
}
table.coverage td.line-coverage {
text-align: right;
padding-right: 10px;
min-width:20px;
}
table.coverage td span.cline-any {
display: inline-block;
padding: 0 5px;
width: 100%;
}
.missing-if-branch {
display: inline-block;
margin-right: 5px;
border-radius: 3px;
position: relative;
padding: 0 4px;
background: #333;
color: yellow;
}
.skip-if-branch {
display: none;
margin-right: 10px;
position: relative;
padding: 0 4px;
background: #ccc;
color: white;
}
.missing-if-branch .typ, .skip-if-branch .typ {
color: inherit !important;
}
.coverage-summary {
border-collapse: collapse;
width: 100%;
}
.coverage-summary tr { border-bottom: 1px solid #bbb; }
.keyline-all { border: 1px solid #ddd; }
.coverage-summary td, .coverage-summary th { padding: 10px; }
.coverage-summary tbody { border: 1px solid #bbb; }
.coverage-summary td { border-right: 1px solid #bbb; }
.coverage-summary td:last-child { border-right: none; }
.coverage-summary th {
text-align: left;
font-weight: normal;
white-space: nowrap;
}
.coverage-summary th.file { border-right: none !important; }
.coverage-summary th.pct { }
.coverage-summary th.pic,
.coverage-summary th.abs,
.coverage-summary td.pct,
.coverage-summary td.abs { text-align: right; }
.coverage-summary td.file { white-space: nowrap; }
.coverage-summary td.pic { min-width: 120px !important; }
.coverage-summary tfoot td { }
.coverage-summary .sorter {
height: 10px;
width: 7px;
display: inline-block;
margin-left: 0.5em;
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
}
.coverage-summary .sorted .sorter {
background-position: 0 -20px;
}
.coverage-summary .sorted-desc .sorter {
background-position: 0 -10px;
}
.status-line { height: 10px; }
/* yellow */
.cbranch-no { background: yellow !important; color: #111; }
/* dark red */
.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
.low .chart { border:1px solid #C21F39 }
.highlighted,
.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
background: #C21F39 !important;
}
/* medium red */
.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
/* light red */
.low, .cline-no { background:#FCE1E5 }
/* light green */
.high, .cline-yes { background:rgb(230,245,208) }
/* medium green */
.cstat-yes { background:rgb(161,215,106) }
/* dark green */
.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
.high .chart { border:1px solid rgb(77,146,33) }
/* dark yellow (gold) */
.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
.medium .chart { border:1px solid #f9cd0b; }
/* light yellow */
.medium { background: #fff4c2; }
.cstat-skip { background: #ddd; color: #111; }
.fstat-skip { background: #ddd; color: #111 !important; }
.cbranch-skip { background: #ddd !important; color: #111; }
span.cline-neutral { background: #eaeaea; }
.coverage-summary td.empty {
opacity: .5;
padding-top: 4px;
padding-bottom: 4px;
line-height: 1;
color: #888;
}
.cover-fill, .cover-empty {
display:inline-block;
height: 12px;
}
.chart {
line-height: 0;
}
.cover-empty {
background: white;
}
.cover-full {
border-right: none !important;
}
pre.prettyprint {
border: none !important;
padding: 0 !important;
margin: 0 !important;
}
.com { color: #999 !important; }
.ignore-none { color: #999; font-weight: normal; }
.wrapper {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto -48px;
}
.footer, .push {
height: 48px;
}

View File

@@ -0,0 +1,87 @@
/* eslint-disable */
var jumpToCode = (function init() {
// Classes of code we would like to highlight in the file view
var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
// Elements to highlight in the file listing view
var fileListingElements = ['td.pct.low'];
// We don't want to select elements that are direct descendants of another match
var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
// Selector that finds elements on the page to which we can jump
var selector =
fileListingElements.join(', ') +
', ' +
notSelector +
missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
// The NodeList of matching elements
var missingCoverageElements = document.querySelectorAll(selector);
var currentIndex;
function toggleClass(index) {
missingCoverageElements
.item(currentIndex)
.classList.remove('highlighted');
missingCoverageElements.item(index).classList.add('highlighted');
}
function makeCurrent(index) {
toggleClass(index);
currentIndex = index;
missingCoverageElements.item(index).scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
});
}
function goToPrevious() {
var nextIndex = 0;
if (typeof currentIndex !== 'number' || currentIndex === 0) {
nextIndex = missingCoverageElements.length - 1;
} else if (missingCoverageElements.length > 1) {
nextIndex = currentIndex - 1;
}
makeCurrent(nextIndex);
}
function goToNext() {
var nextIndex = 0;
if (
typeof currentIndex === 'number' &&
currentIndex < missingCoverageElements.length - 1
) {
nextIndex = currentIndex + 1;
}
makeCurrent(nextIndex);
}
return function jump(event) {
if (
document.getElementById('fileSearch') === document.activeElement &&
document.activeElement != null
) {
// if we're currently focused on the search input, we don't want to navigate
return;
}
switch (event.which) {
case 78: // n
case 74: // j
goToNext();
break;
case 66: // b
case 75: // k
case 80: // p
goToPrevious();
break;
}
};
})();
window.addEventListener('keydown', jumpToCode);

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

View File

@@ -0,0 +1,191 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for All files</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>All files</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">46.51% </span>
<span class="quiet">Statements</span>
<span class='fraction'>20/43</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">50% </span>
<span class="quiet">Branches</span>
<span class='fraction'>2/4</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">30.3% </span>
<span class="quiet">Functions</span>
<span class='fraction'>10/33</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">46.51% </span>
<span class="quiet">Lines</span>
<span class='fraction'>20/43</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>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file medium" data-value="AppWriteRepairController.js"><a href="AppWriteRepairController.js.html">AppWriteRepairController.js</a></td>
<td data-value="50" class="pic medium">
<div class="chart"><div class="cover-fill" style="width: 50%"></div><div class="cover-empty" style="width: 50%"></div></div>
</td>
<td data-value="50" class="pct medium">50%</td>
<td data-value="10" class="abs medium">5/10</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
<td data-value="16.66" class="pct low">16.66%</td>
<td data-value="6" class="abs low">1/6</td>
<td data-value="50" class="pct medium">50%</td>
<td data-value="10" class="abs medium">5/10</td>
</tr>
<tr>
<td class="file low" data-value="AppWriteRepairInterface.js"><a href="AppWriteRepairInterface.js.html">AppWriteRepairInterface.js</a></td>
<td data-value="44.44" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 44%"></div><div class="cover-empty" style="width: 56%"></div></div>
</td>
<td data-value="44.44" class="pct low">44.44%</td>
<td data-value="9" class="abs low">4/9</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="1" class="abs low">0/1</td>
<td data-value="16.66" class="pct low">16.66%</td>
<td data-value="6" class="abs low">1/6</td>
<td data-value="44.44" class="pct low">44.44%</td>
<td data-value="9" class="abs low">4/9</td>
</tr>
<tr>
<td class="file high" data-value="AppWriteRepairTypes.js"><a href="AppWriteRepairTypes.js.html">AppWriteRepairTypes.js</a></td>
<td data-value="100" class="pic high">
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="6" class="abs high">6/6</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="2" class="abs high">2/2</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="5" class="abs high">5/5</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="6" class="abs high">6/6</td>
</tr>
<tr>
<td class="file low" data-value="AppWriteSchemaAnalyzer.js"><a href="AppWriteSchemaAnalyzer.js.html">AppWriteSchemaAnalyzer.js</a></td>
<td data-value="20" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 20%"></div><div class="cover-empty" style="width: 80%"></div></div>
</td>
<td data-value="20" class="pct low">20%</td>
<td data-value="5" class="abs low">1/5</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="20" class="pct low">20%</td>
<td data-value="5" class="abs low">1/5</td>
<td data-value="20" class="pct low">20%</td>
<td data-value="5" class="abs low">1/5</td>
</tr>
<tr>
<td class="file low" data-value="AppWriteSchemaRepairer.js"><a href="AppWriteSchemaRepairer.js.html">AppWriteSchemaRepairer.js</a></td>
<td data-value="37.5" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 37%"></div><div class="cover-empty" style="width: 63%"></div></div>
</td>
<td data-value="37.5" class="pct low">37.5%</td>
<td data-value="8" class="abs low">3/8</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="16.66" class="pct low">16.66%</td>
<td data-value="6" class="abs low">1/6</td>
<td data-value="37.5" class="pct low">37.5%</td>
<td data-value="8" class="abs low">3/8</td>
</tr>
<tr>
<td class="file low" data-value="AppWriteSchemaValidator.js"><a href="AppWriteSchemaValidator.js.html">AppWriteSchemaValidator.js</a></td>
<td data-value="20" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 20%"></div><div class="cover-empty" style="width: 80%"></div></div>
</td>
<td data-value="20" class="pct low">20%</td>
<td data-value="5" class="abs low">1/5</td>
<td data-value="100" class="pct high">100%</td>
<td data-value="0" class="abs high">0/0</td>
<td data-value="20" class="pct low">20%</td>
<td data-value="5" class="abs low">1/5</td>
<td data-value="20" class="pct low">20%</td>
<td data-value="5" class="abs low">1/5</td>
</tr>
</tbody>
</table>
</div>
<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-01-11T21:07:32.669Z
</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>

View File

@@ -0,0 +1 @@
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 B

View File

@@ -0,0 +1,210 @@
/* eslint-disable */
var addSorting = (function() {
'use strict';
var cols,
currentSort = {
index: 0,
desc: false
};
// returns the summary table element
function getTable() {
return document.querySelector('.coverage-summary');
}
// returns the thead element of the summary table
function getTableHeader() {
return getTable().querySelector('thead tr');
}
// returns the tbody element of the summary table
function getTableBody() {
return getTable().querySelector('tbody');
}
// returns the th element for nth column
function getNthColumn(n) {
return getTableHeader().querySelectorAll('th')[n];
}
function onFilterInput() {
const searchValue = document.getElementById('fileSearch').value;
const rows = document.getElementsByTagName('tbody')[0].children;
// Try to create a RegExp from the searchValue. If it fails (invalid regex),
// it will be treated as a plain text search
let searchRegex;
try {
searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive
} catch (error) {
searchRegex = null;
}
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
let isMatch = false;
if (searchRegex) {
// If a valid regex was created, use it for matching
isMatch = searchRegex.test(row.textContent);
} else {
// Otherwise, fall back to the original plain text search
isMatch = row.textContent
.toLowerCase()
.includes(searchValue.toLowerCase());
}
row.style.display = isMatch ? '' : 'none';
}
}
// loads the search box
function addSearchBox() {
var template = document.getElementById('filterTemplate');
var templateClone = template.content.cloneNode(true);
templateClone.getElementById('fileSearch').oninput = onFilterInput;
template.parentElement.appendChild(templateClone);
}
// loads all columns
function loadColumns() {
var colNodes = getTableHeader().querySelectorAll('th'),
colNode,
cols = [],
col,
i;
for (i = 0; i < colNodes.length; i += 1) {
colNode = colNodes[i];
col = {
key: colNode.getAttribute('data-col'),
sortable: !colNode.getAttribute('data-nosort'),
type: colNode.getAttribute('data-type') || 'string'
};
cols.push(col);
if (col.sortable) {
col.defaultDescSort = col.type === 'number';
colNode.innerHTML =
colNode.innerHTML + '<span class="sorter"></span>';
}
}
return cols;
}
// attaches a data attribute to every tr element with an object
// of data values keyed by column name
function loadRowData(tableRow) {
var tableCols = tableRow.querySelectorAll('td'),
colNode,
col,
data = {},
i,
val;
for (i = 0; i < tableCols.length; i += 1) {
colNode = tableCols[i];
col = cols[i];
val = colNode.getAttribute('data-value');
if (col.type === 'number') {
val = Number(val);
}
data[col.key] = val;
}
return data;
}
// loads all row data
function loadData() {
var rows = getTableBody().querySelectorAll('tr'),
i;
for (i = 0; i < rows.length; i += 1) {
rows[i].data = loadRowData(rows[i]);
}
}
// sorts the table using the data for the ith column
function sortByIndex(index, desc) {
var key = cols[index].key,
sorter = function(a, b) {
a = a.data[key];
b = b.data[key];
return a < b ? -1 : a > b ? 1 : 0;
},
finalSorter = sorter,
tableBody = document.querySelector('.coverage-summary tbody'),
rowNodes = tableBody.querySelectorAll('tr'),
rows = [],
i;
if (desc) {
finalSorter = function(a, b) {
return -1 * sorter(a, b);
};
}
for (i = 0; i < rowNodes.length; i += 1) {
rows.push(rowNodes[i]);
tableBody.removeChild(rowNodes[i]);
}
rows.sort(finalSorter);
for (i = 0; i < rows.length; i += 1) {
tableBody.appendChild(rows[i]);
}
}
// removes sort indicators for current column being sorted
function removeSortIndicators() {
var col = getNthColumn(currentSort.index),
cls = col.className;
cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
col.className = cls;
}
// adds sort indicators for current column being sorted
function addSortIndicators() {
getNthColumn(currentSort.index).className += currentSort.desc
? ' sorted-desc'
: ' sorted';
}
// adds event listeners for all sorter widgets
function enableUI() {
var i,
el,
ithSorter = function ithSorter(i) {
var col = cols[i];
return function() {
var desc = col.defaultDescSort;
if (currentSort.index === i) {
desc = !currentSort.desc;
}
sortByIndex(i, desc);
removeSortIndicators();
currentSort.index = i;
currentSort.desc = desc;
addSortIndicators();
};
};
for (i = 0; i < cols.length; i += 1) {
if (cols[i].sortable) {
// add the click event handler on the th so users
// dont have to click on those tiny arrows
el = getNthColumn(i).querySelector('.sorter').parentElement;
if (el.addEventListener) {
el.addEventListener('click', ithSorter(i));
} else {
el.attachEvent('onclick', ithSorter(i));
}
}
}
}
// adds sorting functionality to the UI
return function() {
if (!getTable()) {
return;
}
cols = loadColumns();
loadData();
addSearchBox();
addSortIndicators();
enableUI();
};
})();
window.addEventListener('load', addSorting);

167
coverage/lcov.info Normal file
View File

@@ -0,0 +1,167 @@
TN:
SF:src\AppWriteRepairController.js
FN:29,(anonymous_0)
FN:44,(anonymous_1)
FN:54,(anonymous_2)
FN:64,(anonymous_3)
FN:73,(anonymous_4)
FN:83,(anonymous_5)
FNF:6
FNH:1
FNDA:2,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
FNDA:0,(anonymous_5)
DA:30,2
DA:31,2
DA:32,2
DA:33,2
DA:34,2
DA:46,0
DA:56,0
DA:66,0
DA:75,0
DA:85,0
LF:10
LH:5
BRDA:44,0,0,0
BRF:1
BRH:0
end_of_record
TN:
SF:src\AppWriteRepairInterface.js
FN:14,(anonymous_0)
FN:26,(anonymous_1)
FN:37,(anonymous_2)
FN:46,(anonymous_3)
FN:57,(anonymous_4)
FN:67,(anonymous_5)
FNF:6
FNH:1
FNDA:1,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
FNDA:0,(anonymous_5)
DA:15,1
DA:16,1
DA:17,1
DA:18,1
DA:28,0
DA:39,0
DA:48,0
DA:59,0
DA:69,0
LF:9
LH:4
BRDA:37,0,0,0
BRF:1
BRH:0
end_of_record
TN:
SF:src\AppWriteRepairTypes.js
FN:161,(anonymous_0)
FN:162,(anonymous_1)
FN:163,(anonymous_2)
FN:164,(anonymous_3)
FN:165,(anonymous_4)
FNF:5
FNH:5
FNDA:405,(anonymous_0)
FNDA:105,(anonymous_1)
FNDA:104,(anonymous_2)
FNDA:104,(anonymous_3)
FNDA:4,(anonymous_4)
DA:159,1
DA:161,405
DA:162,105
DA:163,104
DA:164,104
DA:165,4
LF:6
LH:6
BRDA:161,0,0,405
BRDA:161,0,1,403
BRF:2
BRH:2
end_of_record
TN:
SF:src\AppWriteSchemaAnalyzer.js
FN:41,(anonymous_0)
FN:50,(anonymous_1)
FN:59,(anonymous_2)
FN:69,(anonymous_3)
FN:79,(anonymous_4)
FNF:5
FNH:1
FNDA:3,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
DA:42,3
DA:52,0
DA:61,0
DA:71,0
DA:81,0
LF:5
LH:1
BRF:0
BRH:0
end_of_record
TN:
SF:src\AppWriteSchemaRepairer.js
FN:24,(anonymous_0)
FN:36,(anonymous_1)
FN:46,(anonymous_2)
FN:56,(anonymous_3)
FN:66,(anonymous_4)
FN:77,(anonymous_5)
FNF:6
FNH:1
FNDA:3,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
FNDA:0,(anonymous_5)
DA:25,3
DA:26,3
DA:27,3
DA:38,0
DA:48,0
DA:58,0
DA:68,0
DA:79,0
LF:8
LH:3
BRF:0
BRH:0
end_of_record
TN:
SF:src\AppWriteSchemaValidator.js
FN:24,(anonymous_0)
FN:33,(anonymous_1)
FN:43,(anonymous_2)
FN:53,(anonymous_3)
FN:63,(anonymous_4)
FNF:5
FNH:1
FNDA:3,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
DA:25,3
DA:35,0
DA:45,0
DA:55,0
DA:65,0
LF:5
LH:1
BRF:0
BRH:0
end_of_record