From 0841cbb031a08b47018fc091d5f67ee0a2273d28 Mon Sep 17 00:00:00 2001 From: Alina Sireneva Date: Thu, 12 Oct 2023 05:24:16 +0300 Subject: [PATCH] fix: errors codegen --- packages/tl-utils/src/codegen/errors.ts | 31 ++++++++++++++++++------- packages/tl-utils/src/codegen/types.ts | 7 ------ packages/tl/scripts/gen-code.ts | 21 +++++++++++++++++ 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/packages/tl-utils/src/codegen/errors.ts b/packages/tl-utils/src/codegen/errors.ts index 52aec98e..9d5d518c 100644 --- a/packages/tl-utils/src/codegen/errors.ts +++ b/packages/tl-utils/src/codegen/errors.ts @@ -4,26 +4,36 @@ import { snakeToCamel } from './utils' const TEMPLATE_JS = ` const _descriptionsMap = JSON.parse('{descriptionsMap}') class RpcError extends Error { - constructor(code, text) { - super(_descriptionsMap[text] || 'Unknown RPC error: [' + code + ':' + text + ']'); + constructor(code, text, description) { + super(description || 'Unknown RPC error: [' + code + ':' + text + ']'); this.code = code; this.text = text; - this.unknown = !_descriptionsMap[text]; } static is(err, text) { return err.constructor === RpcError && (!text || err.text === text); } is(text) { return this.text === text; } } RpcError.fromTl = function (obj) { - const err = new RpcError(obj.errorCode, obj.errorMessage); + if (obj.errorMessage in _descriptionsMap) { + return new RpcError(obj.errorCode, obj.errorMessage, _descriptionsMap[obj.errorMessage]); + } - if (err in _descriptionsMap) return err; - - let match; + var err = new RpcError(obj.errorCode, obj.errorMessage); + var match; {matchers} + else return err + err.message = _descriptionsMap[err.text]; return err } +RpcError.create = function(code, text) { + var desc = _descriptionsMap[text]; + var err = new RpcError(code, text, desc); + if (!desc) { + err.unknown = true; + } + return err; +} {statics} {exports}RpcError = RpcError; `.trimStart() @@ -115,6 +125,8 @@ export function generateCodeForErrors(errors: TlErrors, exports = 'exports.'): [ staticsTs += ` static ${name}: ${code};\n` } + let first = true + for (const error of Object.values(errors.errors)) { const [name, placeholders] = parseCode(error.name, error._paramNames) @@ -131,7 +143,10 @@ export function generateCodeForErrors(errors: TlErrors, exports = 'exports.'): [ const regex = name.replace('%d', '(\\d+)') const setters = placeholders.map((it, i) => `err.${it} = parseInt(match[${i + 1}])`).join('; ') - matchers += ` if ((match=obj.errorMessage.match(/^${regex}$/))!=null){ err.text = '${name}'; ${setters} }\n` + matchers += ` ${ + first ? '' : 'else ' + }if ((match=err.text.match(/^${regex}$/))!=null){ err.text = '${name}'; ${setters} }\n` + first = false } } diff --git a/packages/tl-utils/src/codegen/types.ts b/packages/tl-utils/src/codegen/types.ts index 16c1a0f8..7356bc32 100644 --- a/packages/tl-utils/src/codegen/types.ts +++ b/packages/tl-utils/src/codegen/types.ts @@ -234,16 +234,9 @@ export function generateTypescriptDefinitionsForTlSchema( let js = PRELUDE_JS.replace('$NS$', namespace).replace('$LAYER$', String(layer)) if (errors) { - // ts += '\n namespace errors {\n' - // js += 'ns.errors = {};\n(function(ns){\n' - const [_ts, _js] = generateCodeForErrors(errors, 'ns.') - // ts += indent(8, _ts) ts += _ts js += _js - - // ts += '}\n' - // js += '})(ns.errors);\n' } const namespaces = groupTlEntriesByNamespace(schema.entries) diff --git a/packages/tl/scripts/gen-code.ts b/packages/tl/scripts/gen-code.ts index 20fb2794..1eebbbf6 100644 --- a/packages/tl/scripts/gen-code.ts +++ b/packages/tl/scripts/gen-code.ts @@ -59,8 +59,29 @@ async function generateWriters(apiSchema: TlFullSchema, mtpSchema: TlFullSchema) await writeFile(OUT_WRITERS_FILE, ESM_PRELUDE + code) } +// put common errors to the top so they are parsed first +const ERRORS_ORDER = ['FLOOD_WAIT_%d', 'FILE_MIGRATE_%d', 'NETWORK_MIGRATE_%d', 'PHONE_MIGRATE_%d', 'STATS_MIGRATE_%d'] + +function putCommonErrorsFirst(errors: TlErrors) { + const newErrors: TlErrors['errors'] = {} + + for (const name of ERRORS_ORDER) { + if (name in errors.errors) { + newErrors[name] = errors.errors[name] + } + } + + for (const name in errors.errors) { + if (name in newErrors) continue + newErrors[name] = errors.errors[name] + } + + errors.errors = newErrors +} + async function main() { const errors = JSON.parse(await readFile(ERRORS_JSON_FILE, 'utf8')) as TlErrors + putCommonErrorsFirst(errors) const [apiSchema, apiLayer] = unpackTlSchema( JSON.parse(await readFile(API_SCHEMA_JSON_FILE, 'utf8')) as TlPackedSchema,