Skip to content

Commit

Permalink
tdl-install-types: better support for prebuilt-tdlib
Browse files Browse the repository at this point in the history
Can now load tdlib commit hash and tdlib version from
prebuilt-tdlib/package.json, prebuilt-tdlib/prebuilds/tdlib.json (as a
fallback for older prebuilt-tdlib versions), or falling back to the old
behavior of extracting commit hash from
require('prebuilt-tdlib').getTdjson().

Added a special <target> `prebuilt-tdlib` instead of using the
`--prebuilt-tdlib` option. `--prebuilt-tdlib` is deprecated.

Some misc. improvements. tdl-install-types now fails if called with too
many arguments.
  • Loading branch information
Bannerets committed Jun 10, 2024
1 parent fb222cf commit a3c6f65
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 54 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
- No longer generates `number | string` instead of `string` for `int64` types
in output positions (the input int64 is still `number | string`).
- Better detection of `prebuilt-tdlib`: can now use TDLib commit and version
from `prebuilt-tdlib/package.json` or `prebuilt-tdlib/prebuilds/tdlib.json`
instead of always extracting the commit hash from the library file. The
`--prebuilt-tdlib` option is replaced with the `prebuilt-tdlib` argument
(`--prebuilt-tdlib` is deprecated).
-->

## [email protected] (2024-05-28)
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ $ npx tdl-install-types [<options>] [<target>]

(Type "y" in case it asks to install the `tdl-install-types` package.)

The utility can generate types given a tdjson library file (e.g. `npx tdl-install-types ./libtdjson.so`), a TDLib git ref (examples: `npx tdl-install-types v1.8.0`, `npx tdl-install-types master`, `npx tdl-install-types 2de39ffffe71dc41c538e66085658d21cecbae08`), or a td_api.tl file (`npx tdl-install-types td_api.tl`). When called without arguments, it will try to use `require('prebuilt-tdlib').getTdjson()` as the tdjson library, generating types for the installed version of `prebuilt-tdlib`.
The utility can generate types given a tdjson library file (e.g. `npx tdl-install-types ./libtdjson.so`), a TDLib git ref (examples: `npx tdl-install-types v1.8.0`, `npx tdl-install-types master`, `npx tdl-install-types 2de39ffffe71dc41c538e66085658d21cecbae08`), or a td_api.tl file (`npx tdl-install-types td_api.tl`). When called without arguments or with the `prebuilt-tdlib` argument, it will generate types for the installed version of `prebuilt-tdlib`.

By default, the types are generated into a `tdlib-types.d.ts` file that you can
git-commit. The declaration file should be inside your project to work. When you
Expand All @@ -457,8 +457,9 @@ important to keep the types in sync with the interface TDLib actually uses.
```console
$ # Various examples:
$ npx tdl-install-types libtdjson.so # generate types for this shared library in the cwd
$ npx tdl-install-types 0ada45c3618108a62806ce7d9ab435a18dac1aab # types for the TDLib commit
$ npx tdl-install-types 0ada45c3618108a62806ce7d9ab435a18dac1aab # types for this TDLib commit
$ npx tdl-install-types # tries to use prebult-tdlib
$ npx tdl-install-types prebuilt-tdlib # same as the above one
$ npx tdl-install-types v1.8.0 # types for the git tag in the TDLib repository
```

Expand Down
1 change: 1 addition & 0 deletions packages/tdl-install-types/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Examples:

