build(docs): api reference generation improvements

- added readme in each package
- updated typedoc, fixed related issues
- use @link instead of @see
- moved configs to typedoc.js, improved exclusion of unneeded stuff
- custom plugin for typedoc for cross-package references
- preparing to move documentation to separate repository
This commit is contained in:
teidesu 2022-08-24 23:37:26 +03:00
parent b08ec342e5
commit 390b65f796
100 changed files with 997 additions and 302 deletions

View file

View file

@ -9,7 +9,8 @@
"test-all": "pnpm run -r test",
"lint": "eslint \"packages/**/*.ts\"",
"format": "prettier --write \"packages/**/*.ts\"",
"publish-all": "node scripts/publish.js all"
"publish-all": "node scripts/publish.js all",
"docs": "pnpm run -r docs"
},
"dependencies": {
"node-gyp": "^9.0.0"
@ -29,7 +30,8 @@
"node-forge": "^1.3.1",
"prettier": "^2.6.2",
"ts-node": "^10.8.1",
"typedoc": "^0.23.2",
"typedoc": "^0.23.10",
"typedoc-plugin-coverage": "^2.0.0",
"typescript": "^4.7.4",
"nyc": "^15.1.0",
"rimraf": "^3.0.2",

View file

@ -8,7 +8,7 @@
"main": "src/index.ts",
"scripts": {
"test": "mocha -r ts-node/register \"tests/**/*.spec.ts\"",
"docs": "npx typedoc",
"docs": "typedoc",
"build": "tsc"
},
"dependencies": {

View file

@ -464,7 +464,7 @@ on(name: '${type.typeName}', handler: ((upd: ${type.updateType}) => void)): this
output.write('}\n')
output.write(
'/** @internal */\nexport class TelegramClient extends BaseTelegramClient {\n'
'\nexport class TelegramClient extends BaseTelegramClient {\n'
)
state.fields.forEach(({ code }) => output.write(`protected ${code}\n`))

View file

@ -467,8 +467,8 @@ export interface TelegramClient extends BaseTelegramClient {
* Errors that were encountered while calling {@link start}
* and `then` will be emitted as usual, and can be caught with {@link onError}
*
* @param params Parameters to be passed to {@link params}
* @param then Function to be called after {@link start} returns
* @param params Parameters to be passed to {@link TelegramClient.start}
* @param then Function to be called after {@link TelegramClient.start} returns
*/
run(
params: Parameters<TelegramClient['start']>[0],
@ -673,7 +673,7 @@ export interface TelegramClient extends BaseTelegramClient {
* to show a GUI alert of some kind.
* Defaults to `console.log`.
*
* This method is called *before* {@link code}.
* This method is called *before* {@link TelegramClient.start.params.code}.
*
* @param code
*/
@ -1350,7 +1350,7 @@ export interface TelegramClient extends BaseTelegramClient {
params?: Parameters<TelegramClient['getChatMembers']>[1] & {
/**
* Chunk size, which will be passed as `limit` parameter
* to {@link getChatMembers}. Usually you shouldn't care about this.
* to {@link TelegramClient.getChatMembers}. Usually you shouldn't care about this.
*
* Defaults to `200`
*/
@ -2538,8 +2538,7 @@ export interface TelegramClient extends BaseTelegramClient {
reverse?: boolean
/**
* Chunk size, which will be passed as `limit` parameter
* to {@link getHistory}. Usually you shouldn't care about this.
* Chunk size. Usually you shouldn't care about this.
*
* Defaults to `100`
*/

View file

@ -1,3 +1,4 @@
/** @hidden */
export {
MemoryStorage,
JsonFileStorage,

View file

@ -9,8 +9,8 @@ import { User } from '../../types'
* Errors that were encountered while calling {@link start}
* and `then` will be emitted as usual, and can be caught with {@link onError}
*
* @param params Parameters to be passed to {@link params}
* @param then Function to be called after {@link start} returns
* @param params Parameters to be passed to {@link TelegramClient.start}
* @param then Function to be called after {@link TelegramClient.start} returns
* @internal
*/
export function run(

View file

@ -113,7 +113,7 @@ export async function start(
* to show a GUI alert of some kind.
* Defaults to `console.log`.
*
* This method is called *before* {@link code}.
* This method is called *before* {@link TelegramClient.start.params.code}.
*
* @param code
*/

View file

@ -19,7 +19,7 @@ export async function* iterChatMembers(
params?: Parameters<TelegramClient['getChatMembers']>[1] & {
/**
* Chunk size, which will be passed as `limit` parameter
* to {@link getChatMembers}. Usually you shouldn't care about this.
* to {@link TelegramClient.getChatMembers}. Usually you shouldn't care about this.
*
* Defaults to `200`
*/

View file

@ -70,8 +70,7 @@ export async function* getHistory(
reverse?: boolean
/**
* Chunk size, which will be passed as `limit` parameter
* to {@link getHistory}. Usually you shouldn't care about this.
* Chunk size. Usually you shouldn't care about this.
*
* Defaults to `100`
*/

View file

@ -6,7 +6,7 @@ import { fileIdToInputDocument, fileIdToInputPhoto } from '@mtcute/file-id'
import { extractFileName } from '../../../utils/file-utils'
import { MtArgumentError } from '../../errors'
interface BaseInputInlineResult {
export interface BaseInputInlineResult {
/**
* Unique ID of the result
*/

View file

@ -2,7 +2,7 @@ import { tl } from '@mtcute/tl'
import type { InlineKeyboardMarkup, ReplyKeyboardMarkup } from './keyboards'
type ButtonLike = tl.TypeKeyboardButton | false | null | undefined | void
export type ButtonLike = tl.TypeKeyboardButton | false | null | undefined | void
/**
* Builder for bot keyboards

View file

@ -0,0 +1 @@
export * from './discard-reason'

View file

@ -1,3 +1,4 @@
export * from './utils'
export * from './file-location'
export * from './uploaded-file'
export * from './web-document'

View file

@ -7,6 +7,7 @@ export * from './peers'
export * from './misc'
export * from './updates'
export * from './conversation'
export * from './calls'
export * from './errors'
export * from './parser'

View file

@ -5,7 +5,7 @@ import { InputFileLike } from '../files'
import { Venue } from './venue'
import { FormattedString } from '../parser'
interface CaptionMixin {
export interface CaptionMixin {
/**
* Caption of the media
*/
@ -18,7 +18,7 @@ interface CaptionMixin {
entities?: tl.TypeMessageEntity[]
}
interface FileMixin {
export interface FileMixin {
/**
* File to be sent
*/
@ -564,7 +564,7 @@ export type InputMediaLike =
| tl.TypeInputMedia
export namespace InputMedia {
type OmitTypeAndFile<
export type OmitTypeAndFile<
T extends InputMediaLike,
K extends keyof T = never
> = Omit<T, 'type' | 'file' | K>

View file

@ -190,7 +190,7 @@ export class WebPage {
*
* Seems that this is only used for `document` previews.
*
* Can be a {@link Animation}, {@link Photo}, {@link Video},
* Can be a {@link Photo}, {@link Video},
* {@link Audio}, {@link Document}.
*/
get document(): RawDocument | null {

View file

@ -4,7 +4,7 @@ import { Photo } from '../media'
import {
_callDiscardReasonFromTl,
CallDiscardReason,
} from '../calls/discard-reason'
} from '../calls'
import { Message } from './message'
export namespace MessageAction {
@ -200,7 +200,7 @@ export namespace MessageAction {
/**
* A user is in proximity of another user
* (see [Proximity alerts]{https://core.telegram.org/api/live-location#proximity-alert})
* (see [Proximity alerts](https://core.telegram.org/api/live-location#proximity-alert))
*/
export interface ActionGeoProximity {
readonly type: 'geo_proximity'

View file

@ -106,7 +106,7 @@ export class Message {
readonly _peers: PeersIndex,
/**
* Whether the message is scheduled.
* If it is, then its {@link date} is set to future.
* If it is, then its {@link Message.date} is set to future.
*/
readonly isScheduled = false
) {

View file

@ -3,9 +3,11 @@ import { tl } from '@mtcute/tl'
export * from './user'
export * from './chat'
export * from './chat-preview'
export { InputChatPermissions } from './chat-permissions'
export * from './chat-permissions'
export * from './chat-member'
export * from './chat-event'
export * from './chat-photo'
export * from './chat-location'
export * from './chat-invite-link'
export * from './typing-status'
export * from './peers-index'

View file

@ -91,6 +91,13 @@ export class User {
return this.raw.restricted!
}
/**
* Reason why this bot was restricted
*/
get restrictionReason(): tl.TypeRestrictionReason[] {
return this.raw.restrictionReason ?? []
}
/** Whether this user has been flagged for scam */
get isScam(): boolean {
return this.raw.scam!

View file

@ -5,15 +5,5 @@
},
"include": [
"./src"
],
"typedocOptions": {
"name": "@mtcute/client",
"includeVersion": true,
"out": "../../docs/packages/client",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./src/index.ts"
]
}
]
}

View file

@ -0,0 +1,16 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./src/index.ts'],
excludeExternals: true,
externalPattern: [
'../tl/**/*',
'**/*/node_modules/**/*',
]
}

7
packages/core/README.md Normal file
View file

@ -0,0 +1,7 @@
# `@mtcute/core`
![](./coverage.svg)
Core functions and MTProto implementation.
You can learn more in [the guide](/guide/index.html).

View file

@ -9,7 +9,7 @@
"scripts": {
"test": "mocha -r ts-node/register \"tests/**/*.spec.ts\"",
"build": "tsc",
"docs": "npx typedoc"
"docs": "typedoc"
},
"browser": {
"./utils/platform/crypto.js": "./utils/platform/crypto.web.js",
@ -28,6 +28,7 @@
"events": "3.2.0"
},
"devDependencies": {
"@mtcute/dispatcher": "workspace:^1.0.0",
"@types/ws": "^7.4.1",
"ws": "^7.4.4"
}

View file

@ -826,10 +826,11 @@ export class BaseTelegramClient extends EventEmitter {
}
/**
* Destroy a connection that was previously created using {@link createAdditionalConnection}.
* Destroy a connection that was previously created using
* {@link BaseTelegramClient.createAdditionalConnection}.
* Passing any other connection will not have any effect.
*
* @param connection Connection created with {@link createAdditionalConnection}
* @param connection Connection created with {@link BaseTelegramClient.createAdditionalConnection}
*/
async destroyAdditionalConnection(
connection: SessionConnection

View file

@ -4,7 +4,9 @@ export * from './storage'
export * from './types'
export * from './utils'
/** @hidden */
export * from '@mtcute/tl'
/** @hidden */
export * from '@mtcute/tl-runtime'
export { defaultDcs } from './utils/default-dcs'

View file

@ -1,4 +1,5 @@
import { tl } from '@mtcute/tl'
import { IStateStorage } from '@mtcute/dispatcher'
import { LruMap, toggleChannelIdMark } from '../utils'
import { MaybeAsync } from '../types'
@ -8,7 +9,7 @@ const CURRENT_VERSION = 1
type PeerInfoWithUpdated = ITelegramStorage.PeerInfo & { updated: number }
interface MemorySessionState {
export interface MemorySessionState {
// forwards compatibility for persistent storages
$version: typeof CURRENT_VERSION
@ -54,7 +55,7 @@ interface MemorySessionState {
const USERNAME_TTL = 86400000 // 24 hours
export class MemoryStorage implements ITelegramStorage /*, IStateStorage */ {
export class MemoryStorage implements ITelegramStorage, IStateStorage {
protected _state!: MemorySessionState
private _cachedInputPeers: LruMap<number, tl.TypeInputPeer> = new LruMap(
100

View file

@ -10,7 +10,11 @@
"name": "@mtcute/core",
"includeVersion": true,
"out": "../../docs/packages/core",
"listInvalidSymbolLinks": true,
"validation": {
"notExported": true,
"invalidLink": true,
"notDocumented": false
},
"excludePrivate": true,
"entryPoints": [
"./src/index.ts"

17
packages/core/typedoc.js Normal file
View file

@ -0,0 +1,17 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./src/index.ts'],
excludeExternals: true,
externalPattern: [
// '../client/**/*',
'../tl/**/*',
'**/*/node_modules/**/*',
]
}

View file

@ -1,4 +1,7 @@
# `@mtcute/crypto-node`
![](./coverage.svg)
Native extension for NodeJS that improves performance of the most used
cryptographic mode in Telegram (IGE), which is not implemented by OpenSSL.

View file

@ -15,7 +15,7 @@
"rebuild": "node-gyp configure && node-gyp -j 16 rebuild",
"clean": "node-gyp clean",
"test": "mocha -r ts-node/register \"tests/**/*.spec.ts\"",
"docs": "npx typedoc"
"docs": "typedoc"
},
"dependencies": {
"@mtcute/core": "workspace:^1.0.0"

View file

@ -5,15 +5,5 @@
},
"include": [
"./src"
],
"typedocOptions": {
"name": "@mtcute/crypto-node",
"includeVersion": true,
"out": "../../docs/packages/crypto-node",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./src/index.ts"
]
}
]
}

View file

@ -0,0 +1,11 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./src/index.ts']
}

View file

@ -0,0 +1,7 @@
# `@mtcute/dispatcher`
![](./coverage.svg)
Dispatcher and bot framework for mtcute.
You can learn more in [the guide](/guide/index.html).

View file

@ -8,7 +8,7 @@
"main": "src/index.ts",
"scripts": {
"test": "mocha -r ts-node/register \"tests/**/*.spec.ts\"",
"docs": "npx typedoc",
"docs": "typedoc",
"build": "tsc"
},
"dependencies": {

View file

@ -21,14 +21,14 @@ import { tl } from '@mtcute/tl'
import { PropagationAction } from './propagation'
interface BaseUpdateHandler<Name, Handler, Checker> {
export interface BaseUpdateHandler<Name, Handler, Checker> {
name: Name
callback: Handler
check?: Checker
}
type ParsedUpdateHandler<Name, Update, State = never> = BaseUpdateHandler<
export type ParsedUpdateHandler<Name, Update, State = never> = BaseUpdateHandler<
Name,
(update: Update, state: State) => MaybeAsync<void | PropagationAction>,
(update: Update, state: State) => MaybeAsync<boolean>

View file

@ -4,5 +4,4 @@ export * from './handler'
export * from './propagation'
export * from './wizard'
export * from './callback-data-builder'
export { UpdateState, IStateStorage } from './state'
export * from './state'

View file

@ -1,3 +1,3 @@
export { IStateStorage } from './storage'
export { StateKeyDelegate, defaultStateKeyDelegate } from './key'
export { UpdateState, RateLimitError } from './update-state'
export * from './storage'
export * from './key'
export * from './update-state'

View file

@ -5,15 +5,4 @@
},
"include": [
"./src"
],
"typedocOptions": {
"name": "@mtcute/dispatcher",
"includeVersion": true,
"out": "../../docs/packages/dispatcher",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./src/index.ts"
]
}
}
]

View file

@ -0,0 +1,11 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./src/index.ts']
}

View file

@ -1,5 +1,7 @@
# `@mtcute/file-id`
![](./coverage.svg)
A package that is used internally by `@mtcute/client` to parse, serialize
and manipulate TDLib and Bot API compatible File IDs, but can also be used
for any other purposes.
@ -15,14 +17,6 @@ This package exports a number of functions, namely:
This package also exports namespace `tdFileId`, which contains all the types
used by the library
## Dependencies
This package uses `@mtcute/core` `BinaryReader` and `BinaryWriter` classes to
work with binary streams. Additionally, it depends on `@mtcute/tl` types to
allow type-safe code for conversion functions.
Note that `@mtcute/core` itself depends on `@mtcute/tl`, which might
redundantly increase your bundle size in case you don't actually use TL types.
## Acknowledgements
This is basically a port of a portion of TDLib APIs, but greatly
simplified in usage and made to work seamlessly with the rest of the

View file

@ -8,7 +8,7 @@
"main": "src/index.ts",
"scripts": {
"test": "mocha -r ts-node/register \"tests/**/*.spec.ts\"",
"docs": "npx typedoc",
"docs": "typedoc",
"build": "tsc"
},
"dependencies": {

View file

@ -4,7 +4,7 @@ import { TlBinaryWriter } from '@mtcute/tl-runtime'
import { tdFileId as td } from './types'
import { telegramRleEncode } from './utils'
type InputUniqueLocation =
export type InputUniqueLocation =
| Pick<td.RawWebRemoteFileLocation, '_' | 'url'>
| Pick<td.RawPhotoRemoteFileLocation, '_' | 'id' | 'source'>
| Pick<td.RawCommonRemoteFileLocation, '_' | 'id'>

View file

@ -5,15 +5,5 @@
},
"include": [
"./src"
],
"typedocOptions": {
"name": "@mtcute/file-id",
"includeVersion": true,
"out": "../../docs/packages/file-id",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./src/index.ts"
]
}
]
}

View file

@ -0,0 +1,11 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./src/index.ts'],
}

View file

@ -1,11 +1,13 @@
# @mtcute/html-parser
![](./coverage.svg)
> HTML entities parser for MTCute
This package implements formatting syntax based on HTML, similar to the one available in the Bot
API ([documented here](https://core.telegram.org/bots/api#html-style))
> **NOTE**: The syntax implemented here is **incompatible** with Bot API _HTML_.
> **NOTE**: The syntax implemented here is **not** compatible with Bot API _HTML_.
>
> Please read [Syntax](#syntax) below for a detailed explanation

View file

@ -10,7 +10,7 @@
"test": "mocha -r ts-node/register \"tests/**/*.spec.ts\"",
"coverage": "nyc npm run test",
"build": "tsc",
"docs": "npx typedoc"
"docs": "typedoc"
},
"dependencies": {
"@mtcute/tl": "workspace:^144.0.0",

View file

@ -5,15 +5,5 @@
},
"include": [
"./src"
],
"typedocOptions": {
"name": "@mtcute/html-parser",
"includeVersion": true,
"out": "../../docs/packages/html-parser",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./src/index.ts"
]
}
]
}

View file

@ -0,0 +1,11 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./src/index.ts'],
}

View file

@ -0,0 +1,19 @@
# @mtcute/http-proxy
![](./coverage.svg)
HTTP(s) proxy transport for mtcute.
## Usage
```typescript
import { HttpProxyTcpTransport } from '@mtcute/socks-proxy'
const tg = new TelegramClient({
// ...
transport: () => new HttpProxyTcpTransport({
host: 'localhost',
port: 1080,
})
})
```

View file

@ -7,7 +7,7 @@
"license": "LGPL-3.0",
"main": "index.ts",
"scripts": {
"docs": "npx typedoc",
"docs": "typedoc",
"build": "tsc"
},
"dependencies": {

View file

@ -5,15 +5,5 @@
},
"include": [
"./index.ts",
],
"typedocOptions": {
"name": "@mtcute/http-proxy",
"includeVersion": true,
"out": "../../docs/packages/http-proxy",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./index.ts"
]
}
]
}

View file

@ -0,0 +1,11 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./index.ts'],
}

View file

@ -1,6 +1,6 @@
# @mtcute/i18n
> I18n for MTCute
![](./coverage.svg)
This package implements utility for i18n functionality in `@mtcute/client` based apps.

View file

@ -10,7 +10,7 @@
"test": "mocha -r ts-node/register \"tests/**/*.spec.ts\"",
"coverage": "nyc npm run test",
"build": "tsc",
"docs": "npx typedoc"
"docs": "typedoc"
},
"dependencies": {
"@mtcute/client": "workspace:^1.0.0"

View file

@ -2,6 +2,8 @@ import { MtArgumentError, ParsedUpdate } from '@mtcute/client'
import { I18nValue, MtcuteI18nFunction, OtherLanguageWrap } from './types'
import { createI18nStringsIndex, extractLanguageFromUpdate } from './utils'
export * from './types'
export interface MtcuteI18nParameters<Strings> {
/**
* Primary language which will also be used as a fallback

View file

@ -5,15 +5,5 @@
},
"include": [
"./src"
],
"typedocOptions": {
"name": "@mtcute/html-parser",
"includeVersion": true,
"out": "../../docs/packages/html-parser",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./src/index.ts"
]
}
]
}

11
packages/i18n/typedoc.js Normal file
View file

@ -0,0 +1,11 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./src/index.ts'],
}

View file

@ -1,5 +1,7 @@
# @mtcute/markdown-parser
![](./coverage.svg)
> Markdown entities parser for MTCute
This package implements formatting syntax similar to Markdown (CommonMark) but slightly adjusted and simplified.

View file

@ -10,7 +10,7 @@
"test": "mocha -r ts-node/register \"tests/**/*.spec.ts\"",
"coverage": "nyc npm run test",
"build": "tsc",
"docs": "npx typedoc"
"docs": "typedoc"
},
"dependencies": {
"@mtcute/tl": "workspace:^144.0.0",

View file

@ -5,15 +5,5 @@
},
"include": [
"./src"
],
"typedocOptions": {
"name": "@mtcute/markdown-parser",
"includeVersion": true,
"out": "../../docs/packages/markdown-parser",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./src/index.ts"
]
}
]
}

View file

@ -0,0 +1,11 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./src/index.ts'],
}

View file

@ -0,0 +1,20 @@
# @mtcute/mtproxy
![](./coverage.svg)
MTProto proxy (MTProxy) transport for mtcute.
## Usage
```typescript
import { MtProxyTcpTransport } from '@mtcute/mtproxy'
const tg = new TelegramClient({
// ...
transport: () => new MtProxyTcpTransport({
host: 'localhost',
port: 443,
secret: 'secret'
})
})
```

View file

@ -7,7 +7,7 @@
"license": "LGPL-3.0",
"main": "index.ts",
"scripts": {
"docs": "npx typedoc",
"docs": "typedoc",
"build": "tsc"
},
"dependencies": {

View file

@ -5,15 +5,5 @@
},
"include": [
"./index.ts",
],
"typedocOptions": {
"name": "@mtcute/mtproxy",
"includeVersion": true,
"out": "../../docs/packages/mtproxy",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./index.ts"
]
}
]
}

View file

@ -0,0 +1,11 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./index.ts'],
}

23
packages/node/README.md Normal file
View file

@ -0,0 +1,23 @@
# @mtcute/node
![](./coverage.svg)
All-in-one package for NodeJS. Includes support for native crypto addon
(must be installed separately, `@mtcute/crypto-node`), terminal I/O via
`readline` and comes with pre-installed HTML and Markdown parsers.
> **Note**: documentation for this package only includes changes from
> `@mtcute/client`. For full documentation, see
> [`@mtcute/client` docs](../client/index.html).
## Usage
```typescript
import { NodeTelegramClient } from '@mtcute/node'
const tg = new NodeTelegramClient({
apiId: 12345,
apiHash: 'abcdef',
storage: 'client.session'
})
```

View file

@ -7,7 +7,7 @@
"license": "LGPL-3.0",
"main": "index.ts",
"scripts": {
"docs": "npx typedoc",
"docs": "typedoc",
"build": "tsc"
},
"dependencies": {

View file

@ -5,15 +5,5 @@
},
"include": [
"./index.ts"
],
"typedocOptions": {
"name": "@mtcute/node",
"includeVersion": true,
"out": "../../docs/packages/node",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./index.ts"
]
}
]
}

