"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.formatImports = formatImports;
exports.formatJSDocComment = formatJSDocComment;
exports.generateTypeImports = generateTypeImports;
exports.isNameReserved = isNameReserved;
exports.isTupleStruct = isTupleStruct;
exports.parseTypeFromTypeDef = parseTypeFromTypeDef;
exports.sanitizeIdentifier = sanitizeIdentifier;
var _stellarBase = require("@stellar/stellar-base");
function isNameReserved(name) {
const reservedNames = [
// Keywords
"break", "case", "catch", "class", "const", "continue", "debugger", "default", "delete", "do", "else", "export", "extends", "finally", "for", "function", "if", "import", "in", "instanceof", "new", "return", "super", "switch", "this", "throw", "try", "typeof", "var", "void", "while", "with", "yield",
// Future reserved words
"enum",
// Strict mode reserved words
"implements", "interface", "let", "package", "private", "protected", "public", "static",
// Contextual keywords
"async", "await", "constructor",
// Literals
"null", "true", "false"];
return reservedNames.includes(name);
}
/**
* Sanitize a name to avoid reserved keywords
* @param identifier - The identifier to sanitize
* @returns The sanitized identifier
*/
function sanitizeIdentifier(identifier) {
if (isNameReserved(identifier)) {
// Append underscore to reserved
return identifier + "_";
}
if (/^\d/.test(identifier)) {
// Prefix leading digit with underscore
return "_" + identifier;
}
return identifier;
}
/**
* Generate TypeScript type from XDR type definition
*/
function parseTypeFromTypeDef(typeDef, isFunctionInput = false) {
switch (typeDef.switch()) {
case _stellarBase.xdr.ScSpecType.scSpecTypeVal():
return "any";
case _stellarBase.xdr.ScSpecType.scSpecTypeBool():
return "boolean";
case _stellarBase.xdr.ScSpecType.scSpecTypeVoid():
return "null";
case _stellarBase.xdr.ScSpecType.scSpecTypeError():
return "Error";
case _stellarBase.xdr.ScSpecType.scSpecTypeU32():
case _stellarBase.xdr.ScSpecType.scSpecTypeI32():
return "number";
case _stellarBase.xdr.ScSpecType.scSpecTypeU64():
case _stellarBase.xdr.ScSpecType.scSpecTypeI64():
case _stellarBase.xdr.ScSpecType.scSpecTypeTimepoint():
case _stellarBase.xdr.ScSpecType.scSpecTypeDuration():
case _stellarBase.xdr.ScSpecType.scSpecTypeU128():
case _stellarBase.xdr.ScSpecType.scSpecTypeI128():
case _stellarBase.xdr.ScSpecType.scSpecTypeU256():
case _stellarBase.xdr.ScSpecType.scSpecTypeI256():
return "bigint";
case _stellarBase.xdr.ScSpecType.scSpecTypeBytes():
case _stellarBase.xdr.ScSpecType.scSpecTypeBytesN():
return "Buffer";
case _stellarBase.xdr.ScSpecType.scSpecTypeString():
return "string";
case _stellarBase.xdr.ScSpecType.scSpecTypeSymbol():
return "string";
case _stellarBase.xdr.ScSpecType.scSpecTypeAddress():
case _stellarBase.xdr.ScSpecType.scSpecTypeMuxedAddress():
{
// function inputs can accept either string or Address
if (isFunctionInput) {
return "string | Address";
}
// Otherwise for backward compatibility use string
return "string";
}
case _stellarBase.xdr.ScSpecType.scSpecTypeVec():
{
const vecType = parseTypeFromTypeDef(typeDef.vec().elementType(), isFunctionInput);
return `Array<${vecType}>`;
}
case _stellarBase.xdr.ScSpecType.scSpecTypeMap():
{
const keyType = parseTypeFromTypeDef(typeDef.map().keyType(), isFunctionInput);
const valueType = parseTypeFromTypeDef(typeDef.map().valueType(), isFunctionInput);
return `Map<${keyType}, ${valueType}>`;
}
case _stellarBase.xdr.ScSpecType.scSpecTypeTuple():
{
const tupleTypes = typeDef.tuple().valueTypes().map(t => parseTypeFromTypeDef(t, isFunctionInput));
return `[${tupleTypes.join(", ")}]`;
}
case _stellarBase.xdr.ScSpecType.scSpecTypeOption():
{
// Handle nested options
while (typeDef.option().valueType().switch() === _stellarBase.xdr.ScSpecType.scSpecTypeOption()) {
typeDef = typeDef.option().valueType();
}
const optionType = parseTypeFromTypeDef(typeDef.option().valueType(), isFunctionInput);
return `${optionType} | null`;
}
case _stellarBase.xdr.ScSpecType.scSpecTypeResult():
{
const okType = parseTypeFromTypeDef(typeDef.result().okType(), isFunctionInput);
const errorType = parseTypeFromTypeDef(typeDef.result().errorType(), isFunctionInput);
return `Result<${okType}, ${errorType}>`;
}
case _stellarBase.xdr.ScSpecType.scSpecTypeUdt():
{
const udtName = sanitizeIdentifier(typeDef.udt().name().toString());
return udtName;
}
default:
return "unknown";
}
}
/**
* Imports needed for generating bindings
*/
/**
* Extract nested type definitions from container types
*/
function extractNestedTypes(typeDef) {
switch (typeDef.switch()) {
case _stellarBase.xdr.ScSpecType.scSpecTypeVec():
return [typeDef.vec().elementType()];
case _stellarBase.xdr.ScSpecType.scSpecTypeMap():
return [typeDef.map().keyType(), typeDef.map().valueType()];
case _stellarBase.xdr.ScSpecType.scSpecTypeTuple():
return typeDef.tuple().valueTypes();
case _stellarBase.xdr.ScSpecType.scSpecTypeOption():
return [typeDef.option().valueType()];
case _stellarBase.xdr.ScSpecType.scSpecTypeResult():
return [typeDef.result().okType(), typeDef.result().errorType()];
default:
return [];
}
}
/**
* Visitor to collect imports from a single type definition
*/
function visitTypeDef(typeDef, accumulator) {
const typeSwitch = typeDef.switch();
// Handle leaf types (no nested types)
switch (typeSwitch) {
case _stellarBase.xdr.ScSpecType.scSpecTypeUdt():
accumulator.typeFileImports.add(sanitizeIdentifier(typeDef.udt().name().toString()));
return;
case _stellarBase.xdr.ScSpecType.scSpecTypeAddress():
case _stellarBase.xdr.ScSpecType.scSpecTypeMuxedAddress():
accumulator.stellarImports.add("Address");
return;
case _stellarBase.xdr.ScSpecType.scSpecTypeBytes():
case _stellarBase.xdr.ScSpecType.scSpecTypeBytesN():
accumulator.needsBufferImport = true;
return;
case _stellarBase.xdr.ScSpecType.scSpecTypeVal():
accumulator.stellarImports.add("xdr");
return;
case _stellarBase.xdr.ScSpecType.scSpecTypeResult():
accumulator.stellarContractImports.add("Result");
// Fall through to handle nested types
break;
// Primitive types that need no imports
case _stellarBase.xdr.ScSpecType.scSpecTypeBool():
case _stellarBase.xdr.ScSpecType.scSpecTypeVoid():
case _stellarBase.xdr.ScSpecType.scSpecTypeError():
case _stellarBase.xdr.ScSpecType.scSpecTypeU32():
case _stellarBase.xdr.ScSpecType.scSpecTypeI32():
case _stellarBase.xdr.ScSpecType.scSpecTypeU64():
case _stellarBase.xdr.ScSpecType.scSpecTypeI64():
case _stellarBase.xdr.ScSpecType.scSpecTypeTimepoint():
case _stellarBase.xdr.ScSpecType.scSpecTypeDuration():
case _stellarBase.xdr.ScSpecType.scSpecTypeU128():
case _stellarBase.xdr.ScSpecType.scSpecTypeI128():
case _stellarBase.xdr.ScSpecType.scSpecTypeU256():
case _stellarBase.xdr.ScSpecType.scSpecTypeI256():
case _stellarBase.xdr.ScSpecType.scSpecTypeString():
case _stellarBase.xdr.ScSpecType.scSpecTypeSymbol():
return;
}
// Handle container types (have nested types)
const nestedTypes = extractNestedTypes(typeDef);
nestedTypes.forEach(nested => visitTypeDef(nested, accumulator));
}
/**
* Generate imports needed for a list of type definitions
*/
function generateTypeImports(typeDefs) {
const imports = {
typeFileImports: new Set(),
stellarContractImports: new Set(),
stellarImports: new Set(),
needsBufferImport: false
};
// Visit each type definition
typeDefs.forEach(typeDef => visitTypeDef(typeDef, imports));
return imports;
}
/**
* Options for formatting imports
*/
/**
* Format imports into import statement strings
*/
function formatImports(imports, options) {
const importLines = [];
const typeFileImports = imports.typeFileImports;
const stellarContractImports = [...imports.stellarContractImports, ...(options?.additionalStellarContractImports || [])];
const stellarImports = [...imports.stellarImports, ...(options?.additionalStellarImports || [])];
// Type file imports (only if enabled)
if (options?.includeTypeFileImports && typeFileImports.size > 0) {
importLines.push(`import {${Array.from(typeFileImports).join(", ")}} from './types.js';`);
}
// Stellar contract imports
if (stellarContractImports.length > 0) {
const uniqueContractImports = Array.from(new Set(stellarContractImports));
importLines.push(`import {${uniqueContractImports.join(", ")}} from '@stellar/stellar-sdk/contract';`);
}
// Stellar SDK imports
if (stellarImports.length > 0) {
const uniqueStellarImports = Array.from(new Set(stellarImports));
importLines.push(`import {${uniqueStellarImports.join(", ")}} from '@stellar/stellar-sdk';`);
}
// Buffer import
if (imports.needsBufferImport) {
importLines.push(`import { Buffer } from 'buffer';`);
}
return importLines.join("\n");
}
/**
* Escape special characters in JSDoc comment content
*/
function escapeJSDocContent(text) {
return text
// Escape closing comment sequences that would break the JSDoc block
.replace(/\*\//g, "* /")
// Escape @ symbols at word boundaries to prevent accidental JSDoc tags
// We allow common JSDoc tags to pass through
.replace(/@(?!(param|returns?|type|throws?|example|deprecated|see|link|since|author|version|description|summary)\b)/g, "\\@");
}
/**
* Format a comment string as JSDoc with proper escaping
*/
function formatJSDocComment(comment, indentLevel = 0) {
if (comment.trim() === "") {
return "";
}
const indent = " ".repeat(indentLevel);
// Escape special characters and split into lines
const escapedComment = escapeJSDocContent(comment);
const lines = escapedComment.split("\n").map(line => `${indent} * ${line}`.trimEnd());
return `${indent}/**\n${lines.join("\n")}\n${indent} */\n`;
}
function isTupleStruct(udtStruct) {
const fields = udtStruct.fields();
// A tuple struct has unnamed fields
return fields.every((field, index) => field.name().toString().trim() === index.toString());
}
Source