```console
$ npx tdl-install-types # tries to use prebult-tdlib
$ npx tdl-install-types prebuilt-tdlib # same as above
$ npx tdl-install-types ./libtdjson.so # generate types for this shared library
$ npx tdl-install-types 0ada45c3618108a62806ce7d9ab435a18dac1aab # commit hash
$ npx tdl-install-types v1.8.0 # git tag in the TDLib repository
Expand Down
125 changes: 74 additions & 51 deletions packages/tdl-install-types/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@ const help = `\
By default, a tdlib-types.d.ts file is created that you can git-commit.
<target> can be a path to a .so/.dylib/.dll library, a git ref in the TDLib
repository (e.g. v1.8.0 or a commit hash), or a path to the td_api.tl file.
<target> can be one of:
- a file path to the .so/.dylib/.dll tdjson shared library file
- a file path to the td_api.tl file
- a git ref in the TDLib repository
- "prebuilt-tdlib": special value to generate types for the installed
version of prebuilt-tdlib (this is the default)
Examples:
tdl-install-types # tries to use tdlib from prebult-tdlib
tdl-install-types ./libtdjson.so # generate types for this shared library
tdl-install-types prebuilt-tdlib # use version of installed prebuilt-tdlib
tdl-install-types # similar to above: try to use prebuilt-tdlib
tdl-install-types 0ada45c3618108a62806ce7d9ab435a18dac1aab # commit hash
tdl-install-types v1.8.0 # git tag in the TDLib repository
tdl-install-types td_api.tl # generate directly from the tl file
Expand All @@ -44,12 +49,7 @@ const help = `\
--git-ref
Interpret <target> as a git ref (e.g., a commit hash or a git tag or a
branch name) in the TDLib repository. This is the default behavior if
neither of the above conditions is met.
--prebuilt-tdlib
Try to use require('prebuilt-tdlib').getTdjson() as the <target> for
--lib. Implies --lib. If this option is set, <target> is ignored.
This is the default behavior if <target> is omitted.
neither of the above conditions is met and <target> is not prebuilt-tdlib.
-o <path>
Output generated TypeScript types to <path>.
Expand All @@ -67,13 +67,15 @@ const help = `\
Can be set, for example, to the tdlight's repository.
Defaults to tdlib/td.
--prebuilt-tdlib Deprecated. Same as setting <target> to prebuilt-tdlib.
-h, --help Print this text and exit.
-v, --version Print version and exit.`

const LIB = 'lib'
const GIT_REF = 'git-ref'
const TL = 'tl'
const PREBUILT_TDLIB_TARGET = '<prebuilt-tdlib>'
const PREBUILT_TDLIB = 'prebuilt-tdlib'

let target
let type
Expand Down Expand Up @@ -105,8 +107,8 @@ function parseArgs () {
type = GIT_REF
break
case '--prebuilt-tdlib':
type = LIB
target = PREBUILT_TDLIB_TARGET
type = PREBUILT_TDLIB
target = 'prebuilt-tdlib'
break
case '-o':
if (!argv[i + 1]) {
Expand Down Expand Up @@ -143,10 +145,15 @@ function parseArgs () {
console.error(`WARN Unrecognized option ${arg}`)
break
}
if (target === PREBUILT_TDLIB_TARGET) break
if (target) {
console.error('Too many arguments')
return false
}
target = arg
if (type != null) break
if (target.endsWith('.so') || target.endsWith('.dylib') || target.endsWith('.dll'))
if (target == 'prebuilt-tdlib')
type = PREBUILT_TDLIB
else if (target.endsWith('.so') || target.endsWith('.dylib') || target.endsWith('.dll'))
type = LIB
else if (target.endsWith('.tl'))
type = TL
Expand All @@ -155,8 +162,7 @@ function parseArgs () {
}
}
if (!target) {
type = LIB
target = PREBUILT_TDLIB_TARGET
type = PREBUILT_TDLIB
defaultTarget = true
}
return true
Expand Down Expand Up @@ -185,25 +191,27 @@ function fromSchema (schema, { ver, hash } = {}) {

async function fetchTdVersion (ref) {
try {
const res = await fetch(`https://raw.githubusercontent.com/${githubRepo}/${ref}/CMakeLists.txt`)
const url = `https://raw.githubusercontent.com/${githubRepo}/${ref}/CMakeLists.txt`
const res = await fetch(url)
const text = await res.text()
if (text.includes('404: Not Found')) throw Error('Not found')
if (text.includes('404: Not Found')) throw Error('404 Not found')
const version = text.match(/TDLib VERSION ([\w.]+) /)?.[1]
if (!version) throw Error('Could not find version')
if (!version) throw Error('Could not find version in CMakeLists.txt')
return version
} catch (e) {
console.error(`WARN Failed to fetch TDLib version: ${e?.message || String(e)}`)
console.error(`WARN Failed to get TDLib version: ${e?.message || String(e)}`)
return '<unknown>'
}
}

