#!/usr/bin/env node // @ts-check /** * @file * Updates the SDK Typescript definitions located in the file sdk.d.ts * to match the current definitions of functions of sdk.mjs. */ import {spawnSync} from 'node:child_process'; import fs from 'node:fs/promises'; import path from 'node:path'; import process from 'node:process'; import {fileExists} from '../utils.js'; const rootDirectory = path.resolve(import.meta.dirname, '..', '..'); const sdkTs = path.resolve(rootDirectory, 'sdk.d.ts'); const sdkMts = path.resolve(rootDirectory, 'sdk.d.mts'); const sdkMjs = path.resolve(rootDirectory, 'sdk.mjs'); const generateSdkMts = async () => { // Remove temporally type definitions imported with comments // in sdk.mjs to avoid circular imports const originalSdkMjsContent = await fs.readFile(sdkMjs, 'utf8'); const temporarySdkMjsContent = originalSdkMjsContent .split('\n') .filter((line) => !line.startsWith(' * @typedef {import("./sdk")')) .join('\n'); await fs.writeFile(sdkMjs, temporarySdkMjsContent); let cmd; let error = false; try { cmd = spawnSync( 'npx', [ 'tsc', '-p', path.join('scripts', 'release', 'sdk-ts-defs-jsconfig.json'), '--declaration', '--emitDeclarationOnly', ], {stdio: 'inherit'}, ); } catch { await fs.writeFile(sdkMjs, originalSdkMjsContent); error = true; } let errorMessage = "Command 'npx tsc sdk.mjs' failed for an unknown reason"; if (cmd && cmd.stderr) { errorMessage = cmd.stderr.toString(); } if (error || cmd === undefined) { process.stdout.write( `Error generating Typescript definitions: '${errorMessage}'\n`, ); process.exit(1); } await fs.writeFile(sdkMjs, originalSdkMjsContent); }; /** * We must remove the duplicated export types that tsc generates from * JSDoc `typedef` comments. * See {@link https://github.com/microsoft/TypeScript/issues/46011}. * @param {string} content Content of the file. * @returns {string} The content without duplicated export types. */ const removeDuplicatedExportTypes = (content) => { const newContent = []; const lines = content.split('\n'); /** @type {string[]} */ const exportTypesFound = []; for (const line of lines) { if (line.startsWith('export type ')) { const type = line.split(' ')[2]; if (!exportTypesFound.includes(type)) { newContent.push(line); exportTypesFound.push(type); } } else { newContent.push(line); } } return newContent.join('\n'); }; const generateSdkTs = async () => { const sdkMtsExists = await fileExists(sdkMts); if (sdkMtsExists) await fs.unlink(sdkMts); await generateSdkMts(); const autogeneratedMessage = '/* The next code is autogenerated from sdk.mjs */\n/* eslint-disable */'; const newSdkTsContent = // eslint-disable-next-line unicorn/no-await-expression-member (await fs.readFile(sdkTs, 'utf8')).split(autogeneratedMessage)[0] + `${autogeneratedMessage}\n\n${await fs.readFile(sdkMts, 'utf8')}`; await fs.writeFile(sdkTs, removeDuplicatedExportTypes(newSdkTsContent)); await fs.unlink(sdkMts); let cmd; let error = false; try { cmd = spawnSync('npx', ['prettier', '-w', 'sdk.d.ts'], {stdio: 'inherit'}); } catch { error = true; } let errorMessage = "Command 'npx prettier -w sdk.d.ts' failed for an unknown reason"; if (cmd && cmd.stderr) { errorMessage = cmd.stderr.toString(); } if (error || cmd === undefined) { process.stdout.write( 'Error executing Prettier to prettify' + ` SDK TS definitions: '${errorMessage}'\n`, ); process.exit(1); } }; await generateSdkTs();