forked from Rosetta/landing
Добавлена докуметация по RCC
This commit is contained in:
@@ -10,6 +10,7 @@ const browserRoutes = [
|
||||
'privacy',
|
||||
'proto',
|
||||
'proto/docs',
|
||||
'rcc',
|
||||
'support',
|
||||
'terms',
|
||||
];
|
||||
|
||||
@@ -8,10 +8,16 @@
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://rosetta.im/proto/</loc>
|
||||
<lastmod>2026-07-30</lastmod>
|
||||
<lastmod>2026-08-01</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://rosetta.im/rcc/</loc>
|
||||
<lastmod>2026-08-01</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://rosetta.im/proto/docs/</loc>
|
||||
<lastmod>2026-07-31</lastmod>
|
||||
|
||||
@@ -18,6 +18,9 @@ const ProtoPage = lazy(() =>
|
||||
const ProtoDocsPage = lazy(() =>
|
||||
import('./pages/ProtoPage').then((module) => ({ default: module.ProtoDocsPage })),
|
||||
);
|
||||
const RccPage = lazy(() =>
|
||||
import('./pages/RccPage').then((module) => ({ default: module.RccPage })),
|
||||
);
|
||||
const SupportPage = lazy(() =>
|
||||
import('./pages/SupportPage').then((module) => ({ default: module.SupportPage })),
|
||||
);
|
||||
@@ -87,6 +90,7 @@ export default function App() {
|
||||
<Route path="/encryption" element={<EncryptionPage />} />
|
||||
<Route path="/proto" element={<ProtoPage />} />
|
||||
<Route path="/proto/docs" element={<ProtoDocsPage />} />
|
||||
<Route path="/rcc" element={<RccPage />} />
|
||||
<Route path="/support" element={<SupportPage />} />
|
||||
<Route path="/privacy" element={<PrivacyPage />} />
|
||||
<Route path="/terms" element={<TermsPage />} />
|
||||
|
||||
@@ -39,6 +39,9 @@ export function SiteFooter() {
|
||||
<Anchor component={Link} to="/proto" c="dimmed" size="sm">
|
||||
Proto
|
||||
</Anchor>
|
||||
<Anchor component={Link} to="/rcc" c="dimmed" size="sm">
|
||||
RCC
|
||||
</Anchor>
|
||||
<Anchor component={Link} to="/support" c="dimmed" size="sm">
|
||||
Support
|
||||
</Anchor>
|
||||
|
||||
@@ -26,6 +26,11 @@
|
||||
font-weight: 650;
|
||||
}
|
||||
|
||||
.important {
|
||||
color: light-dark(var(--mantine-color-orange-8), var(--mantine-color-orange-3));
|
||||
font-weight: 650;
|
||||
}
|
||||
|
||||
.layerExamples {
|
||||
min-width: 0;
|
||||
margin: 18px 0 24px;
|
||||
@@ -40,9 +45,13 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.docsLinks {
|
||||
margin-top: 44px;
|
||||
gap: 28px;
|
||||
}
|
||||
|
||||
.docsLink {
|
||||
display: inline-block;
|
||||
margin-top: 44px;
|
||||
font-size: var(--mantine-font-size-sm);
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
|
||||
@@ -517,6 +517,57 @@ export class RccGeneratedPacketRegistry {
|
||||
</Code>
|
||||
</LegalSection>
|
||||
|
||||
<LegalSection title="RCC: one schema contract, two generation modes">
|
||||
<LegalText>
|
||||
Rosetta Code Compiler (RCC) is the build-time compiler behind the protocol.
|
||||
It reads every <Code>layer.N.yml</Code> snapshot, turns the YAML into a
|
||||
typed protocol model, validates that the history is safe, and emits source
|
||||
code for the selected language. Applications import generated models and
|
||||
codecs; they do not parse the YAML at runtime.
|
||||
</LegalText>
|
||||
<Code block className={classes.protoCode}>
|
||||
{`proto/layer.*.yml
|
||||
│
|
||||
├─ parse packets, reusable types, enums and comments
|
||||
├─ validate references, required fields and stable field IDs
|
||||
│
|
||||
├─ mode=server → all layers + version-aware codecs + registry
|
||||
└─ mode=client → latest layer + latest codecs + version constant`}
|
||||
</Code>
|
||||
<LegalList>
|
||||
<List.Item>
|
||||
<strong>Server generation</strong> preserves the protocol timeline.
|
||||
Java codecs receive the negotiated layer, include only fields active in
|
||||
that layer, and expose the compiled minimum and maximum versions.
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<strong>Client generation</strong>{' '}
|
||||
<Text component="span" className={classes.important}>
|
||||
selects the highest layer and creates the current packet, type, enum,
|
||||
codec, and registry sources without carrying historical shapes into
|
||||
the application.
|
||||
</Text>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<strong>Schema validation</strong> fails the build for unknown types or
|
||||
unsafe field-ID reuse, so incompatible protocol edits are caught before
|
||||
generated sources reach a server or client package.
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<strong>Generated documentation</strong> carries schema comments into
|
||||
Javadoc or TSDoc, including field direction, wire type, optionality, and
|
||||
accessor contracts.
|
||||
</List.Item>
|
||||
</LegalList>
|
||||
<LegalText>
|
||||
The RCC guide includes separate client and version-aware server examples.{' '}
|
||||
<Text component="span" className={classes.important}>
|
||||
Run <Code>npx rcc --list-languages</Code> for the authoritative list of
|
||||
language targets in the installed compiler version.
|
||||
</Text>
|
||||
</LegalText>
|
||||
</LegalSection>
|
||||
|
||||
<LegalSection title="How an RCC YAML layer is structured">
|
||||
<LegalText>
|
||||
RCC reads versioned files named <Code>layer.N.yml</Code>. The top-level
|
||||
@@ -664,9 +715,14 @@ packet field 1 · INT8 · SUCCESS (0)`}
|
||||
</LegalText>
|
||||
</LegalSection>
|
||||
|
||||
<Anchor component={Link} to="/proto/docs" className={classes.docsLink}>
|
||||
See docs of PROTO →
|
||||
</Anchor>
|
||||
<Group className={classes.docsLinks}>
|
||||
<Anchor component={Link} to="/proto/docs" className={classes.docsLink}>
|
||||
See docs of PROTO →
|
||||
</Anchor>
|
||||
<Anchor component={Link} to="/rcc" className={classes.docsLink}>
|
||||
Learn RCC →
|
||||
</Anchor>
|
||||
</Group>
|
||||
</LegalPage>
|
||||
</>
|
||||
);
|
||||
|
||||
114
src/pages/RccPage.module.css
Normal file
114
src/pages/RccPage.module.css
Normal file
@@ -0,0 +1,114 @@
|
||||
.code {
|
||||
margin: 18px 0;
|
||||
padding: 16px;
|
||||
border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-5));
|
||||
border-radius: var(--mantine-radius-xs);
|
||||
background: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-7));
|
||||
color: light-dark(var(--mantine-color-gray-8), var(--mantine-color-dark-0));
|
||||
font-size: 12px;
|
||||
line-height: 1.65;
|
||||
overflow-x: auto;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.pipeline {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto minmax(0, 1fr);
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
margin: 22px 0;
|
||||
}
|
||||
|
||||
.pipeline > span:nth-child(odd) {
|
||||
padding: 14px;
|
||||
border: 1px solid light-dark(var(--mantine-color-blue-2), var(--mantine-color-blue-9));
|
||||
border-radius: var(--mantine-radius-xs);
|
||||
background: light-dark(var(--mantine-color-blue-0), rgba(25, 113, 194, 0.12));
|
||||
color: light-dark(var(--mantine-color-blue-9), var(--mantine-color-blue-1));
|
||||
font-size: var(--mantine-font-size-sm);
|
||||
font-weight: 650;
|
||||
line-height: 1.45;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pipeline > span:nth-child(even) {
|
||||
color: var(--mantine-color-blue-6);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.step {
|
||||
display: grid;
|
||||
grid-template-columns: 34px minmax(0, 1fr);
|
||||
gap: 16px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.step:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.stepNumber {
|
||||
display: grid;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
place-items: center;
|
||||
border-radius: 50%;
|
||||
background: var(--mantine-color-blue-6);
|
||||
color: var(--mantine-color-white);
|
||||
font-size: var(--mantine-font-size-sm);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.stepBody {
|
||||
min-width: 0;
|
||||
padding-bottom: 24px;
|
||||
border-bottom: 1px solid light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-5));
|
||||
}
|
||||
|
||||
.step:last-child .stepBody {
|
||||
padding-bottom: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.subheading {
|
||||
margin: 3px 0 12px;
|
||||
color: light-dark(var(--mantine-color-dark-8), var(--mantine-color-dark-0));
|
||||
font-size: 17px;
|
||||
font-weight: 650;
|
||||
}
|
||||
|
||||
.important {
|
||||
color: light-dark(var(--mantine-color-orange-8), var(--mantine-color-orange-3));
|
||||
font-weight: 650;
|
||||
}
|
||||
|
||||
.note {
|
||||
margin: 18px 0;
|
||||
border: 1px solid light-dark(var(--mantine-color-orange-3), var(--mantine-color-orange-9));
|
||||
border-left: 3px solid var(--mantine-color-orange-6);
|
||||
background: light-dark(var(--mantine-color-orange-0), rgba(253, 126, 20, 0.1));
|
||||
color: light-dark(var(--mantine-color-orange-9), var(--mantine-color-orange-2));
|
||||
}
|
||||
|
||||
@media (max-width: 48em) {
|
||||
.pipeline {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.pipeline > span:nth-child(even) {
|
||||
transform: rotate(90deg);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 36em) {
|
||||
.step {
|
||||
grid-template-columns: 28px minmax(0, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.stepNumber {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
}
|
||||
239
src/pages/RccPage.tsx
Normal file
239
src/pages/RccPage.tsx
Normal file
@@ -0,0 +1,239 @@
|
||||
import { Anchor, Box, Code, List, Paper, Text, Title } from '@mantine/core';
|
||||
import type { ReactNode } from 'react';
|
||||
import {
|
||||
LegalList,
|
||||
LegalPage,
|
||||
LegalSection,
|
||||
LegalText,
|
||||
} from '../components/LegalPage/LegalPage';
|
||||
import { SEO } from '../components/SEO/SEO';
|
||||
import classes from './RccPage.module.css';
|
||||
|
||||
const GITEA_REPOSITORY = 'https://git.rosetta.im/Rosetta/rcc';
|
||||
|
||||
function TechnicalCode({ children }: { children: string }) {
|
||||
return (
|
||||
<Code block className={classes.code}>
|
||||
{children}
|
||||
</Code>
|
||||
);
|
||||
}
|
||||
|
||||
function Step({ number, title, children }: { number: number; title: string; children: ReactNode }) {
|
||||
return (
|
||||
<Box className={classes.step}>
|
||||
<Text className={classes.stepNumber}>{number}</Text>
|
||||
<Box className={classes.stepBody}>
|
||||
<Title order={3} className={classes.subheading}>
|
||||
{title}
|
||||
</Title>
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export function RccPage() {
|
||||
return (
|
||||
<>
|
||||
<SEO
|
||||
title="Rosetta Code Compiler (RCC)"
|
||||
description="Install RCC and generate validated protocol models, codecs, and registries from versioned Rosetta YAML schemas."
|
||||
canonical="https://rosetta.im/rcc/"
|
||||
keywords="RCC, Rosetta Code Compiler, code generation, protocol codecs, YAML protocol"
|
||||
/>
|
||||
<LegalPage eyebrow="Developer tooling" title="Rosetta Code Compiler">
|
||||
<LegalText lead>
|
||||
RCC compiles Rosetta's versioned YAML protocol into typed models, codecs,
|
||||
and packet registries.{' '}
|
||||
<Text component="span" className={classes.important}>
|
||||
A server build can retain the complete protocol history; a client build
|
||||
stays small by generating only the latest layer.
|
||||
</Text>
|
||||
</LegalText>
|
||||
|
||||
<LegalSection title="What RCC produces">
|
||||
<LegalText>
|
||||
RCC treats <Code>proto/layer.*.yml</Code> as the protocol's source of
|
||||
truth. Before writing code, it resolves primitive, enum, and reusable type
|
||||
references and rejects incompatible reuse of a field ID between layers.
|
||||
</LegalText>
|
||||
<Box className={classes.pipeline}>
|
||||
<Text component="span">Versioned YAML schemas</Text>
|
||||
<Text component="span" aria-hidden="true">→</Text>
|
||||
<Text component="span">Parse + validate</Text>
|
||||
<Text component="span" aria-hidden="true">→</Text>
|
||||
<Text component="span">Models + codecs + registry</Text>
|
||||
</Box>
|
||||
<LegalList>
|
||||
<List.Item>
|
||||
Packets become typed packet classes; reusable schema types become model
|
||||
classes; enums preserve their numeric wire values.
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
Codecs encode and decode TLV fields and verify required fields before
|
||||
encoding and after decoding.
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
The generated registry maps packet IDs to codecs and exposes the
|
||||
compiled protocol version or version range.
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
YAML comments become Javadoc or TSDoc for generated declarations and
|
||||
accessors.
|
||||
</List.Item>
|
||||
</LegalList>
|
||||
</LegalSection>
|
||||
|
||||
<LegalSection title="Install RCC from Rosetta Gitea">
|
||||
<LegalText>
|
||||
Add Rosetta's npm package registry to the project, then install RCC. The
|
||||
registry setting can live in a project-level <Code>.npmrc</Code> so CI and
|
||||
local builds resolve the same compiler package.
|
||||
</LegalText>
|
||||
<TechnicalCode>{`# .npmrc
|
||||
registry=https://git.rosetta.im/api/packages/Rosetta/npm/
|
||||
|
||||
# install the compiler
|
||||
npm install rcc
|
||||
|
||||
# query languages from the installed RCC version
|
||||
npx rcc --list-languages
|
||||
|
||||
# inspect the rest of the CLI
|
||||
npx rcc --help`}</TechnicalCode>
|
||||
<LegalText>
|
||||
RCC source is hosted in the{' '}
|
||||
<Anchor href={GITEA_REPOSITORY} target="_blank" rel="noreferrer">
|
||||
Rosetta/rcc Gitea repository
|
||||
</Anchor>
|
||||
.{' '}
|
||||
<Text component="span" className={classes.important}>
|
||||
Pin the dependency version in the project lockfile so generated output
|
||||
remains reproducible.
|
||||
</Text>
|
||||
</LegalText>
|
||||
</LegalSection>
|
||||
|
||||
<LegalSection title="Generate from schemas, step by step">
|
||||
<Step number={1} title="Create versioned schema layers">
|
||||
<LegalText>
|
||||
Put complete protocol snapshots in one directory and name them
|
||||
<Code> layer.N.yml</Code>. Increment the top-level version, keep packet
|
||||
and field IDs stable, and repeat definitions that remain part of the
|
||||
protocol.
|
||||
</LegalText>
|
||||
<TechnicalCode>{`proto/
|
||||
├── layer.1.yml
|
||||
├── layer.2.yml
|
||||
└── layer.3.yml`}</TechnicalCode>
|
||||
</Step>
|
||||
|
||||
<Step number={2} title="Choose client or server output">
|
||||
<LegalText>
|
||||
Use <Code>client</Code> for the current application package. RCC selects
|
||||
the highest schema version. Use <Code>server</Code> when the runtime must
|
||||
decode connections negotiated on older supported layers. Full
|
||||
multi-version codec generation is currently implemented by the Java
|
||||
backend.
|
||||
</LegalText>
|
||||
</Step>
|
||||
|
||||
<Step number={3} title="Generate Java sources">
|
||||
<LegalText>
|
||||
Server generation combines all layers and emits version-aware codecs,
|
||||
models, enums, and a registry with <Code>MIN_VERSION</Code> and
|
||||
<Code> MAX_VERSION</Code>.
|
||||
</LegalText>
|
||||
<TechnicalCode>{`npx rcc \\
|
||||
--mode server \\
|
||||
--lang java \\
|
||||
--protoDir ./proto \\
|
||||
--outDir ./server/src/generated/java \\
|
||||
--basePackage im.rosetta.network \\
|
||||
--clean`}</TechnicalCode>
|
||||
<LegalText>
|
||||
For a Java client, change the mode and output directory. The generated
|
||||
sources describe only the latest layer.
|
||||
</LegalText>
|
||||
<TechnicalCode>{`npx rcc \\
|
||||
--mode client \\
|
||||
--lang java \\
|
||||
--protoDir ./proto \\
|
||||
--outDir ./client/src/generated/java \\
|
||||
--basePackage im.rosetta.network \\
|
||||
--clean`}</TechnicalCode>
|
||||
</Step>
|
||||
|
||||
<Step number={4} title="Generate TypeScript sources">
|
||||
<LegalText>
|
||||
TypeScript is the current latest-layer client target. It produces
|
||||
models, enums, codecs, and <Code>RccGeneratedPacketRegistry.VERSION</Code>.
|
||||
</LegalText>
|
||||
<TechnicalCode>{`npx rcc \\
|
||||
--mode client \\
|
||||
--lang typescript \\
|
||||
--protoDir ./proto \\
|
||||
--outDir ./client/src/generated/protocol \\
|
||||
--clean`}</TechnicalCode>
|
||||
<Paper className={classes.note} radius="sm" p="md">
|
||||
<Text size="sm" lh={1.7}>
|
||||
Always run <Code>npx rcc --list-languages</Code> before configuring a
|
||||
generator. The installed compiler's output is the source of truth
|
||||
for available language targets.
|
||||
</Text>
|
||||
</Paper>
|
||||
</Step>
|
||||
|
||||
<Step number={5} title="Run all targets from one prebuild config">
|
||||
<LegalText>
|
||||
Keep client and server generation together in
|
||||
<Code> rcc-prebuild.yml</Code>. Paths are resolved relative to the
|
||||
config file; <Code>clean: true</Code> clears only each configured output
|
||||
directory.
|
||||
</LegalText>
|
||||
<TechnicalCode>{`watch: false
|
||||
protoDir: ./proto
|
||||
clean: true
|
||||
|
||||
compilers:
|
||||
- name: TypeScript client
|
||||
mode: client
|
||||
lang: typescript
|
||||
output: ./client/src/generated/protocol
|
||||
|
||||
- name: Java server
|
||||
mode: server
|
||||
lang: java
|
||||
output: ./server/src/generated/java
|
||||
basePackage: im.rosetta.network`}</TechnicalCode>
|
||||
<TechnicalCode>{`npx rcc -f ./rcc-prebuild.yml`}</TechnicalCode>
|
||||
</Step>
|
||||
|
||||
<Step number={6} title="Compile and package the generated sources">
|
||||
<LegalText>
|
||||
Add the output directory to the language build, then run generation
|
||||
before compilation in local development and CI. RCC writes source
|
||||
files; the surrounding Gradle, npm, or application build is responsible
|
||||
for compiling and publishing the final server or client package.
|
||||
</LegalText>
|
||||
</Step>
|
||||
</LegalSection>
|
||||
|
||||
<LegalSection title="CLI reference">
|
||||
<TechnicalCode>{`npx rcc --mode <client|server> [options]
|
||||
npx rcc -f <filename.yml>
|
||||
npx rcc --list-languages
|
||||
|
||||
--mode, -m client | server
|
||||
--lang, -l language returned by --list-languages
|
||||
--protoDir, -p schema directory (default: ./proto)
|
||||
--outDir, -o generated source directory (default: ./generated)
|
||||
--basePackage, -b Java base package (default: im.rosetta.generated)
|
||||
--clean clean the output directory before generation
|
||||
--file, -f prebuild YAML config`}</TechnicalCode>
|
||||
</LegalSection>
|
||||
</LegalPage>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user