async function fromGitRef (ref, ver) {
const res = await fetch(`https://raw.githubusercontent.com/${githubRepo}/${ref}/td/generate/scheme/td_api.tl`)
async function fromGitRef (ref, ver = null) {
const url = `https://raw.githubusercontent.com/${githubRepo}/${ref}/td/generate/scheme/td_api.tl`
const res = await fetch(url)
const schema = await res.text()
if (schema.length < 2000)
throw Error(`Failed to fetch schema: ${schema}`)
throw Error(`Failed to fetch schema from ${url}\n ${schema}`)
ver ||= await fetchTdVersion(ref)
const hash = ref.length >= 30 && ref !== ver ? ref : null
const hash = (ref.length >= 30 && ref !== ver) ? ref : null
fromSchema(schema, { ver, hash })
}

Expand All @@ -217,7 +225,7 @@ function fromDynamicLib (lib) {
const version = data.match(/\W([1234]\.\d{1,2}\.\d{1,3})\W/)?.[1]
// console.log('hash', hash)
// console.log('version', version)
if (version?.endsWith('.0')) {
if (version?.endsWith?.('.0')) {
const parsed = version.split('.').map(Number)
const useVersionRef = (parsed?.[0] === 1 && parsed?.[1] < 8)
|| (!hash && parsed.every(x => !Number.isNaN(x)))
Expand All @@ -231,33 +239,49 @@ function fromDynamicLib (lib) {
throw Error('Could not determine TDLib commit hash')
}

async function getPrebuiltLibPath () {
// return new Promise((resolve, reject) => {
// const node = spawn('node', ['-e', 'console.log(require("prebuilt-tdlib").getTdjson())'])
// if (!defaultTarget) node.stderr.pipe(process.stderr)
// let output = ''
// node.stdout.on('data', data => {
// output += data.toString()
// })
// node.on('close', code => {
// if (code !== 0)
// return reject(Error(`node exited with code ${code}`))
// resolve(output)
// })
// })
const cwdRequire = createRequire(path.resolve('index.js'))
return cwdRequire('prebuilt-tdlib').getTdjson()
}

async function fromPrebuiltTdlib () {
try {
const lib = await getPrebuiltLibPath()
fromDynamicLib(lib)
// Find path of the prebuilt-tdlib module
const cwdRequire = createRequire(path.resolve('index.js'))
const prebuiltTdlib = path.dirname(cwdRequire.resolve('prebuilt-tdlib'))

// Try to use the tdlib.commit and tdlib.version fields in package.json
const packageJsonPath = path.join(prebuiltTdlib, 'package.json')
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString())
const tdlibCommit = packageJson?.tdlib?.commit
const tdlibVersion = packageJson?.tdlib?.version
if (typeof tdlibCommit === 'string' && typeof tdlibVersion === 'string') {
await fromGitRef(tdlibCommit, tdlibVersion)
return
}

// If not existent (e.g. because of an older version of prebuilt-tdlib),
// fallback to the prebuilds/tdlib.json file
const tdlibJsonFile = path.join(prebuiltTdlib, 'prebuilds', 'tdlib.json')
const tdlibJson = JSON.parse(fs.readFileSync(tdlibJsonFile).toString())
if (typeof tdlibJson?.version === 'string') {
if (typeof tdlibJson?.commit === 'string') {
await fromGitRef(tdlibJson.commit, tdlibJson.version)
return
}
// If the 'commit' field does not exist, fallback to 'ref'
if (typeof tdlibJson?.ref === 'string') {
await fromGitRef(tdlibJson.commit, tdlibJson.version)
return
}
}

// If nothing works, fallback to executing getTdjson() and extracting tdlib
// commit from the shared library
const tdjsonFile = cwdRequire('prebuilt-tdlib').getTdjson()
await fromDynamicLib(tdjsonFile)
} catch (e) {
if (defaultTarget) {
if (defaultTarget && e?.code === 'MODULE_NOT_FOUND') {
console.error('Error: Cannot find prebuilt-tdlib. Help:')
console.error(help)
} else if (defaultTarget) {
console.error('Could not generate types for prebuilt-tdlib:')
console.error(e?.message || String(e))
console.error('Help:')
console.error(help)
} else {
console.error(String(e))
Expand All @@ -270,14 +294,13 @@ const shouldContinue = parseArgs()

if (!shouldContinue) {
// Nothing, exit
} else if (type === PREBUILT_TDLIB) {
fromPrebuiltTdlib()
} else if (type === TL) {
const schema = fs.readFileSync(target).toString()
fromSchema(schema)
} else if (type === GIT_REF) {
fromGitRef(target)
.catch(console.error)
} else if (type === LIB && target === PREBUILT_TDLIB_TARGET) {
fromPrebuiltTdlib()
fromGitRef(target).catch(console.error)
} else if (type === LIB) {
fromDynamicLib(target)
}
2 changes: 1 addition & 1 deletion scripts/update-types.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

# Should be executed with project root as the cwd

npx tdl-install-types -o typings/tdlib-types.d.ts --flow --prebuilt-tdlib
npx tdl-install-types -o typings/tdlib-types.d.ts --flow prebuilt-tdlib

0 comments on commit a3c6f65

Please sign in to comment.