22
packages/node/typedoc.js Normal file
View file

@ -0,0 +1,22 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./index.ts'],
excludeExternals: true,
externalPattern: [
'../client/**/*',
'../dispatcher/**/*',
'../tl/**/*',
'../html-parser/**/*',
'../markdown-parser/**/*',
'../core/**/*',
'../sqlite/**/*',
'**/*/node_modules/**/*',
]
}

View file

@ -0,0 +1,19 @@
# @mtcute/socks-proxy
![](./coverage.svg)
Socks4/5 proxy transport for mtcute.
## Usage
```typescript
import { SocksTcpTransport } from '@mtcute/socks-proxy'
const tg = new TelegramClient({
// ...
transport: () => new SocksTcpTransport({
host: 'localhost',
port: 1080,
})
})
```

View file

@ -7,7 +7,7 @@
"license": "LGPL-3.0",
"main": "index.ts",
"scripts": {
"docs": "npx typedoc",
"docs": "typedoc",
"build": "tsc"
},
"dependencies": {

View file

@ -5,15 +5,5 @@
},
"include": [
"./index.ts",
],
"typedocOptions": {
"name": "@mtcute/socks-proxy",
"includeVersion": true,
"out": "../../docs/packages/socks-proxy",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./index.ts"
]
}
]
}

