|
const path = require('path'); |
|
const globby = require('globby'); |
|
const fs = require('fs'); |
|
const os = require('os'); |
|
const { promisify } = require('util'); |
|
const openrpcTypings = require('@open-rpc/typings'); |
|
const { pascalCase, camelCase } = require('change-case'); |
|
const { dereferenceDocument } = require('@open-rpc/schema-utils-js'); |
|
const { defaultResolver } = require('@json-schema-tools/reference-resolver'); |
|
|
|
const readfs = promisify(fs.readFile); |
|
const writefs = promisify(fs.writeFile); |
|
|
|
/** |
|
* |
|
* @param {*} declaration e.g. `export type Foo = (fp1: P) => Promise<Y>;` |
|
* @returns e.g. `async foo(fp1: P): Promise<T>;` |
|
*/ |
|
function convertTypeDeclaration(declaration) { |
|
const [functionName, arrowFunctionDecleration] = declaration |
|
.split('type')[1] |
|
.trim() |
|
.split(' = '); |
|
const [params, returnType] = arrowFunctionDecleration.split('=>'); |
|
return `async ${camelCase(functionName)}${params.trim()}: ${returnType.trim()}`;} |
|
|
|
function generateInterface(typings, name) { |
|
const functions = typings |
|
.getMethodTypings('typescript') |
|
.split(os.EOL) |
|
.map((line) => convertTypeDeclaration(line)); |
|
const symbol = [pascalCase(name.split('.')[0]), 'RpcMethods'].join(''); |
|
return `export interface ${symbol} { |
|
${functions.join(os.EOL)} |
|
}`; |
|
} |
|
|
|
async function exec() { |
|
const openrpcDocPaths = await globby('src/**/*.openrpc.json', {}); |
|
const tasks = openrpcDocPaths.map(async (docPath) => { |
|
const doc = await readfs(path.resolve(docPath)); |
|
const dereffedDocument = await dereferenceDocument( |
|
JSON.parse(doc), |
|
defaultResolver, |
|
); |
|
const typings = new openrpcTypings.default(dereffedDocument); |
|
const { dir, name } = path.parse(docPath); |
|
const interface = generateInterface(typings, name); |
|
const dtsFilePath = path.resolve(dir, `${name}.d.ts`); |
|
await writefs( |
|
dtsFilePath, |
|
[typings.toString('typescript'), interface].join(os.EOL), |
|
); |
|
return dtsFilePath; |
|
}); |
|
return Promise.all(tasks); |
|
} |
|
|
|
exec().then((generatedFiles) => |
|
console.log( |
|
['done generating the following file:', ...generatedFiles].join(os.EOL), |
|
), |
|
); |