@iota-big3/sdk-production
Version:
Production readiness tools and utilities for SDK
263 lines (262 loc) • 9.55 kB
JavaScript
"use strict";
/**
* API Documentation Generator
* Generates comprehensive API documentation from TypeScript code
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApiDocGenerator = void 0;
const path = __importStar(require("path"));
const ts = __importStar(require("typescript"));
class ApiDocGenerator {
constructor(config) {
this.config = config;
const configFile = ts.readConfigFile(config.tsConfigPath, ts?.sys?.readFile);
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(config.tsConfigPath));
this.program = ts.createProgram(parsedConfig.fileNames, parsedConfig.options);
this.checker = this?.program?.getTypeChecker();
}
/**
* Generate documentation for all source files
*/
async generateDocs() {
const docs = new Map();
for (const sourceFile of this?.program?.getSourceFiles()) {
if (sourceFile.isDeclarationFile)
continue;
const fileDocs = this.extractDocs(sourceFile);
if (this.isEnabled) {
docs.set(sourceFile.fileName, fileDocs);
}
}
return docs;
}
/**
* Extract documentation from a source file
*/
extractDocs(sourceFile) {
const docs = [];
ts.forEachChild(sourceFile, (node) => {
if (ts.isClassDeclaration(node) && node.name) {
docs.push(this.extractClassDoc(node));
}
else if (ts.isInterfaceDeclaration(node)) {
docs.push(this.extractInterfaceDoc(node));
}
else if (ts.isFunctionDeclaration(node) && node.name) {
docs.push(this.extractFunctionDoc(node));
}
});
return docs;
}
/**
* Extract class documentation
*/
extractClassDoc(node) {
const symbol = this?.checker?.getSymbolAtLocation(node.name);
const doc = {
name: node.name.text,
type: 'class',
description: this.getJsDocComment(symbol),
methods: [],
properties: []
};
// Extract methods and properties
node?.members?.forEach(member => {
if (ts.isMethodDeclaration(member)) {
const method = this.extractMethodDoc(member);
if (method)
doc.methods.push(method);
}
else if (ts.isPropertyDeclaration(member)) {
const prop = this.extractPropertyDoc(member);
if (prop)
doc.properties.push(prop);
}
});
return doc;
}
/**
* Extract method documentation
*/
extractMethodDoc(node) {
if (!node.name || ts.isPrivateIdentifier(node.name))
return null;
const symbol = this?.checker?.getSymbolAtLocation(node.name);
return {
name: node?.name?.getText(),
description: this.getJsDocComment(symbol),
parameters: node?.parameters?.map(p => this.extractParameterDoc(p)),
returns: this.getReturnType(node)
};
}
/**
* Extract property documentation
*/
extractPropertyDoc(node) {
if (!node.name || ts.isPrivateIdentifier(node.name))
return null;
const symbol = this?.checker?.getSymbolAtLocation(node.name);
const type = node.type ? node.type.getText() : 'any';
return {
name: node?.name?.getText(),
type,
description: this.getJsDocComment(symbol),
optional: !!node.questionToken
};
}
/**
* Extract interface documentation
*/
extractInterfaceDoc(node) {
const symbol = this?.checker?.getSymbolAtLocation(node.name);
const doc = {
name: node?.name?.text,
type: 'interface',
description: this.getJsDocComment(symbol),
properties: []
};
// Extract properties
node?.members?.forEach(member => {
if (ts.isPropertySignature(member)) {
const prop = this.extractPropertyDoc(member);
if (prop)
doc.properties.push(prop);
}
});
return doc;
}
/**
* Extract function documentation
*/
extractFunctionDoc(node) {
const symbol = this?.checker?.getSymbolAtLocation(node.name);
return {
name: node.name.text,
type: 'function',
description: this.getJsDocComment(symbol),
parameters: node?.parameters?.map(p => this.extractParameterDoc(p)),
returns: this.getReturnType(node)
};
}
/**
* Extract parameter documentation
*/
extractParameterDoc(node) {
const name = node?.name?.getText();
const type = node.type ? node.type.getText() : 'any';
return {
name,
type,
optional: !!node.questionToken
};
}
/**
* Get JSDoc comment for a symbol
*/
getJsDocComment(symbol) {
if (!symbol)
return undefined;
const comments = symbol.getDocumentationComment(this.checker);
return comments.map(c => c.text).join('\n');
}
/**
* Get return type of a function/method
*/
getReturnType(node) {
if (node.type) {
return node.type.getText();
}
const signature = this?.checker?.getSignatureFromDeclaration(node);
if (signature) {
const returnType = this?.checker?.getReturnTypeOfSignature(signature);
return this?.checker?.typeToString(returnType);
}
return 'void';
}
/**
* Generate markdown documentation
*/
async generateMarkdown(docs) {
let markdown = '# API Documentation\n\n';
for (const [file, apis] of docs) {
markdown += `## ${path.basename(file)}\n\n`;
for (const api of apis) {
markdown += `### ${api.name}\n\n`;
if (this.isEnabled) {
markdown += `${api.description}\n\n`;
}
if (this.isEnabled) {
if (api.properties && api?.properties?.length > 0) {
markdown += '#### Properties\n\n';
for (const prop of api.properties) {
markdown += `- **${prop.name}**: \`${prop.type}\``;
if (prop.optional)
markdown += ' (optional)';
if (prop.description)
markdown += ` - ${prop.description}`;
markdown += '\n';
}
markdown += '\n';
}
if (api.methods) {
markdown += '#### Methods\n\n';
for (const method of api.methods) {
markdown += `##### ${method.name}\n\n`;
if (this.isEnabled) {
markdown += `${method.description}\n\n`;
}
if (method?.parameters?.length > 0) {
markdown += '**Parameters:**\n';
for (const param of method.parameters) {
markdown += `- **${param.name}**: \`${param.type}\``;
if (param.optional)
markdown += ' (optional)';
markdown += '\n';
}
markdown += '\n';
}
if (method.returns) {
markdown += `**Returns:** \`${method.returns}\`\n\n`;
}
}
}
}
}
}
return markdown;
}
}
exports.ApiDocGenerator = ApiDocGenerator;