View file

@ -0,0 +1,11 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./index.ts'],
}

16
packages/sqlite/README.md Normal file
View file

@ -0,0 +1,16 @@
# @mtcute/sqlite
![](./coverage.svg)
SQLite backed storage for mtcute.
## Usage
```typescript
import { SqliteStorage } from '@mtcute/sqlite'
const tg = new TelegramClient({
// ...
storage: new SqliteStorage('client.session')
})
```

View file

@ -16,6 +16,7 @@ import {
TlReaderMap,
TlWriterMap,
} from '@mtcute/core'
import { IStateStorage } from '@mtcute/dispatcher'
// todo: add testMode to "self"
@ -168,7 +169,7 @@ const EMPTY_BUFFER = Buffer.alloc(0)
*
* Uses `better-sqlite3` library
*/
export class SqliteStorage implements ITelegramStorage /*, IStateStorage */ {
export class SqliteStorage implements ITelegramStorage, IStateStorage {
private _db!: sqlite3.Database
private _statements!: Record<keyof typeof STATEMENTS, sqlite3.Statement>
private readonly _filename: string

View file

@ -7,7 +7,7 @@
"license": "LGPL-3.0",
"main": "index.ts",
"scripts": {
"docs": "npx typedoc",
"docs": "typedoc",
"build": "tsc"
},
"dependencies": {
@ -17,6 +17,7 @@
"long": "^4.0.0"
},
"devDependencies": {
"@mtcute/dispatcher": "workspace:^1.0.0",
"@types/sqlite3": "^3.1.7",
"@types/better-sqlite3": "^5.4.1",
"@types/long": "^4.0.1"

View file

@ -5,15 +5,5 @@
},
"include": [
"./index.ts"
],
"typedocOptions": {
"name": "@mtcute/sqlite",
"includeVersion": true,
"out": "../../docs/packages/sqlite",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./index.ts"
]
}
]
}

