215 lines
11 KiB
HTML
215 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>gerbeur documentation</title>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="doc-current-file" content="">
|
|
<link rel="stylesheet" href="styles.css">
|
|
<link rel="stylesheet" href="page.css">
|
|
<link id="ddocResetStylesheet" rel="stylesheet" href="reset.css"><link href="comrak.css" rel="stylesheet" /><link href="prism.css" rel="stylesheet" /><script src="prism.js"></script><script src="script.js" defer></script>
|
|
<script src="darkmode_toggle.js"></script><script src="search_index.js" defer></script>
|
|
<script src="fuse.js" defer></script>
|
|
<script src="search.js" defer></script></head>
|
|
<body>
|
|
<div class="ddoc">
|
|
<div><nav id="topnav">
|
|
<div class="h-full">
|
|
<div class="flex items-center"><ul class="breadcrumbs">
|
|
<li>
|
|
<a href="" class="contextLink">gerbeur</a>
|
|
</li></ul>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-2">
|
|
<button id="theme-toggle" type="button" aria-label="Toggle dark mode" style="display: none;"><svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="14"
|
|
height="14"
|
|
viewBox="0 0 24 24"
|
|
fill="currentColor"
|
|
>
|
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
<path
|
|
d="M12 1.992a10 10 0 1 0 9.236 13.838c.341 -.82 -.476 -1.644 -1.298 -1.31a6.5 6.5 0 0 1 -6.864 -10.787l.077 -.08c.551 -.63 .113 -1.653 -.758 -1.653h-.266l-.068 -.006l-.06 -.002z"
|
|
/>
|
|
</svg>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="14"
|
|
height="14"
|
|
viewBox="0 0 24 24"
|
|
fill="currentColor"
|
|
class="hidden"
|
|
>
|
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
<path
|
|
d="M12 19a1 1 0 0 1 .993 .883l.007 .117v1a1 1 0 0 1 -1.993 .117l-.007 -.117v-1a1 1 0 0 1 1 -1z"
|
|
/>
|
|
<path
|
|
d="M18.313 16.91l.094 .083l.7 .7a1 1 0 0 1 -1.32 1.497l-.094 -.083l-.7 -.7a1 1 0 0 1 1.218 -1.567l.102 .07z"
|
|
/>
|
|
<path
|
|
d="M7.007 16.993a1 1 0 0 1 .083 1.32l-.083 .094l-.7 .7a1 1 0 0 1 -1.497 -1.32l.083 -.094l.7 -.7a1 1 0 0 1 1.414 0z"
|
|
/>
|
|
<path
|
|
d="M4 11a1 1 0 0 1 .117 1.993l-.117 .007h-1a1 1 0 0 1 -.117 -1.993l.117 -.007h1z"
|
|
/>
|
|
<path
|
|
d="M21 11a1 1 0 0 1 .117 1.993l-.117 .007h-1a1 1 0 0 1 -.117 -1.993l.117 -.007h1z"
|
|
/>
|
|
<path
|
|
d="M6.213 4.81l.094 .083l.7 .7a1 1 0 0 1 -1.32 1.497l-.094 -.083l-.7 -.7a1 1 0 0 1 1.217 -1.567l.102 .07z"
|
|
/>
|
|
<path
|
|
d="M19.107 4.893a1 1 0 0 1 .083 1.32l-.083 .094l-.7 .7a1 1 0 0 1 -1.497 -1.32l.083 -.094l.7 -.7a1 1 0 0 1 1.414 0z"
|
|
/>
|
|
<path
|
|
d="M12 2a1 1 0 0 1 .993 .883l.007 .117v1a1 1 0 0 1 -1.993 .117l-.007 -.117v-1a1 1 0 0 1 1 -1z"
|
|
/>
|
|
<path
|
|
d="M12 7a5 5 0 1 1 -4.995 5.217l-.005 -.217l.005 -.217a5 5 0 0 1 4.995 -4.783z"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
|
|
<input
|
|
type="text"
|
|
id="searchbar"
|
|
style="display: none;"
|
|
class="py-2 px-2.5 mx-1 rounded text-sm border border-gray-300 bg-transparent dark:bg-gray-800 dark:border-gray-700"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<div id="searchResults"></div><div id="content">
|
|
<main><section>
|
|
<div class="space-y-2 flex-1"><div class="space-y-7" id="module_doc"><div class="markdown"><p>Documents gerbeur, a small invite-only social platform for sharing links and
|
|
files. The repository holds three parts: the backend in <code>api/</code>, the
|
|
frontend in <code>src/</code>, and in <code>shared/</code> whatever crosses the wire between them.
|
|
<a href="./all_symbols.html">Every module</a> is listed by path, so the list groups
|
|
them by part and layer.</p>
|
|
<h2 id="backend,-in-api/">
|
|
Backend, in <code>api/</code></h2>
|
|
<p>An Oak server over SQLite answers the API and the WebSocket, and serves the
|
|
built frontend. <code>api/main.ts</code> builds the application and listens. A request
|
|
goes to a route, which parses it, calls services and answers. The services
|
|
hold the logic and every SQL query, read rows through the model, and reach
|
|
other sites only through <code>remote/</code>. Each folder holds one kind of module,
|
|
and each file is named after its domain.</p>
|
|
<ul>
|
|
<li><code>routes/</code> holds the HTTP API, one router per resource. Each router's page
|
|
lists its endpoints, with their method and path, who may call them, and
|
|
what they do; <code>API.md</code> at the root sums them up, with the rule they all
|
|
follow.</li>
|
|
<li><code>middleware/</code> holds what runs around the routes, which is auth, errors and
|
|
the Open Graph tags.</li>
|
|
<li><code>services/</code> holds the logic and every SQL query, one module per domain.</li>
|
|
<li><code>model/</code> holds each table's row type, guard and mappers.</li>
|
|
<li><code>validators/</code> holds the guards of the request bodies.</li>
|
|
<li><code>remote/</code> is the only place that fetches from other sites, and its
|
|
<code>providers/</code> build the previews of each kind of site.</li>
|
|
<li><code>mail/</code> renders each email, one template per email on a shared layout
|
|
that takes every site style, its colors and fonts read from the themes'
|
|
stylesheets, and <code>services/email-service.ts</code> sends them.</li>
|
|
<li><code>lib/</code> holds the helpers that belong to no layer.</li>
|
|
<li><code>db/</code> opens, creates and migrates the database, and cleans it up at
|
|
startup. <code>db/migrations/</code> are applied in order, each once.</li>
|
|
<li><code>config.ts</code> reads the settings from the environment, and <code>scripts/</code> holds
|
|
the icon generator.</li>
|
|
</ul>
|
|
<h2 id="shared,-in-shared/">
|
|
Shared, in <code>shared/</code></h2>
|
|
<p>The types and constants both halves use sit here, one module per domain.
|
|
They are the API envelope, each domain's types and request bodies, the
|
|
socket protocol, the validation limits, the role permissions, and the page
|
|
paths and slugs (<code>paths.ts</code>, <code>slug.ts</code>) the client links with and the
|
|
server matches. <code>shared/</code> imports nothing from either half. The server
|
|
sends <code>Date</code>s, and the client reads the same types through <code>Wire<T></code>, where
|
|
every <code>Date</code> is an ISO string.</p>
|
|
<p>Beside it, <code>locales/</code> holds one Lingui catalogue per language for the whole
|
|
app: the interface's messages, and the emails' that <code>api/mail/i18n.ts</code>
|
|
loads compiled. The interface writes its English in place (<code>t</code>, <code>Trans</code>)
|
|
and Lingui keys the message by it. A message with a named id, which every
|
|
email's is, along with the labels the interface shares with them, has its
|
|
English in <code>locales/en.po</code> alone and the code names only the id; the build
|
|
fails when a language lacks one.</p>
|
|
<h2 id="frontend,-in-src/">
|
|
Frontend, in <code>src/</code></h2>
|
|
<p>The React app is built with Vite and translated with Lingui. <code>main.tsx</code>
|
|
mounts it, <code>App.tsx</code> holds the providers and the route table, and <code>i18n.ts</code>
|
|
sets the language. A page reads the API and the socket through contexts and
|
|
hooks, and draws with components, while utils hold what isn't React at all.</p>
|
|
<ul>
|
|
<li><code>pages/</code> holds one component per route, each naming its route, and the two
|
|
guards that keep routes to signed-in or signed-out visitors.</li>
|
|
<li><code>config/</code> holds the settings read at startup.</li>
|
|
<li><code>contexts/</code> holds, for each domain, a <code>FooContext</code> with its state and the
|
|
<code>FooProvider</code> that fills it.</li>
|
|
<li><code>hooks/</code> holds every hook, and <code>components/</code> only components.</li>
|
|
<li><code>utils/</code> holds every module that isn't React.</li>
|
|
</ul>
|
|
<p>Every layer but <code>pages/</code> and <code>config/</code> is split into the same domains (auth,
|
|
category, chat, comment, dump, editor, feed, form, layout, player, playlist,
|
|
profile, social, theme, ws, and shared for what belongs to no one domain), so
|
|
the chat lives in <code>components/chat/</code>, <code>contexts/chat/</code>, <code>hooks/chat/</code> and
|
|
<code>utils/chat/</code>.</p>
|
|
</div></div>
|
|
</div>
|
|
</section>
|
|
</main><div class="toc">
|
|
<div><nav class="topSymbols">
|
|
<h3>Symbols</h3>
|
|
<ul><li>
|
|
<a href="./api/middleware/auth.ts/~/AuthState.html" title="AuthState"><div class="docNodeKindIcon"><div class="text-Interface bg-Interface/15 dark:text-InterfaceDark dark:bg-InterfaceDark/15" title="Interface">I</div></div>
|
|
<span class="hover:bg-Interface/15 hover:bg-InterfaceDark/15">
|
|
AuthState
|
|
</span>
|
|
</a>
|
|
</li><li>
|
|
<a href="./api/middleware/auth.ts/~/AuthContext.html" title="AuthContext"><div class="docNodeKindIcon"><div class="text-TypeAlias bg-TypeAlias/15 dark:text-TypeAliasDark dark:bg-TypeAliasDark/15" title="Type Alias">T</div></div>
|
|
<span class="hover:bg-TypeAlias/15 hover:bg-TypeAliasDark/15">
|
|
AuthContext
|
|
</span>
|
|
</a>
|
|
</li><li>
|
|
<a href="./api/middleware/auth.ts/~/authMiddleware.html" title="authMiddleware"><div class="docNodeKindIcon"><div class="text-Function bg-Function/15 dark:text-FunctionDark dark:bg-FunctionDark/15" title="Function">f</div></div>
|
|
<span class="hover:bg-Function/15 hover:bg-FunctionDark/15">
|
|
authMiddleware
|
|
</span>
|
|
</a>
|
|
</li><li>
|
|
<a href="./api/middleware/auth.ts/~/requirePermission.html" title="requirePermission"><div class="docNodeKindIcon"><div class="text-Function bg-Function/15 dark:text-FunctionDark dark:bg-FunctionDark/15" title="Function">f</div></div>
|
|
<span class="hover:bg-Function/15 hover:bg-FunctionDark/15">
|
|
requirePermission
|
|
</span>
|
|
</a>
|
|
</li><li>
|
|
<a href="./api/middleware/error.ts/~/errorMiddleware.html" title="errorMiddleware"><div class="docNodeKindIcon"><div class="text-Function bg-Function/15 dark:text-FunctionDark dark:bg-FunctionDark/15" title="Function">f</div></div>
|
|
<span class="hover:bg-Function/15 hover:bg-FunctionDark/15">
|
|
errorMiddleware
|
|
</span>
|
|
</a>
|
|
</li></ul><a class="flex items-center gap-0.5" href="./all_symbols.html">
|
|
<span class="leading-none">view all 1307 symbols</span><svg
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 16 16"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<path
|
|
fill-rule="evenodd"
|
|
clip-rule="evenodd"
|
|
d="M5.76748 11.8159C5.5378 11.577 5.54525 11.1972 5.78411 10.9675L8.93431 8L5.78411 5.0325C5.54525 4.80282 5.5378 4.423 5.76748 4.18413C5.99715 3.94527 6.37698 3.93782 6.61584 4.1675L10.2158 7.5675C10.3335 7.68062 10.4 7.83679 10.4 8C10.4 8.16321 10.3335 8.31938 10.2158 8.4325L6.61584 11.8325C6.37698 12.0622 5.99715 12.0547 5.76748 11.8159Z"
|
|
fill="currentColor"
|
|
/>
|
|
</svg>
|
|
</a></nav><nav class="documentNavigation">
|
|
<h3>Document Navigation</h3><ul><li><a href="#backend,-in-api/" title="Backend, in api/">Backend, in api/</a></li><li><a href="#shared,-in-shared/" title="Shared, in shared/">Shared, in shared/</a></li><li><a href="#frontend,-in-src/" title="Frontend, in src/">Frontend, in src/</a></li></ul></nav></div>
|
|
</div></div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|