mtcute/tl-reference/src/pages/index.tsx
2021-08-05 20:38:24 +03:00

355 lines
13 KiB
TypeScript

import React from 'react'
import { Link as MuiLink, Typography } from '@material-ui/core'
import { Page, usePageStyles } from '../components/page'
import { graphql, Link } from 'gatsby'
interface Data {
mtClasses: { totalCount: number }
classes: { totalCount: number }
mtMethods: { totalCount: number }
methods: { totalCount: number }
mtUnions: { totalCount: number }
unions: { totalCount: number }
clsWithDesc: { totalCount: number }
clsWithoutDesc: { totalCount: number }
argWithDesc: {
totalCount: number
nodes: { arguments: { description: string | null }[] }[]
}
argWithoutDesc: {
totalCount: number
nodes: { arguments: { description: string | null }[] }[]
}
currentTlSchema: {
layer: string
}
historySchemas: { totalCount: number }
historyTypes: { totalCount: number }
}
function countMissingDescriptionArguments(
item: Data['argWithDesc'],
eqNull: boolean
) {
let count = 0
item.nodes.forEach((node) =>
node.arguments?.forEach((arg) => {
if (eqNull ? arg.description === null : arg.description !== null)
count += 1
})
)
item.totalCount = count
}
export default function IndexPage({ data }: { data: Data }) {
const classes = usePageStyles()
countMissingDescriptionArguments(data.argWithoutDesc, true)
countMissingDescriptionArguments(data.argWithDesc, false)
return (
<Page
toc={[
{ id: 'tl-reference', title: 'TL Reference' },
{ id: 'types', title: 'Types' },
{ id: 'core-types', title: 'Core types' },
{ id: 'statistics', title: 'Statistics' },
]}
>
<div className={classes.heading1}>
<Typography variant="h3" id="tl-reference">
TL Reference
</Typography>
<Typography variant="body2">
layer {data.currentTlSchema.layer}
</Typography>
</div>
<Typography variant="body1" className={classes.paragraph}>
This web application allows easily browsing through myriads of
TL objects and reading through their documentation. Unlike{' '}
<MuiLink href="//core.telegram.org/schema">
official documentation
</MuiLink>
, this app has simpler structure, search and nice interface.
</Typography>
<Typography variant="body1" className={classes.paragraph}>
Even though this reference is intended to be used with{' '}
<MuiLink href="//github.com/mtcute/mtcute">MTCute</MuiLink>{' '}
library, the objects are common to any other MTProto library.
The key difference is that MTCute (and this reference) use{' '}
<code>camelCase</code> for arguments, while the original schema
and some other libraries use <code>snake_case</code>.
</Typography>
<Typography variant="h4" id="types" className={classes.heading}>
Types
</Typography>
<Typography variant="body1" className={classes.paragraph}>
In TL, there are 3 main groups of types: <i>Classes</i>,{' '}
<i>Methods</i> and Unions (officially they are called{' '}
<i>constructors</i>, <i>methods</i> and <i>types</i>{' '}
respectively).
</Typography>
<Typography variant="body1" className={classes.paragraph}>
<i>Classes</i> and <i>Methods</i> are simply typed objects, that
contain some data. The only difference is that Methods are used
in RPC calls (i.e. they are sent to the server), and Classes are
used inside methods, or sent by the server back (either as an
RPC result, or as an update).
</Typography>
<Typography variant="body1" className={classes.paragraph}>
<i>Union</i> is a type that combines multiple <i>Classes</i> in
one type. In some languages, this can be represented as an
abstract class. <i>Unions</i> are sent by Telegram in response
to RPC results, as well as they are used as arguments for other{' '}
<i>Classes</i> or <i>Methods</i>.
</Typography>
<Typography variant="body1" className={classes.paragraph}>
In TL, every single <i>Class</i> is a part of exactly one{' '}
<i>Union</i>, and every <i>Union</i> contains at least one{' '}
<i>Class</i>.
</Typography>
<Typography variant="body1" className={classes.paragraph}>
In MTCute, all types are exposed as a namespace <code>tl</code>{' '}
of package <code>@mtcute/tl</code>. By design, we use immutable
plain objects with type discriminator to represent{' '}
<i>Classes</i> and <i>Methods</i>, and TypeScript unions to
represent <i>Unions</i>.<br />
To differentiate between different groups of types, we use
different naming for each of them:
</Typography>
<Typography
variant="body1"
className={classes.paragraph}
component="ul"
>
<li>
<i>Classes</i> are prefixed with <code>Raw</code> (e.g.{' '}
<code>tl.RawMessage</code>)
</li>
<li>
Additionally, <i>Methods</i> are postfixed with{' '}
<code>Request</code> and (e.g.{' '}
<code>tl.RawGetMessageRequest</code>)
</li>
<li>
Finally, <i>Unions</i> are simply prefixed with{' '}
<code>Type</code> (e.g. <code>tl.TypeUser</code>)
</li>
</Typography>
<Typography
variant="h4"
id="core-types"
className={classes.heading}
>
Core types
</Typography>
<Typography variant="body1" className={classes.paragraph}>
Core types are basic built-in types that are used in TL schema.
Quick reference:
</Typography>
<Typography
variant="body1"
className={classes.paragraph}
component="ul"
>
<li>
<code>number</code>: 32-bit signed integer
</li>
<li>
<code>Long</code>: 64-bit signed integer
</li>
<li>
<code>Int128</code>: 128-bit signed integer (only used for
MTProto)
</li>
<li>
<code>Int256</code>: 256-bit signed integer (only used for
MTProto)
</li>
<li>
<code>Double</code>: 64-bit floating point value
</li>
<li>
<code>string</code>: UTF-16 string (strings in JS are also
UTF-16)
</li>
<li>
<code>Buffer</code>: Byte array of a known size
</li>
<li>
<code>boolean</code>: One-byte boolean value (true/false)
</li>
<li>
<code>true</code>: Zero-size <code>true</code> value, used
for TL flags
</li>
<li>
<code>any</code>: Any other TL object (usually another
method)
</li>
<li>
<code>T[]</code>: Array of <code>T</code>
</li>
<li>
<code>TlFlags</code>: 32-bit signed value representing
object's TL flags
</li>
</Typography>
<Typography
variant="h4"
className={classes.heading}
id="statistics"
>
Statistics
</Typography>
<Typography
variant="body1"
className={classes.paragraph}
component="ul"
>
<li>
Generated from layer <b>{data.currentTlSchema.layer}</b>{' '}
</li>
<li>
Current schema contains{' '}
<b>
{data.methods.totalCount +
data.classes.totalCount +
data.unions.totalCount}
</b>{' '}
types (+{' '}
<b>
{data.mtClasses.totalCount +
data.mtMethods.totalCount +
data.mtUnions.totalCount}
</b>{' '}
for MTProto)
</li>
<li>
Current schema contains <b>{data.classes.totalCount}</b>{' '}
classes (+ <b>{data.mtClasses.totalCount}</b> for MTProto)
</li>
<li>
Current schema contains <b>{data.methods.totalCount}</b>{' '}
methods (+ <b>{data.mtMethods.totalCount}</b> for MTProto)
</li>
<li>
Current schema contains <b>{data.unions.totalCount}</b>{' '}
unions (+ <b>{data.mtUnions.totalCount}</b> for MTProto)
</li>
<li>
Description coverage:{' '}
{(function () {
const totalWith =
data.argWithDesc.totalCount +
data.clsWithDesc.totalCount
const totalWithout =
data.argWithoutDesc.totalCount +
data.clsWithoutDesc.totalCount
const total = totalWith + totalWithout
return (
<>
<b>
{Math.round((totalWith / total) * 10000) /
100}
%
</b>{' '}
(out of {total} items, {totalWithout}{' '}
<MuiLink component={Link} to="/no-description">
don't have description
</MuiLink>{' '}
- that is {data.clsWithoutDesc.totalCount} types
and {data.argWithoutDesc.totalCount} arguments)
</>
)
})()}
</li>
<li>
History is available for{' '}
<MuiLink component={Link} to="/history">
<b>{data.historySchemas.totalCount}</b> schemas
</MuiLink>{' '}
and <b>{data.historyTypes.totalCount}</b> types
</li>
</Typography>
</Page>
)
}
export const query = graphql`
query {
mtClasses: allTlObject(
filter: { type: { eq: "class" }, prefix: { eq: "mtproto/" } }
) {
totalCount
}
classes: allTlObject(
filter: { type: { eq: "class" }, prefix: { ne: "mtproto/" } }
) {
totalCount
}
mtMethods: allTlObject(
filter: { type: { eq: "method" }, prefix: { eq: "mtproto/" } }
) {
totalCount
}
methods: allTlObject(
filter: { type: { eq: "method" }, prefix: { ne: "mtproto/" } }
) {
totalCount
}
mtUnions: allTlObject(
filter: { type: { eq: "union" }, prefix: { eq: "mtproto/" } }
) {
totalCount
}
unions: allTlObject(
filter: { type: { eq: "union" }, prefix: { ne: "mtproto/" } }
) {
totalCount
}
currentTlSchema {
layer
}
clsWithDesc: allTlObject(filter: { description: { ne: null } }) {
totalCount
}
clsWithoutDesc: allTlObject(filter: { description: { eq: null } }) {
totalCount
}
argWithDesc: allTlObject(
filter: { arguments: { elemMatch: { description: { ne: null } } } }
) {
totalCount
nodes {
arguments {
description
}
}
}
argWithoutDesc: allTlObject(
filter: { arguments: { elemMatch: { description: { eq: null } } } }
) {
totalCount
nodes {
arguments {
description
}
}
}
historySchemas: allHistoryJson {
totalCount
}
historyTypes: allTypesJson {
totalCount
}
}
`