View file

@ -0,0 +1,11 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./index.ts'],
}

View file

@ -1,5 +1,7 @@
# @mtcute/tl-runtime
![](./coverage.svg)
This package contains runtime for TL (de-)serialization.
It only contains binary reader and writer implementations,
and is used by `@mtcute/core`.

View file

@ -8,7 +8,7 @@
"main": "src/index.ts",
"scripts": {
"test": "mocha -r ts-node/register \"tests/**/*.spec.ts\"",
"docs": "npx typedoc",
"docs": "typedoc",
"build": "tsc"
},
"browser": {

View file

@ -7,8 +7,6 @@ const TWO_PWR_32_DBL = (1 << 16) * (1 << 16)
*/
export type TlWriterMap = Record<string, (w: any, val: any) => void>
type SerializableObject = { _: string }
export class TlSerializationCounter {
count = 0
@ -16,7 +14,7 @@ export class TlSerializationCounter {
static countNeededBytes(
objectMap: TlWriterMap,
obj: SerializableObject
obj: { _: string }
): number {
const cnt = new TlSerializationCounter(objectMap)
cnt.object(obj)
@ -94,7 +92,7 @@ export class TlSerializationCounter {
this.count += TlSerializationCounter.countBytesOverhead(length) + length
}
object(obj: SerializableObject): void {
object(obj: { _: string }): void {
if (!this.objectMap[obj._]) throw new Error(`Unknown object ${obj._}`)
this.objectMap[obj._](this, obj)
}
@ -132,7 +130,7 @@ export class TlBinaryWriter {
static serializeObject(
objectMap: TlWriterMap,
obj: SerializableObject,
obj: { _: string },
knownSize = -1
): Buffer {
if (knownSize === -1)
@ -238,7 +236,7 @@ export class TlBinaryWriter {
this.bytes(Buffer.from(val, 'utf-8'))
}
object(obj: SerializableObject): void {
object(obj: { _: string }): void {
const fn = this.objectMap![obj._]
if (!fn) throw new Error(`Unknown object ${obj._}`)
fn(this, obj)

View file

@ -5,15 +5,5 @@
},
"include": [
"./src",
],
"typedocOptions": {
"name": "@mtcute/tl-runtime",
"includeVersion": true,
"out": "../../docs/packages/tl-runtime",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./src/index.ts"
]
}
]
}

View file

@ -0,0 +1,12 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./src'],
entryPointStrategy: 'expand',
}

View file

@ -1,3 +1,5 @@
# @mtcute/tl-utils
![](./coverage.svg)
This package contains utilities for TL schema parsing and manipulation.

View file

@ -8,7 +8,7 @@
"main": "src/index.ts",
"scripts": {
"test": "mocha -r ts-node/register \"tests/**/*.spec.ts\"",
"docs": "npx typedoc",
"docs": "typedoc",
"build": "tsc"
},
"browser": {

View file

@ -191,7 +191,7 @@ export function generateCodeForErrors(
idx = 0
comment += it.description.replace(
/%[a-z]/g,
() => `{@see ${placeholders[idx++]}}`
() => `{@link ${placeholders[idx++]}}`
)
} else {
description = `"Unknown RPC error: [${it.code}:${it.name}]"`

View file

@ -60,13 +60,13 @@ export interface TlErrors {
userOnly: Record<string, 1>
}
interface BasicDiff<T, K> {
export interface BasicDiff<T, K> {
added: T[]
removed: T[]
modified: K[]
}
interface PropertyDiff<T> {
export interface PropertyDiff<T> {
old: T
new: T
}
@ -86,7 +86,7 @@ export interface TlEntryDiff {
comment?: PropertyDiff<string | undefined>
}
interface TlUnionDiff {
export interface TlUnionDiff {
name: string
classes: BasicDiff<TlEntry, never>
methods: BasicDiff<TlEntry, never>

View file

@ -5,15 +5,5 @@
},
"include": [
"./src/**/*.ts"
],
"typedocOptions": {
"name": "@mtcute/tl-utils",
"includeVersion": true,
"out": "../../docs/packages/tl-utils",
"listInvalidSymbolLinks": true,
"excludePrivate": true,
"entryPoints": [
"./src/**/*.ts"
]
}
]
}

View file

@ -0,0 +1,12 @@
const path = require('path')
module.exports = {
...require('../../typedoc.js'),
out: path.join(
__dirname,
'../../docs/packages/' +
require('./package.json').name.replace(/^@.+\//, '')
),
entryPoints: ['./src'],
entryPointStrategy: 'expand',
}

View file

@ -2,7 +2,7 @@
> TL schema and related utils used for MTCute.
Generated from TL layer **144** (last updated on 12.08.2022).
Generated from TL layer **144** (last updated on 18.08.2022).
## About

File diff suppressed because one or more lines are too long

View file

@ -13,8 +13,7 @@
"docs-cli": "node -r ts-node/register scripts/documentation.ts",
"gen-code": "node -r ts-node/register scripts/gen-code.ts",
"gen-rsa": "node -r ts-node/register scripts/gen-rsa-keys.ts",
"fetch-and-gen": "yarn fetch-api && yarn gen-code",
"docs": "npx typedoc --options typedoc.json"
"fetch-and-gen": "yarn fetch-api && yarn gen-code"
},
"dependencies": {
"@types/long": "^4.0.1",
@ -28,5 +27,8 @@
"js-yaml": "^4.0.0",
"node-fetch": "^2.6.1",
"@types/node-fetch": "^2.5.10"
},
"typedoc": {
"entryPoint": "index.d.ts"
}
}

File diff suppressed because one or more lines are too long

View file

@ -1,15 +0,0 @@
{
"name": "@mtcute/tl",
"out": "../../docs/packages/tl",
"includeVersion": true,
"listInvalidSymbolLinks": false,
"excludeExternals": true,
"entryPoints": [
"./index.d.ts",
"./errors.d.ts",
"./raw-schema.d.ts",
"./binary/reader.d.ts",
"./binary/writer.d.ts",
"./binary/rsa-keys.d.ts"
]
}

View file

@ -1,4 +1,4 @@
lockfileVersion: 5.4
lockfileVersion: 5.3
importers:
@ -24,7 +24,8 @@ importers:
rimraf: ^3.0.2
semver: ^7.3.7
ts-node: ^10.8.1
typedoc: ^0.23.2
typedoc: ^0.23.10
typedoc-plugin-coverage: ^2.0.0
typescript: ^4.7.4
dependencies:
node-gyp: 9.0.0
@ -34,8 +35,8 @@ importers:
'@types/node': 14.18.16
'@types/node-forge': 1.0.2
'@types/ws': 7.4.7
'@typescript-eslint/eslint-plugin': 4.33.0_3ekaj7j3owlolnuhj3ykrb7u7i
'@typescript-eslint/parser': 4.33.0_hxadhbs2xogijvk7vq4t2azzbu
'@typescript-eslint/eslint-plugin': 4.33.0_d91404fd3b7596e5b6874ef0a887f4fa
'@typescript-eslint/parser': 4.33.0_eslint@7.32.0+typescript@4.7.4
chai: 4.3.6
dotenv-flow: 3.2.0
eslint: 7.32.0
@ -47,15 +48,16 @@ importers:
prettier: 2.6.2
rimraf: 3.0.2
semver: 7.3.7
ts-node: 10.8.1_n4ne3vfoqubxgiypogr36fpdje
typedoc: 0.23.2_typescript@4.7.4
ts-node: 10.8.1_6f1a4dd4ae850373230f71a3bf15e349
typedoc: 0.23.10_typescript@4.7.4
typedoc-plugin-coverage: 2.0.0_typedoc@0.23.10
typescript: 4.7.4
packages/client:
specifiers:
'@mtcute/core': workspace:^1.0.0
'@mtcute/file-id': workspace:^1.0.0
'@mtcute/tl': workspace:143.0.0
'@mtcute/tl': workspace:^144.0.0
'@types/long': ^4.0.1
'@types/node': ^15.12.1
eager-async-pool: ^1.0.0
@ -73,7 +75,8 @@ importers:
packages/core:
specifiers:
'@mtcute/tl': workspace:143.0.0
'@mtcute/dispatcher': workspace:^1.0.0
'@mtcute/tl': workspace:^144.0.0
'@mtcute/tl-runtime': workspace:^1.0.0
'@types/events': ^3.0.0
'@types/long': ^4.0.2
@ -93,6 +96,7 @@ importers:
events: 3.2.0
long: 4.0.0
devDependencies:
'@mtcute/dispatcher': link:../dispatcher
'@types/ws': 7.4.7
ws: 7.5.7
@ -109,7 +113,7 @@ importers:
specifiers:
'@mtcute/client': workspace:^1.0.0
'@mtcute/core': workspace:^1.0.0
'@mtcute/tl': workspace:143.0.0
'@mtcute/tl': workspace:^144.0.0
events: ^3.2.0
dependencies:
'@mtcute/client': link:../client
@ -120,7 +124,7 @@ importers:
packages/file-id:
specifiers:
'@mtcute/core': workspace:^1.0.0
'@mtcute/tl': workspace:143.0.0
'@mtcute/tl': workspace:^144.0.0
'@mtcute/tl-runtime': workspace:^1.0.0
'@types/long': ^4.0.1
long: ^4.0.0
@ -135,7 +139,7 @@ importers:
packages/html-parser:
specifiers:
'@mtcute/client': workspace:^1.0.0
'@mtcute/tl': workspace:143.0.0
'@mtcute/tl': workspace:^144.0.0
'@types/long': ^4.0.1
htmlparser2: ^6.0.1
long: ^4.0.0
@ -162,7 +166,7 @@ importers:
packages/markdown-parser:
specifiers:
'@mtcute/client': workspace:^1.0.0
'@mtcute/tl': workspace:143.0.0
'@mtcute/tl': workspace:^144.0.0
'@types/long': ^4.0.1
long: ^4.0.0
dependencies:
@ -207,6 +211,7 @@ importers:
packages/sqlite:
specifiers:
'@mtcute/core': workspace:^1.0.0
'@mtcute/dispatcher': workspace:^1.0.0
'@mtcute/tl-runtime': workspace:^1.0.0
'@types/better-sqlite3': ^5.4.1
'@types/long': ^4.0.1
@ -219,6 +224,7 @@ importers:
better-sqlite3: 7.5.1
long: 4.0.0
devDependencies:
'@mtcute/dispatcher': link:../dispatcher
'@types/better-sqlite3': 5.4.3
'@types/long': 4.0.2
'@types/sqlite3': 3.1.8
@ -697,7 +703,7 @@ packages:
'@types/node': 14.18.16
dev: true
/@typescript-eslint/eslint-plugin/4.33.0_3ekaj7j3owlolnuhj3ykrb7u7i:
/@typescript-eslint/eslint-plugin/4.33.0_d91404fd3b7596e5b6874ef0a887f4fa:
resolution: {integrity: sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==}
engines: {node: ^10.12.0 || >=12.0.0}
peerDependencies:
@ -708,8 +714,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/experimental-utils': 4.33.0_hxadhbs2xogijvk7vq4t2azzbu
'@typescript-eslint/parser': 4.33.0_hxadhbs2xogijvk7vq4t2azzbu
'@typescript-eslint/experimental-utils': 4.33.0_eslint@7.32.0+typescript@4.7.4
'@typescript-eslint/parser': 4.33.0_eslint@7.32.0+typescript@4.7.4
'@typescript-eslint/scope-manager': 4.33.0
debug: 4.3.4
eslint: 7.32.0
@ -723,7 +729,7 @@ packages:
- supports-color
dev: true
/@typescript-eslint/experimental-utils/4.33.0_hxadhbs2xogijvk7vq4t2azzbu:
/@typescript-eslint/experimental-utils/4.33.0_eslint@7.32.0+typescript@4.7.4:
resolution: {integrity: sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==}
engines: {node: ^10.12.0 || >=12.0.0}
peerDependencies:
@ -741,7 +747,7 @@ packages:
- typescript
dev: true
/@typescript-eslint/parser/4.33.0_hxadhbs2xogijvk7vq4t2azzbu:
/@typescript-eslint/parser/4.33.0_eslint@7.32.0+typescript@4.7.4:
resolution: {integrity: sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==}
engines: {node: ^10.12.0 || >=12.0.0}
peerDependencies:
@ -1089,8 +1095,6 @@ packages:
ssri: 9.0.0
tar: 6.1.11
unique-filename: 1.1.1
transitivePeerDependencies:
- bluebird
dev: false
/caching-transform/4.0.0:
@ -2359,12 +2363,11 @@ packages:
socks-proxy-agent: 6.2.0
ssri: 9.0.0
transitivePeerDependencies:
- bluebird
- supports-color
dev: false
/marked/4.0.17:
resolution: {integrity: sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==}
/marked/4.0.18:
resolution: {integrity: sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==}
engines: {node: '>= 12'}
hasBin: true
dev: true
@ -2587,7 +2590,6 @@ packages:
tar: 6.1.11
which: 2.0.2
transitivePeerDependencies:
- bluebird
- supports-color
dev: false
@ -2880,11 +2882,6 @@ packages:
/promise-inflight/1.0.1:
resolution: {integrity: sha1-mEcocL8igTL8vdhoEputEsPAKeM=}
peerDependencies:
bluebird: '*'
peerDependenciesMeta:
bluebird:
optional: true
dev: false
/promise-retry/2.0.1:
@ -3324,7 +3321,7 @@ packages:
resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=}
dev: true
/ts-node/10.8.1_n4ne3vfoqubxgiypogr36fpdje:
/ts-node/10.8.1_6f1a4dd4ae850373230f71a3bf15e349:
resolution: {integrity: sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==}
hasBin: true
peerDependencies:
@ -3407,15 +3404,24 @@ packages:
is-typedarray: 1.0.0
dev: true
/typedoc/0.23.2_typescript@4.7.4:
resolution: {integrity: sha512-THpC4vtb3wu1yck6YHzEc4ck6W4lScf8TD0Rg7XAetDih8BzP+ErYO0/6DtdzYcZyKkDwEoujkMeWW7CffCbrQ==}
/typedoc-plugin-coverage/2.0.0_typedoc@0.23.10:
resolution: {integrity: sha512-IJsYW0SvV2RUWfUBWuCG2cXTv+FiPDlls9+JlUlct3N41c1hV01ZOLKmZpEVelrvNSU3SnxxA8mkct3BQm2v0g==}
engines: {node: '>= 14'}
peerDependencies:
typedoc: ^0.22.12 || 0.23.x
dependencies:
typedoc: 0.23.10_typescript@4.7.4
dev: true
/typedoc/0.23.10_typescript@4.7.4:
resolution: {integrity: sha512-03EUiu/ZuScUBMnY6p0lY+HTH8SwhzvRE3gImoemdPDWXPXlks83UGTx++lyquWeB1MTwm9D9Ca8RIjkK3AFfQ==}
engines: {node: '>= 14.14'}
hasBin: true
peerDependencies:
typescript: 4.6.x || 4.7.x
dependencies:
lunr: 2.3.9
marked: 4.0.17
marked: 4.0.18
minimatch: 5.1.0
shiki: 0.10.1
typescript: 4.7.4

View file

@ -1,14 +0,0 @@
@echo off
cd %~dp0\..\docs
echo mt.tei.su > CNAME
rem reset git repo
rd /s /q .git
git init
git add --all . > nul 2> nul
git commit -am deploy > nul 2> nul
git push -f https://github.com/teidesu/mtcute.git gh-pages
cd ../

View file

@ -0,0 +1,512 @@
// typedoc plugin to fix up references to other packages, and also some other stuff
// based on https://github.com/nlepage/typedoc-plugin-resolve-crossmodule-references/blob/main/src/index.ts
const path = require('path')
const {
Converter,
Renderer,
DeclarationReflection,
SignatureReflection,
ParameterReflection,
TypeParameterReflection,
makeRecursiveVisitor,
ReferenceType,
TypeScript: ts,
ReflectionKind,
DefaultTheme,
Application,
} = require('typedoc')
const fs = require('fs')
const PACKAGES_DIR = path.join(__dirname, '..', 'packages')
function isReferenceType(type) {
return type.type === 'reference'
}
function isReferenceTypeBroken(type) {
return type.reflection == null && type.getSymbol() != null
}
function isTypedReflection(reflection) {
return (
reflection instanceof DeclarationReflection ||
reflection instanceof SignatureReflection ||
reflection instanceof ParameterReflection ||
reflection instanceof TypeParameterReflection
)
}
const defaultTheme = new DefaultTheme(new Renderer(new Application()))
function packageNameFromPath(path) {
return path
.slice(PACKAGES_DIR.length + 1)
.split(/[\/\\]/)[0]
}
function load(app) {
// app.converter.on(Converter.EVENT_BEGIN, (ctx) => {
// const program = ctx.programs[0]
// const basePath = path.join(PACKAGES_DIR, packageNameFromPath(program.getRootFileNames()[0]))
//
// for (const file of program.getSourceFiles()) {
// if (file.fileName.startsWith(basePath)) {
// let stmtsToRemove = []
// for (const stmt of file.statements) {
// if (stmt.kind === ts.SyntaxKind.ExportDeclaration &&
// stmt.moduleSpecifier &&
// // we only want to remove re-exports from other packages
// !stmt.moduleSpecifier.text.startsWith('.')
// ) {
// stmtsToRemove.push(stmt)
// }
// }
// file.statements = file.statements.filter((stmt) => !stmtsToRemove.includes(stmt))
// }
// }
// })
app.converter.on(Converter.EVENT_RESOLVE, (ctx, reflection) => {
recursivelyVisit(ctx, reflection, fixType)
})
}
function recursivelyVisit(ctx, reflection, callback) {
const project = ctx.project
if (isTypedReflection(reflection)) {
recursivelyVisitTypes(project, reflection, 'type', callback)
}
if (reflection instanceof DeclarationReflection) {
recursivelyVisitTypes(project, reflection, 'extendedTypes', callback)
recursivelyVisitTypes(project, reflection, 'implementedTypes', callback)
}
if (reflection.comment) {
// maybe fix links in the comment
let idx = 0
for (const it of reflection.comment.summary) {
if (it.tag === '@link') {
const name = it.text
// unlike normal references, here we don't have a symbol,
// so we can only manually hardcode some known references
let link = ''
if (name.startsWith('tl.')) {
// todo link to tl reference
link = 'https://google.com'
} else {
const [base, path] = name.split('.')
const knownClasses = {
'TelegramClient': 'client',
'ChosenInlineResult': 'client',
'CallbackQuery': 'client',
'Chat': 'client',
'ChatMember': 'client',
'ChatMemberUpdate': 'client',
'Message': 'client',
'UserStatusUpdate': 'client',
'UserTypingUpdate': 'client',
'PollVoteUpdate': 'client',
'PollUpdate': 'client',
'HistoryReadUpdate': 'client',
'DeleteMessageUpdate': 'client',
'ChatJoinRequestUpdate': 'client',
'BotChatJoinRequestUpdate': 'client',
'SessionConnection': 'core'
}
if (knownClasses[base]) {
// yay we know where that is
link = `/packages/client/${knownClasses[base]}/${base}.html`
}
if (path) link += `#${path}`
}
if (link) {
reflection.comment.summary[idx] = {
kind: 'text',
text: `[${name}](${link})`,
}
}
}
idx += 1
}
}
}
function recursivelyVisitTypes(project, typed, field, callback) {
fixTyped(project, typed, field, callback)
const typedField = typed[field]
if (!typedField) return
const visitor = makeRecursiveVisitor({
array(type) {
fixTyped(project, type, 'elementType', callback)
},
conditional(type) {
fixTyped(project, type, 'checkType', callback)
fixTyped(project, type, 'trueType', callback)
fixTyped(project, type, 'falseType', callback)
fixTyped(project, type, 'extendsType', callback)
},
indexedAccess(type) {
fixTyped(project, type, 'indexType', callback)
fixTyped(project, type, 'objectType', callback)
},
intersection(type) {
fixTyped(project, type, 'types', callback)
},
mapped(type) {
fixTyped(project, type, 'nameType', callback)
fixTyped(project, type, 'parameterType', callback)
fixTyped(project, type, 'templateType', callback)
},
'named-tuple-member'(type) {
fixTyped(project, type, 'element', callback)
},
optional(type) {
fixTyped(project, type, 'elementType', callback)
},
predicate(type) {
fixTyped(project, type, 'targetType', callback)
},
query(type) {
fixTyped(project, type, 'queryType', callback)
},
reference(type) {
fixTyped(project, type, 'typeArguments', callback)
},
reflection(type) {
fixTyped(project, type.declaration, 'type', callback)
},
rest(type) {
fixTyped(project, type, 'elementType', callback)
},
tuple(type) {
fixTyped(project, type, 'elements', callback)
},
// FIXME template-literal?
typeOperator(type) {
fixTyped(project, type, 'target', callback)
},
union(type) {
fixTyped(project, type, 'types', callback)
},
})
if (Array.isArray(typedField)) {
typedField.forEach((type) => type.visit && type.visit(visitor))
} else {
typedField.visit(visitor)
}
}
function fixTyped(project, typed, field, callback) {
const typedField = typed[field]
if (!typedField) return
if (Array.isArray(typedField)) {
typedField.forEach((iType, i) => {
typedField[i] = callback(project, iType)
})
} else {
typed[field] = callback(project, typedField)
}
}
function fixType(project, type) {
if (isReferenceType(type) && isReferenceTypeBroken(type))
return findReferenceType(type, project)
return type
}
function getNamespacedName(symbol) {
if (!symbol.parent) return symbol.name.text
let parts = [symbol.name.text]
while (symbol.parent) {
symbol = symbol.parent
if (symbol.kind === ts.SyntaxKind.ModuleDeclaration) {
parts.push(symbol.name.text)
}
}
return parts.reverse().join('.')
}
findReferenceType._reflections = {}
function findReferenceType(type, project) {
const symbol = type.getSymbol()?.getDeclarations()?.[0]
const pkgFileName = symbol.getSourceFile().fileName
if (!pkgFileName) return type
if (pkgFileName.startsWith(PACKAGES_DIR)) {
const pkgName = packageNameFromPath(pkgFileName)
const namespacedName = getNamespacedName(symbol)
const qualifiedName = `${pkgName}:${namespacedName}`
let reflection = findReferenceType._reflections[qualifiedName]
if (!reflection && pkgName === 'tl') {
reflection = new DeclarationReflection(namespacedName, ReflectionKind.Reference, project)
reflection.$tl = true
project.registerReflection(reflection)
// todo link to TL reference
// reflection.url = '...'
}
if (!reflection) {
let kind = {
[ts.SyntaxKind.TypeAliasDeclaration]: ReflectionKind.TypeAlias,
[ts.SyntaxKind.InterfaceDeclaration]: ReflectionKind.Interface,
[ts.SyntaxKind.ClassDeclaration]: ReflectionKind.Class,
[ts.SyntaxKind.EnumDeclaration]: ReflectionKind.Enum,
[ts.SyntaxKind.FunctionDeclaration]: ReflectionKind.Function,
[ts.SyntaxKind.ModuleDeclaration]: ReflectionKind.Namespace,
}[symbol.kind]
if (!kind) {
return type
}
reflection = new DeclarationReflection(qualifiedName, kind, project)
project.registerReflection(reflection)
// awesome hack
reflection.name = namespacedName
const urls = defaultTheme.buildUrls(reflection, [])
if (!urls[0]) {
throw new Error(`No url for ${qualifiedName}`)
}
reflection.name = qualifiedName
// reflection.url = path.join(`../${pkgName}/index.html`)
const prefix = determineUrlPrefix(pkgFileName, symbol)
if (prefix === null) return type
reflection.url = path.join(`../${pkgName}/${urls[0].url}`)
if (prefix) {
reflection.url = reflection.url.replace(
/\/([^\/]+?)\.html$/,
`/${prefix}$1.html`
)
}
}
findReferenceType._reflections[qualifiedName] = reflection
const newType = ReferenceType.createResolvedReference(
qualifiedName,
reflection,
project
)
if (type.typeArguments) {
newType.typeArguments = type.typeArguments
}
return newType
}
return type
}
function* walkDirectory(dir) {
const dirents = fs.readdirSync(dir, { withFileTypes: true })
for (const dirent of dirents) {
const res = path.resolve(dir, dirent.name)
if (dirent.isDirectory()) {
yield* walkDirectory(res)
} else {
yield res
}
}
}
function getModuleExports(module, filename, prefix = '') {
let exports = []
for (const statement of module.statements) {
if (statement.kind === ts.SyntaxKind.ExportDeclaration) {
const exportDeclaration = statement
if (
exportDeclaration.exportClause &&
exportDeclaration.exportClause.kind ===
ts.SyntaxKind.NamedExports
) {
// export default sucks and we don't use it here
for (const specifier of exportDeclaration.exportClause
.elements) {
exports.push(specifier.name.getText())
}
} else if (
!exportDeclaration.exportClause &&
exportDeclaration.moduleSpecifier
) {
// export * from ...
exports.push(
...getFileExports(
path.resolve(
path.dirname(filename),
exportDeclaration.moduleSpecifier.text
)
)
)
}
}
if (
Array.isArray(statement.modifiers) &&
statement.modifiers.some(
(m) => m.kind === ts.SyntaxKind.ExportKeyword
)
) {
if (statement.declarationList) {
for (const decl of statement.declarationList.declarations) {
exports.push(decl.name.getText())
}
} else if (statement.name) {
exports.push(statement.name.getText())
}
}
if (statement.kind === ts.SyntaxKind.ModuleDeclaration) {
exports.push(
...getModuleExports(statement.body, filename, `${statement.name.text}.`)
)
}
}
if (prefix) exports = exports.map((e) => `${prefix}${e}`)
return exports
}
getFileExports._cache = {}
function getFileExports(filename) {
if (!filename.endsWith('.ts')) {
// could either be a .ts file or a directory with index.ts file
const indexFilename = path.join(filename, 'index.ts')
if (fs.existsSync(indexFilename)) {
filename = indexFilename
} else if (fs.existsSync(filename + '.ts')) {
filename += '.ts'
} else {
return []
}
}
if (getFileExports._cache[filename]) return getFileExports._cache[filename]
const sourceFile = ts.createSourceFile(
filename,
fs.readFileSync(filename, 'utf8'),
ts.ScriptTarget.ES2015,
true
)
const exports = getModuleExports(sourceFile, filename)
getFileExports._cache[filename] = exports
return exports
}
determineUrlPrefix._cache = {}
function determineUrlPrefix(pkgFileName, symbol) {
const cacheKey = `${pkgFileName}!${symbol.getSourceFile().fileName}@${
symbol.pos
}`
if (cacheKey in determineUrlPrefix._cache) {
return determineUrlPrefix._cache[cacheKey]
}
const pkgName = packageNameFromPath(pkgFileName)
const packageJsonFile = path.join(PACKAGES_DIR, pkgName, 'package.json')
const packageJson = JSON.parse(fs.readFileSync(packageJsonFile, 'utf8'))
if (packageJson.name !== '@mtcute/' + pkgName) {
throw new Error(`could not find package.json for ${pkgName}`)
}
const tdConfig = require(path.join(PACKAGES_DIR, pkgName, 'typedoc.js'))
const symbolName = getNamespacedName(symbol)
let entryPoint
switch (tdConfig.entryPointStrategy) {
case 'expand': {
const possiblePoints = []
for (const dir of tdConfig.entryPoints) {
const fullDir = path.join(PACKAGES_DIR, pkgName, dir)
for (const file of walkDirectory(fullDir)) {
const exports = getFileExports(file)
if (exports.includes(symbolName)) {
possiblePoints.push(path.relative(fullDir, file))
break
}
}
}
if (possiblePoints.length) {
// shortest one wins
entryPoint = possiblePoints.sort((a, b) => {
return a.match(/[\/\\]/g).length - b.match(/[\/\\]/g).length
})[0]
}
break
}
case undefined:
case 'resolve':
for (const file of tdConfig.entryPoints) {
const exports = getFileExports(
path.join(PACKAGES_DIR, pkgName, file)
)
if (exports.includes(symbolName)) {
entryPoint = file
break
}
}
break
default:
throw new Error(
`Unsupported entryPointStrategy: ${tdConfig.entryPointStrategy}`
)
}
if (!entryPoint) {
console.warn(
`warning: could not find entry point for ${symbolName}`
)
return null
}
let prefix
if (entryPoint.endsWith('index.ts')) {
// exported from root namespace, no prefix thus
prefix = ''
} else {
prefix = entryPoint.replace(/\.ts$/, '').replace(/[\/\\]/g, '') + '.'
}
determineUrlPrefix._cache[cacheKey] = prefix
return prefix
}
module.exports = { load }

17
typedoc.js Normal file
View file

@ -0,0 +1,17 @@
const path = require('path')
module.exports = {
includeVersion: true,
validation: {
notExported: true,
invalidLink: true,
notDocumented: false,
},
excludePrivate: true,
excludeExternals: true,
exclude: ['**/*/dist', '**/*/node_modules'],
plugin: [
'typedoc-plugin-coverage',
path.join(__dirname, 'scripts/totally-great-typedoc-plugin.js'),
],
}