You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
281 lines
6.3 KiB
281 lines
6.3 KiB
|
5 months ago
|
<script lang="ts">
|
||
|
|
import ModuleHeader from './ModuleHeader.svelte';
|
||
|
|
import CodeBlock from './CodeBlock.svelte';
|
||
|
|
import Callout from './Callout.svelte';
|
||
|
|
import AiAgentsBox from './AiAgentsBox.svelte';
|
||
|
|
import PageNav from './PageNav.svelte';
|
||
|
|
|
||
|
|
export interface DocCode {
|
||
|
|
readonly title?: string;
|
||
|
|
readonly lang?: string;
|
||
|
|
readonly code: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface DocRow {
|
||
|
|
readonly name: string;
|
||
|
|
readonly purpose: string;
|
||
|
|
readonly notes?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface DocSection {
|
||
|
|
readonly title: string;
|
||
|
|
readonly body?: readonly string[];
|
||
|
|
readonly bullets?: readonly string[];
|
||
|
|
readonly table?: readonly DocRow[];
|
||
|
|
readonly code?: DocCode;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ArtifactDocModel {
|
||
|
|
readonly section: string;
|
||
|
|
readonly title: string;
|
||
|
|
readonly alias: string;
|
||
|
|
readonly summary: string;
|
||
|
|
readonly factories: readonly string[];
|
||
|
|
readonly dependsOn?: readonly string[];
|
||
|
|
readonly layer: string;
|
||
|
|
readonly overview: readonly string[];
|
||
|
|
readonly dynamics?: readonly string[];
|
||
|
|
readonly commonMistakes?: readonly DocRow[];
|
||
|
|
readonly quickStart: DocCode;
|
||
|
|
readonly factoryRows: readonly DocRow[];
|
||
|
|
readonly api?: readonly DocSection[];
|
||
|
|
readonly sections: readonly DocSection[];
|
||
|
|
readonly tests: readonly DocRow[];
|
||
|
|
readonly status?: {
|
||
|
|
readonly variant: 'info' | 'warn' | 'success' | 'tip';
|
||
|
|
readonly title: string;
|
||
|
|
readonly body: string;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
let { doc }: { doc: ArtifactDocModel } = $props();
|
||
|
|
|
||
|
|
const moduleName = $derived(doc.alias.startsWith('$') ? doc.alias.slice(1) : doc.alias);
|
||
|
|
const hasServerLayer = $derived(
|
||
|
|
doc.layer.toLowerCase().includes('server') ||
|
||
|
|
(doc.dependsOn ?? []).some((dependency) => dependency.includes('$svrs'))
|
||
|
|
);
|
||
|
|
const testTargets = $derived(doc.tests.map((test) => test.name).join(', '));
|
||
|
|
const aiAgentRows = $derived.by(() => {
|
||
|
|
const rows = [
|
||
|
|
{
|
||
|
|
step: 'Public API',
|
||
|
|
where: `src/arts/${moduleName}/index.ts and src/arts/${moduleName}/types.ts`,
|
||
|
|
rule: 'Docs and examples must match exported symbols, not planned APIs.'
|
||
|
|
},
|
||
|
|
{
|
||
|
|
step: 'Runtime shape',
|
||
|
|
where: doc.layer,
|
||
|
|
rule: 'Preserve the documented Engine/Active boundary and the ActiveEngine contract when reactive state exists.'
|
||
|
|
}
|
||
|
|
];
|
||
|
|
|
||
|
|
if (hasServerLayer) {
|
||
|
|
rows.push({
|
||
|
|
step: 'Server authority',
|
||
|
|
where: `src/svrs/${moduleName}`,
|
||
|
|
rule: 'Identity, authorization and private cache decisions stay server-side; active clients are UX reflectors.'
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
rows.push(
|
||
|
|
{
|
||
|
|
step: 'Logging',
|
||
|
|
where: '$libs/logger.Logger plus module consts.ts',
|
||
|
|
rule: 'Use the shared Logger contract. Do not create local logger interfaces or hard-code categories/messages.'
|
||
|
|
},
|
||
|
|
{
|
||
|
|
step: 'Tests',
|
||
|
|
where: testTargets,
|
||
|
|
rule: 'Update or add tests when behavior, public contracts or integration points change.'
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
return rows;
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<svelte:head>
|
||
|
|
<title>{doc.title} ({doc.alias}) — Active</title>
|
||
|
|
</svelte:head>
|
||
|
|
|
||
|
|
<article class="article">
|
||
|
|
<ModuleHeader
|
||
|
|
section={doc.section}
|
||
|
|
title={doc.title}
|
||
|
|
alias={doc.alias}
|
||
|
|
summary={doc.summary}
|
||
|
|
factories={doc.factories}
|
||
|
|
dependsOn={doc.dependsOn}
|
||
|
|
layer={doc.layer}
|
||
|
|
/>
|
||
|
|
|
||
|
|
{#if doc.status}
|
||
|
|
<Callout variant={doc.status.variant} title={doc.status.title}>
|
||
|
|
<p>{doc.status.body}</p>
|
||
|
|
</Callout>
|
||
|
|
{/if}
|
||
|
|
|
||
|
|
<h2>Overview</h2>
|
||
|
|
{#each doc.overview as paragraph}
|
||
|
|
<p>{paragraph}</p>
|
||
|
|
{/each}
|
||
|
|
|
||
|
|
{#if doc.dynamics?.length}
|
||
|
|
<h2>How it works in practice</h2>
|
||
|
|
{#each doc.dynamics as paragraph}
|
||
|
|
<p>{paragraph}</p>
|
||
|
|
{/each}
|
||
|
|
{/if}
|
||
|
|
|
||
|
|
<h2>Quick start</h2>
|
||
|
|
<CodeBlock code={doc.quickStart.code} lang={doc.quickStart.lang ?? 'ts'} title={doc.quickStart.title} />
|
||
|
|
|
||
|
|
<h2>Factories</h2>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Factory</th>
|
||
|
|
<th>Purpose</th>
|
||
|
|
<th>Notes</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
{#each doc.factoryRows as row (row.name)}
|
||
|
|
<tr>
|
||
|
|
<td><code>{row.name}</code></td>
|
||
|
|
<td>{row.purpose}</td>
|
||
|
|
<td>{row.notes ?? ''}</td>
|
||
|
|
</tr>
|
||
|
|
{/each}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
|
||
|
|
{#if doc.api?.length}
|
||
|
|
<h2>API reference</h2>
|
||
|
|
{#each doc.api as section (section.title)}
|
||
|
|
<h3>{section.title}</h3>
|
||
|
|
{#each section.body ?? [] as paragraph}
|
||
|
|
<p>{paragraph}</p>
|
||
|
|
{/each}
|
||
|
|
{#if section.table}
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Member</th>
|
||
|
|
<th>Purpose</th>
|
||
|
|
<th>Notes</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
{#each section.table as row (row.name)}
|
||
|
|
<tr>
|
||
|
|
<td><code>{row.name}</code></td>
|
||
|
|
<td>{row.purpose}</td>
|
||
|
|
<td>{row.notes ?? ''}</td>
|
||
|
|
</tr>
|
||
|
|
{/each}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
{/if}
|
||
|
|
{#if section.code}
|
||
|
|
<CodeBlock
|
||
|
|
code={section.code.code}
|
||
|
|
lang={section.code.lang ?? 'ts'}
|
||
|
|
title={section.code.title}
|
||
|
|
/>
|
||
|
|
{/if}
|
||
|
|
{/each}
|
||
|
|
{/if}
|
||
|
|
|
||
|
|
{#each doc.sections as section (section.title)}
|
||
|
|
<h2>{section.title}</h2>
|
||
|
|
{#each section.body ?? [] as paragraph}
|
||
|
|
<p>{paragraph}</p>
|
||
|
|
{/each}
|
||
|
|
{#if section.bullets}
|
||
|
|
<ul>
|
||
|
|
{#each section.bullets as item}
|
||
|
|
<li>{item}</li>
|
||
|
|
{/each}
|
||
|
|
</ul>
|
||
|
|
{/if}
|
||
|
|
{#if section.table}
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Name</th>
|
||
|
|
<th>Purpose</th>
|
||
|
|
<th>Notes</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
{#each section.table as row (row.name)}
|
||
|
|
<tr>
|
||
|
|
<td><code>{row.name}</code></td>
|
||
|
|
<td>{row.purpose}</td>
|
||
|
|
<td>{row.notes ?? ''}</td>
|
||
|
|
</tr>
|
||
|
|
{/each}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
{/if}
|
||
|
|
{#if section.code}
|
||
|
|
<CodeBlock
|
||
|
|
code={section.code.code}
|
||
|
|
lang={section.code.lang ?? 'ts'}
|
||
|
|
title={section.code.title}
|
||
|
|
/>
|
||
|
|
{/if}
|
||
|
|
{/each}
|
||
|
|
|
||
|
|
{#if doc.commonMistakes?.length}
|
||
|
|
<h2>Common mistakes</h2>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Mistake</th>
|
||
|
|
<th>Why it hurts</th>
|
||
|
|
<th>Correct pattern</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
{#each doc.commonMistakes as row (row.name)}
|
||
|
|
<tr>
|
||
|
|
<td><code>{row.name}</code></td>
|
||
|
|
<td>{row.purpose}</td>
|
||
|
|
<td>{row.notes ?? ''}</td>
|
||
|
|
</tr>
|
||
|
|
{/each}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
{/if}
|
||
|
|
|
||
|
|
<h2>Testing</h2>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Target</th>
|
||
|
|
<th>Purpose</th>
|
||
|
|
<th>Notes</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
{#each doc.tests as test (test.name)}
|
||
|
|
<tr>
|
||
|
|
<td><code>{test.name}</code></td>
|
||
|
|
<td>{test.purpose}</td>
|
||
|
|
<td>{test.notes ?? ''}</td>
|
||
|
|
</tr>
|
||
|
|
{/each}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
|
||
|
|
<AiAgentsBox
|
||
|
|
intro={`Before editing ${doc.alias}, inspect the real exports and types. Do not invent factories, methods, logger shapes or undocumented behavior from examples alone.`}
|
||
|
|
rows={aiAgentRows}
|
||
|
|
/>
|
||
|
|
|
||
|
|
<PageNav />
|
||
|
|
</article>
|