2021-04-08 12:19:38 +03:00
|
|
|
const ts = require('typescript')
|
|
|
|
const path = require('path')
|
|
|
|
const fs = require('fs')
|
|
|
|
const prettier = require('prettier')
|
2021-07-17 17:26:31 +03:00
|
|
|
const updates = require('./generate-updates')
|
2021-04-08 12:19:38 +03:00
|
|
|
|
|
|
|
const targetDir = path.join(__dirname, '../src')
|
|
|
|
|
|
|
|
async function* getFiles(dir) {
|
|
|
|
const dirents = await fs.promises.readdir(dir, { withFileTypes: true })
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
for (const dirent of dirents) {
|
|
|
|
const res = path.resolve(dir, dirent.name)
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
if (dirent.isDirectory()) {
|
|
|
|
yield* getFiles(res)
|
|
|
|
} else {
|
|
|
|
yield res
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function throwError(ast, file, text) {
|
|
|
|
console.log(
|
|
|
|
`An error encountered at ${path.relative(targetDir, file)}:
|
|
|
|
> ${ast.getText()}
|
2023-06-05 03:30:48 +03:00
|
|
|
${text}`,
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
process.exit(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
async function addSingleMethod(state, fileName) {
|
|
|
|
const fileFullText = await fs.promises.readFile(fileName, 'utf-8')
|
|
|
|
const program = ts.createSourceFile(
|
|
|
|
path.basename(fileName),
|
|
|
|
fileFullText,
|
|
|
|
ts.ScriptTarget.ES2018,
|
2023-06-05 03:30:48 +03:00
|
|
|
true,
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
const relPath = path.relative(targetDir, fileName).replace(/\\/g, '/') // replace path delim to unix
|
|
|
|
|
2021-04-10 23:12:07 +03:00
|
|
|
state.files[relPath] = fileFullText
|
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
function getLeadingComments(ast) {
|
|
|
|
return (ts.getLeadingCommentRanges(fileFullText, ast.pos) || [])
|
|
|
|
.map((range) => fileFullText.substring(range.pos, range.end))
|
|
|
|
.join('\n')
|
|
|
|
}
|
|
|
|
|
|
|
|
function checkForFlag(ast, flag) {
|
|
|
|
return getLeadingComments(ast)
|
|
|
|
.split('\n')
|
|
|
|
.map((i) => i.replace(/^(\/\/|\s*\*+|\/\*\*+\s*)/g, '').trim())
|
2021-04-10 20:51:45 +03:00
|
|
|
.find((i) => i.startsWith(flag))
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
|
2021-04-24 18:01:35 +03:00
|
|
|
const hasOverloads = {}
|
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
for (const stmt of program.statements) {
|
|
|
|
const isCopy = checkForFlag(stmt, '@copy')
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
if (stmt.kind === ts.SyntaxKind.ImportDeclaration) {
|
|
|
|
if (!isCopy) continue
|
|
|
|
|
|
|
|
if (
|
|
|
|
!stmt.importClause.namedBindings ||
|
2023-08-23 22:11:42 +03:00
|
|
|
stmt.importClause.namedBindings.kind !==
|
|
|
|
ts.SyntaxKind.NamedImports
|
|
|
|
) {
|
|
|
|
throwError(stmt, fileName, 'Only named imports are supported!')
|
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
|
|
|
|
let module = stmt.moduleSpecifier.text
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
if (module[0] === '.') {
|
|
|
|
// relative, need to resolve
|
|
|
|
const modFullPath = path.join(
|
|
|
|
path.dirname(fileName),
|
2023-06-05 03:30:48 +03:00
|
|
|
stmt.moduleSpecifier.text,
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
const modPath = path.dirname(modFullPath)
|
|
|
|
const modName = path.basename(modFullPath)
|
|
|
|
|
|
|
|
module = path
|
|
|
|
.join(path.relative(targetDir, modPath), modName)
|
|
|
|
.replace(/\\/g, '/') // replace path delim to unix
|
|
|
|
if (module[0] !== '.') module = './' + module
|
|
|
|
}
|
|
|
|
|
|
|
|
if (module === './client') {
|
|
|
|
throwError(
|
|
|
|
stmt,
|
|
|
|
fileName,
|
2023-06-05 03:30:48 +03:00
|
|
|
"You can't copy an import from ./client",
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(module in state.imports)) {
|
|
|
|
state.imports[module] = new Set()
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const el of stmt.importClause.namedBindings.elements) {
|
|
|
|
state.imports[module].add(el.name.escapedText)
|
|
|
|
}
|
|
|
|
} else if (stmt.kind === ts.SyntaxKind.FunctionDeclaration) {
|
|
|
|
const name = stmt.name.escapedText
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
if (stmt.body && name in state.methods.used) {
|
|
|
|
throwError(
|
|
|
|
stmt.name,
|
|
|
|
fileName,
|
2023-06-05 03:30:48 +03:00
|
|
|
`Function name "${name}" was already used in file ${state.methods.used[name]}`,
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-06-24 00:15:12 +03:00
|
|
|
const isPrivate =
|
|
|
|
name[0] === '_' &&
|
|
|
|
name !== '_handleUpdate' &&
|
|
|
|
name !== '_normalizeInputFile' &&
|
|
|
|
name !== '_normalizeInputMedia'
|
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
const isExported = (stmt.modifiers || []).find(
|
2023-06-05 03:30:48 +03:00
|
|
|
(mod) => mod.kind === ts.SyntaxKind.ExportKeyword,
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
const isInitialize = checkForFlag(stmt, '@initialize')
|
2021-04-10 23:12:07 +03:00
|
|
|
const aliases = (function () {
|
2021-04-10 20:51:45 +03:00
|
|
|
const flag = checkForFlag(stmt, '@alias')
|
|
|
|
if (!flag) return []
|
|
|
|
|
|
|
|
const [, aliases] = flag.split('=')
|
|
|
|
if (!aliases || !aliases.length) return []
|
|
|
|
|
|
|
|
return aliases.split(',')
|
|
|
|
})()
|
2021-04-08 12:19:38 +03:00
|
|
|
|
|
|
|
if (!isExported && !isPrivate) {
|
2023-08-23 22:11:42 +03:00
|
|
|
throwError(stmt, fileName, 'Public methods MUST be exported.')
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isExported && !checkForFlag(stmt, '@internal')) {
|
|
|
|
throwError(
|
|
|
|
isExported,
|
|
|
|
fileName,
|
2023-06-05 03:30:48 +03:00
|
|
|
'Exported methods must be marked as @internal so TS compiler strips them away.',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isInitialize && isExported) {
|
|
|
|
throwError(
|
|
|
|
isExported,
|
|
|
|
fileName,
|
2023-06-05 03:30:48 +03:00
|
|
|
'Initialization methods must not be exported',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isInitialize) {
|
|
|
|
let code = stmt.body.getFullText()
|
|
|
|
|
|
|
|
// strip leading { and trailing }
|
|
|
|
while (code[0] !== '{') code = code.slice(1)
|
|
|
|
while (code[code.length - 1] !== '}') code = code.slice(0, -1)
|
|
|
|
code = code.slice(1, -1).trim()
|
|
|
|
|
|
|
|
state.init.push(code)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isExported) continue
|
|
|
|
|
|
|
|
const firstArg = stmt.parameters[0]
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
if (
|
|
|
|
isExported &&
|
|
|
|
(!firstArg ||
|
|
|
|
(firstArg.type.getText() !== 'TelegramClient' &&
|
|
|
|
firstArg.type.getText() !== 'BaseTelegramClient'))
|
2023-06-05 03:30:48 +03:00
|
|
|
) {
|
2021-04-08 12:19:38 +03:00
|
|
|
throwError(
|
|
|
|
firstArg || stmt.name,
|
|
|
|
fileName,
|
2023-06-05 03:30:48 +03:00
|
|
|
'Exported methods must have `BaseTelegramClient` or `TelegramClient` as their first parameter',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
2023-06-05 03:30:48 +03:00
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
|
2023-08-23 22:11:42 +03:00
|
|
|
const returnsExported = (
|
|
|
|
stmt.body ?
|
|
|
|
ts.getLeadingCommentRanges(
|
|
|
|
fileFullText,
|
|
|
|
stmt.body.pos + 2,
|
|
|
|
) ||
|
|
|
|
(stmt.statements &&
|
|
|
|
stmt.statements.length &&
|
|
|
|
ts.getLeadingCommentRanges(
|
|
|
|
fileFullText,
|
|
|
|
stmt.statements[0].pos,
|
|
|
|
)) ||
|
|
|
|
[] :
|
|
|
|
[]
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
.map((range) => fileFullText.substring(range.pos, range.end))
|
|
|
|
.join('\n')
|
|
|
|
.includes('@returns-exported')
|
|
|
|
|
|
|
|
// overloads
|
2021-04-24 18:01:35 +03:00
|
|
|
const isOverload = !stmt.body
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-24 18:01:35 +03:00
|
|
|
if (isOverload) {
|
|
|
|
hasOverloads[name] = true
|
|
|
|
} else {
|
2021-04-08 12:19:38 +03:00
|
|
|
state.methods.used[name] = relPath
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isExported) {
|
|
|
|
state.methods.list.push({
|
|
|
|
from: relPath,
|
|
|
|
name,
|
|
|
|
isPrivate,
|
|
|
|
func: stmt,
|
|
|
|
comment: getLeadingComments(stmt),
|
2021-04-10 23:12:07 +03:00
|
|
|
aliases,
|
2021-04-24 18:01:35 +03:00
|
|
|
overload: isOverload,
|
2021-05-10 00:35:29 +03:00
|
|
|
hasOverloads: hasOverloads[name] && !isOverload,
|
2021-04-08 12:19:38 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
const module = `./${relPath.replace(/\.ts$/, '')}`
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
if (!(module in state.imports)) {
|
|
|
|
state.imports[module] = new Set()
|
|
|
|
}
|
|
|
|
|
|
|
|
state.imports[module].add(name)
|
|
|
|
|
|
|
|
if (returnsExported) {
|
|
|
|
let returnType = stmt.type.getText()
|
|
|
|
let m = returnType.match(/^Promise<(.+)>$/)
|
|
|
|
if (m) returnType = m[1]
|
|
|
|
state.imports[module].add(returnType)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (stmt.kind === ts.SyntaxKind.InterfaceDeclaration) {
|
2021-11-23 00:03:59 +03:00
|
|
|
if (isCopy) {
|
|
|
|
state.copy.push({
|
|
|
|
from: relPath,
|
2023-06-05 03:30:48 +03:00
|
|
|
code: stmt.getText(),
|
2021-11-23 00:03:59 +03:00
|
|
|
})
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
if (!checkForFlag(stmt, '@extension')) continue
|
|
|
|
const isExported = (stmt.modifiers || []).find(
|
2023-06-05 03:30:48 +03:00
|
|
|
(mod) => mod.kind === 92, /* ExportKeyword */
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
|
2023-06-05 03:30:48 +03:00
|
|
|
if (isExported) {
|
2021-04-08 12:19:38 +03:00
|
|
|
throwError(
|
|
|
|
isExported,
|
|
|
|
fileName,
|
2023-06-05 03:30:48 +03:00
|
|
|
'Extension interfaces must not be imported',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
2023-06-05 03:30:48 +03:00
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
if (stmt.heritageClauses && stmt.heritageClauses.length) {
|
|
|
|
throwError(
|
|
|
|
stmt.heritageClauses[0],
|
|
|
|
fileName,
|
2023-06-05 03:30:48 +03:00
|
|
|
'Extension interfaces must not be extended',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const member of stmt.members || []) {
|
|
|
|
state.fields.push({
|
|
|
|
from: relPath,
|
|
|
|
code: member.getText(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
} else if (isCopy) {
|
|
|
|
state.copy.push({ from: relPath, code: stmt.getFullText().trim() })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function main() {
|
2023-08-23 22:11:42 +03:00
|
|
|
const output = fs.createWriteStream(
|
|
|
|
path.join(__dirname, '../src/client.ts'),
|
|
|
|
)
|
2021-04-08 12:19:38 +03:00
|
|
|
const state = {
|
|
|
|
imports: {},
|
|
|
|
fields: [],
|
|
|
|
init: [],
|
|
|
|
methods: {
|
|
|
|
used: {},
|
|
|
|
list: [],
|
|
|
|
},
|
|
|
|
copy: [],
|
2021-04-10 23:12:07 +03:00
|
|
|
files: {},
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
for await (const file of getFiles(path.join(__dirname, '../src/methods'))) {
|
|
|
|
if (!file.startsWith('.') && file.endsWith('.ts')) {
|
|
|
|
await addSingleMethod(state, file)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
output.write(
|
2023-08-23 22:11:42 +03:00
|
|
|
'/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging, @typescript-eslint/unified-signatures */\n' +
|
|
|
|
'/* THIS FILE WAS AUTO-GENERATED */\n' +
|
2023-06-05 03:30:48 +03:00
|
|
|
"import { BaseTelegramClient, BaseTelegramClientOptions } from '@mtcute/core'\n" +
|
|
|
|
"import { tl } from '@mtcute/tl'\n",
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
Object.entries(state.imports).forEach(([module, items]) => {
|
|
|
|
items = [...items]
|
2021-11-23 00:03:59 +03:00
|
|
|
output.write(`import { ${items.sort().join(', ')} } from '${module}'\n`)
|
2021-04-08 12:19:38 +03:00
|
|
|
})
|
|
|
|
|
2021-11-23 00:03:59 +03:00
|
|
|
output.write('\n')
|
2021-04-08 12:19:38 +03:00
|
|
|
|
|
|
|
state.copy.forEach(({ from, code }) => {
|
|
|
|
output.write(`// from ${from}\n${code}\n`)
|
|
|
|
})
|
|
|
|
|
2021-04-18 16:59:05 +03:00
|
|
|
output.write(
|
2023-06-05 03:30:48 +03:00
|
|
|
'\nexport interface TelegramClient extends BaseTelegramClient {\n',
|
2021-04-18 16:59:05 +03:00
|
|
|
)
|
2021-04-08 12:19:38 +03:00
|
|
|
|
2021-07-17 17:26:31 +03:00
|
|
|
output.write(`/**
|
|
|
|
* Register a raw update handler
|
|
|
|
*
|
|
|
|
* @param name Event name
|
|
|
|
* @param handler Raw update handler
|
|
|
|
*/
|
2021-11-23 00:03:59 +03:00
|
|
|
on(name: 'raw_update', handler: ((upd: tl.TypeUpdate | tl.TypeMessage, peers: PeersIndex) => void)): this
|
2021-07-17 17:26:31 +03:00
|
|
|
/**
|
|
|
|
* Register a parsed update handler
|
|
|
|
*
|
|
|
|
* @param name Event name
|
|
|
|
* @param handler Raw update handler
|
|
|
|
*/
|
2021-11-23 00:03:59 +03:00
|
|
|
on(name: 'update', handler: ((upd: ParsedUpdate) => void)): this\n`)
|
2021-07-17 17:26:31 +03:00
|
|
|
|
|
|
|
updates.types.forEach((type) => {
|
|
|
|
output.write(`/**
|
|
|
|
* Register ${updates.toSentence(type, 'inline')}
|
|
|
|
*
|
|
|
|
* @param name Event name
|
|
|
|
* @param handler ${updates.toSentence(type, 'full')}
|
|
|
|
*/
|
2023-08-23 22:11:42 +03:00
|
|
|
on(name: '${type.typeName}', handler: ((upd: ${
|
|
|
|
type.updateType
|
|
|
|
}) => void)): this\n`)
|
2021-07-17 17:26:31 +03:00
|
|
|
})
|
|
|
|
|
2021-04-10 18:33:05 +03:00
|
|
|
const printer = ts.createPrinter()
|
|
|
|
|
2021-04-18 16:59:05 +03:00
|
|
|
const classContents = []
|
|
|
|
|
2021-04-10 23:12:07 +03:00
|
|
|
state.methods.list.forEach(
|
2021-05-10 00:35:29 +03:00
|
|
|
({
|
|
|
|
name: origName,
|
2023-06-05 03:30:48 +03:00
|
|
|
// isPrivate,
|
2021-05-10 00:35:29 +03:00
|
|
|
func,
|
|
|
|
comment,
|
|
|
|
aliases,
|
|
|
|
overload,
|
|
|
|
hasOverloads,
|
|
|
|
}) => {
|
2021-04-10 20:51:45 +03:00
|
|
|
// create method that calls that function and passes `this`
|
|
|
|
// first let's determine the signature
|
|
|
|
const returnType = func.type ? ': ' + func.type.getText() : ''
|
2023-06-05 03:30:48 +03:00
|
|
|
const generics = func.typeParameters ?
|
|
|
|
`<${func.typeParameters
|
|
|
|
.map((it) => it.getFullText())
|
|
|
|
.join(', ')}>` :
|
|
|
|
''
|
2021-04-10 20:51:45 +03:00
|
|
|
const rawParams = (func.parameters || []).filter(
|
2023-06-05 03:30:48 +03:00
|
|
|
(it) => !it.type || it.type.getText() !== 'TelegramClient',
|
2021-04-10 20:51:45 +03:00
|
|
|
)
|
|
|
|
const parameters = rawParams
|
|
|
|
.map((it) => {
|
|
|
|
if (it.initializer) {
|
|
|
|
// has default value
|
|
|
|
it._savedDefault = it.initializer.getFullText()
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-10 20:51:45 +03:00
|
|
|
if (!it.type) {
|
|
|
|
// no explicit type.
|
|
|
|
// infer from initializer
|
|
|
|
if (
|
2021-04-10 23:12:07 +03:00
|
|
|
it.initializer.kind ===
|
|
|
|
ts.SyntaxKind.TrueKeyword ||
|
|
|
|
it.initializer.kind ===
|
|
|
|
ts.SyntaxKind.FalseKeyword
|
2021-04-10 20:51:45 +03:00
|
|
|
) {
|
|
|
|
it.type = { kind: ts.SyntaxKind.BooleanKeyword }
|
|
|
|
} else if (
|
2021-04-10 23:12:07 +03:00
|
|
|
it.initializer.kind ===
|
|
|
|
ts.SyntaxKind.StringLiteral
|
2021-04-10 20:51:45 +03:00
|
|
|
) {
|
|
|
|
it.type = { kind: ts.SyntaxKind.StringKeyword }
|
|
|
|
} else if (
|
|
|
|
it.initializer.kind ===
|
2021-04-10 23:12:07 +03:00
|
|
|
ts.SyntaxKind.NumericLiteral ||
|
|
|
|
(it.initializer.kind ===
|
|
|
|
ts.SyntaxKind.Identifier &&
|
2021-05-10 00:35:29 +03:00
|
|
|
(it.initializer.escapedText === 'NaN' ||
|
|
|
|
it.initializer.escapedText ===
|
|
|
|
'Infinity'))
|
2021-04-10 20:51:45 +03:00
|
|
|
) {
|
|
|
|
it.type = { kind: ts.SyntaxKind.NumberKeyword }
|
|
|
|
} else {
|
|
|
|
throwError(
|
|
|
|
it,
|
2021-04-10 23:12:07 +03:00
|
|
|
state.methods.used[origName],
|
2023-06-05 03:30:48 +03:00
|
|
|
'Cannot infer parameter type',
|
2021-04-10 20:51:45 +03:00
|
|
|
)
|
|
|
|
}
|
2021-04-10 18:33:05 +03:00
|
|
|
}
|
2021-04-10 20:51:45 +03:00
|
|
|
it.initializer = undefined
|
2021-04-10 23:12:07 +03:00
|
|
|
|
|
|
|
const deleteParents = (obj) => {
|
2023-08-23 22:11:42 +03:00
|
|
|
if (Array.isArray(obj)) {
|
|
|
|
return obj.forEach((it) => deleteParents(it))
|
|
|
|
}
|
2021-04-10 23:12:07 +03:00
|
|
|
|
|
|
|
if (obj.parent) delete obj.parent
|
|
|
|
|
|
|
|
for (const k of Object.keys(obj)) {
|
|
|
|
if (obj[k] && typeof obj[k] === 'object') {
|
|
|
|
deleteParents(obj[k])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
deleteParents(it)
|
|
|
|
|
2021-04-10 20:51:45 +03:00
|
|
|
it.questionToken = { kind: ts.SyntaxKind.QuestionToken }
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-10 23:12:07 +03:00
|
|
|
return printer.printNode(
|
|
|
|
ts.EmitHint.Unspecified,
|
2023-06-05 03:30:48 +03:00
|
|
|
it,
|
2021-04-10 23:12:07 +03:00
|
|
|
// state.files[state.methods.used[origName]]
|
|
|
|
)
|
2021-04-10 18:33:05 +03:00
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
|
2021-04-10 20:51:45 +03:00
|
|
|
return it.getFullText()
|
2021-04-10 23:12:07 +03:00
|
|
|
})
|
|
|
|
.join(', ')
|
|
|
|
|
|
|
|
// remove @internal mark and set default values for parameters
|
|
|
|
comment = comment
|
|
|
|
.replace(/^\s*\/\/+\s*@alias.*$/m, '')
|
|
|
|
.replace(/(\n^|\/\*)\s*\*\s*@internal.*/m, '')
|
|
|
|
.replace(
|
|
|
|
/((?:\n^|\/\*)\s*\*\s*@param )([^\s]+?)($|\s+)/gm,
|
|
|
|
(_, pref, arg, post) => {
|
|
|
|
const param = rawParams.find(
|
2023-06-05 03:30:48 +03:00
|
|
|
(it) => it.name.escapedText === arg,
|
2021-04-10 23:12:07 +03:00
|
|
|
)
|
|
|
|
if (!param) return _
|
|
|
|
if (!param._savedDefault) return _
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-10 23:12:07 +03:00
|
|
|
if (post) {
|
|
|
|
return `${pref}${arg}${post}(default: \`${param._savedDefault.trim()}\`) `
|
|
|
|
}
|
2023-06-05 03:30:48 +03:00
|
|
|
|
|
|
|
return `${pref}${arg}\n* (default: \`${param._savedDefault.trim()}\`)`
|
|
|
|
},
|
2021-04-10 23:12:07 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
for (const name of [origName, ...aliases]) {
|
2022-09-12 19:50:39 +03:00
|
|
|
if (!hasOverloads) {
|
2023-06-05 03:30:48 +03:00
|
|
|
if (!comment.match(/\/\*\*?\s*\*\//)) {
|
2023-08-23 22:11:42 +03:00
|
|
|
// empty comment, no need to write it
|
2021-11-23 00:03:59 +03:00
|
|
|
output.write(comment + '\n')
|
2023-06-05 03:30:48 +03:00
|
|
|
}
|
2021-04-24 18:01:35 +03:00
|
|
|
|
2021-04-18 16:59:05 +03:00
|
|
|
output.write(
|
2023-06-05 03:30:48 +03:00
|
|
|
`${name}${generics}(${parameters})${returnType}\n`,
|
2021-04-18 16:59:05 +03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!overload) {
|
2023-08-23 22:11:42 +03:00
|
|
|
classContents.push(`${name} = ${origName}`)
|
2021-04-18 16:59:05 +03:00
|
|
|
}
|
2021-04-10 23:12:07 +03:00
|
|
|
}
|
2023-06-05 03:30:48 +03:00
|
|
|
},
|
2021-04-10 23:12:07 +03:00
|
|
|
)
|
2021-11-23 00:03:59 +03:00
|
|
|
output.write('}\n')
|
2021-04-08 12:19:38 +03:00
|
|
|
|
2023-08-23 22:11:42 +03:00
|
|
|
output.write('\nexport class TelegramClient extends BaseTelegramClient {\n')
|
2021-04-18 16:59:05 +03:00
|
|
|
|
2021-11-23 00:03:59 +03:00
|
|
|
state.fields.forEach(({ code }) => output.write(`protected ${code}\n`))
|
2021-04-18 16:59:05 +03:00
|
|
|
|
2023-06-05 03:30:48 +03:00
|
|
|
output.write('constructor(opts: BaseTelegramClientOptions) {\n')
|
2021-11-23 00:03:59 +03:00
|
|
|
output.write('super(opts)\n')
|
2021-04-18 16:59:05 +03:00
|
|
|
state.init.forEach((code) => {
|
2021-11-23 00:03:59 +03:00
|
|
|
output.write(code + '\n')
|
2021-04-18 16:59:05 +03:00
|
|
|
})
|
|
|
|
output.write('}\n')
|
|
|
|
|
2021-11-23 00:03:59 +03:00
|
|
|
classContents.forEach((line) => output.write(line + '\n'))
|
2021-04-18 16:59:05 +03:00
|
|
|
output.write('}')
|
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
// format the resulting file with prettier
|
|
|
|
const targetFile = path.join(__dirname, '../src/client.ts')
|
|
|
|
const prettierConfig = await prettier.resolveConfig(targetFile)
|
|
|
|
let fullSource = await fs.promises.readFile(targetFile, 'utf-8')
|
|
|
|
fullSource = await prettier.format(fullSource, {
|
|
|
|
...(prettierConfig || {}),
|
|
|
|
filepath: targetFile,
|
|
|
|
})
|
|
|
|
await fs.promises.writeFile(targetFile, fullSource)
|
2023-06-05 03:30:48 +03:00
|
|
|
|
|
|
|
// fix using eslint
|
2023-08-23 22:11:42 +03:00
|
|
|
require('child_process').execSync(`pnpm exec eslint --fix ${targetFile}`, {
|
|
|
|
stdio: 'inherit',
|
|
|
|
})
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
main().catch(console.error)
|