github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/js/src/solts/lib/syntax.ts (about) 1 import ts, { ConciseBody, factory, MethodDeclaration, TypeNode } from 'typescript'; 2 3 export const ErrorType = factory.createTypeReferenceNode('Error'); 4 export const VoidType = factory.createTypeReferenceNode('void', undefined); 5 export const StringType = factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword); 6 export const NumberType = factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword); 7 export const BooleanType = factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword); 8 export const UnknownType = factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword); 9 export const UndefinedType = factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword); 10 export const Uint8ArrayType = factory.createTypeReferenceNode('Uint8Array'); 11 export const MaybeUint8ArrayType = factory.createUnionTypeNode([Uint8ArrayType, UndefinedType]); 12 13 export const PromiseType = factory.createIdentifier('Promise'); 14 export const ReadableType = factory.createIdentifier('Readable'); 15 export const BufferType = factory.createIdentifier('Buffer'); 16 export const Address = factory.createIdentifier('Address'); 17 export const Event = factory.createIdentifier('Event'); 18 export const ContractCodec = factory.createIdentifier('ContractCodec'); 19 export const Result = factory.createIdentifier('Result'); 20 export const CancelStreamSignal = factory.createIdentifier('CancelStreamSignal'); 21 export const ReturnType = factory.createIdentifier('ReturnType'); 22 export const listenerForName = factory.createIdentifier('listenerFor'); 23 export const linkerName = factory.createIdentifier('linker'); 24 export const keccakName = factory.createIdentifier('Keccak'); 25 26 export const TType = factory.createTypeReferenceNode('T'); 27 export const AddressType = factory.createTypeReferenceNode(Address); 28 export const EventType = factory.createTypeReferenceNode(Event); 29 export const ContractCodecType = factory.createTypeReferenceNode(ContractCodec); 30 export const CancelStreamSignalType = factory.createTypeReferenceNode(CancelStreamSignal); 31 32 export const PrivateToken = factory.createToken(ts.SyntaxKind.PrivateKeyword); 33 export const PublicToken = factory.createToken(ts.SyntaxKind.PublicKeyword); 34 export const ExportToken = factory.createToken(ts.SyntaxKind.ExportKeyword); 35 export const EllipsisToken = factory.createToken(ts.SyntaxKind.DotDotDotToken); 36 export const QuestionToken = factory.createToken(ts.SyntaxKind.QuestionToken); 37 export const QuestionDotToken = factory.createToken(ts.SyntaxKind.QuestionDotToken); 38 export const ColonToken = factory.createToken(ts.SyntaxKind.ColonToken); 39 export const AsyncToken = factory.createToken(ts.SyntaxKind.AsyncKeyword); 40 export const ReadonlyToken = factory.createToken(ts.SyntaxKind.ReadonlyKeyword); 41 export const EqualsGreaterThanToken = factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken); 42 export const Undefined = factory.createIdentifier('undefined'); 43 44 export function createCall(fn: ts.Expression | string, args?: ts.Expression[]): ts.CallExpression { 45 return factory.createCallExpression(asExp(fn), undefined, args); 46 } 47 48 export function accessThis(name: ts.Identifier): ts.PropertyAccessExpression { 49 return factory.createPropertyAccessExpression(factory.createThis(), name); 50 } 51 52 export function bufferFrom(...args: ts.Expression[]): ts.CallExpression { 53 return createCall(factory.createPropertyAccessExpression(BufferType, factory.createIdentifier('from')), args); 54 } 55 56 export function asArray(type: ts.TypeNode): ts.ArrayTypeNode { 57 return factory.createArrayTypeNode(type); 58 } 59 60 export function asTuple(type: ts.TypeNode, size: number): ts.TupleTypeNode { 61 return factory.createTupleTypeNode(Array(size).fill(type)); 62 } 63 64 export function asRefNode(id: ts.Identifier): ts.TypeReferenceNode { 65 return factory.createTypeReferenceNode(id, undefined); 66 } 67 68 export function asConst(exp: ts.Expression): ts.AsExpression { 69 return factory.createAsExpression(exp, factory.createTypeReferenceNode('const')); 70 } 71 72 export function constObject(elements: ts.ObjectLiteralElementLike[]): ts.AsExpression { 73 return asConst(factory.createObjectLiteralExpression(elements)); 74 } 75 76 export function arrowFunc(params: ts.ParameterDeclaration[], body: ConciseBody): ts.ArrowFunction { 77 return factory.createArrowFunction(undefined, undefined, params, undefined, EqualsGreaterThanToken, body); 78 } 79 80 export function hexToBuffer(arg: ts.Expression): ts.CallExpression { 81 return createCall(prop(BufferType, 'from'), [arg, factory.createStringLiteral('hex')]); 82 } 83 84 export function hexToKeccak256(str: ts.Expression): ts.CallExpression { 85 // new Keccak(256).update(str).digest('binary'); 86 return createCall( 87 prop( 88 createCall( 89 prop(factory.createNewExpression(keccakName, undefined, [factory.createNumericLiteral('256')]), 'update'), 90 [str, factory.createStringLiteral('hex')], 91 ), 92 'digest', 93 ), 94 [factory.createStringLiteral('binary')], 95 ); 96 } 97 98 export function arrowFuncT( 99 params: ts.ParameterDeclaration[], 100 constraint: TypeNode | undefined, 101 type: TypeNode | undefined, 102 body: ConciseBody, 103 ): ts.ArrowFunction { 104 return factory.createArrowFunction( 105 undefined, 106 [factory.createTypeParameterDeclaration('T', constraint)], 107 params, 108 type, 109 EqualsGreaterThanToken, 110 body, 111 ); 112 } 113 114 export function prop( 115 obj: ts.Expression | string, 116 name: string | ts.Identifier, 117 optionChain?: boolean, 118 ): ts.PropertyAccessExpression { 119 return factory.createPropertyAccessChain(asExp(obj), optionChain ? QuestionDotToken : undefined, name); 120 } 121 122 function asExp(exp: ts.Expression | string): ts.Expression { 123 return typeof exp === 'string' ? factory.createIdentifier(exp) : exp; 124 } 125 126 export function createParameter( 127 name: string | ts.BindingName, 128 typeNode?: ts.TypeNode, 129 initializer?: ts.Expression, 130 isOptional?: boolean, 131 isVariadic?: boolean, 132 ): ts.ParameterDeclaration { 133 return factory.createParameterDeclaration( 134 undefined, 135 undefined, 136 isVariadic ? EllipsisToken : undefined, 137 name, 138 isOptional ? QuestionToken : undefined, 139 typeNode, 140 initializer, 141 ); 142 } 143 144 export function declareConstant( 145 name: ts.Identifier | string, 146 initializer?: ts.Expression, 147 extern?: boolean, 148 ): ts.VariableStatement { 149 return factory.createVariableStatement( 150 extern ? [ExportToken] : [], 151 factory.createVariableDeclarationList( 152 [factory.createVariableDeclaration(name, undefined, undefined, initializer)], 153 ts.NodeFlags.Const, 154 ), 155 ); 156 } 157 158 export function declareLet(name: ts.Identifier, initializer: ts.Expression, extern?: boolean): ts.VariableStatement { 159 return factory.createVariableStatement( 160 extern ? [ExportToken] : [], 161 factory.createVariableDeclarationList( 162 [factory.createVariableDeclaration(name, undefined, undefined, initializer)], 163 ts.NodeFlags.Let, 164 ), 165 ); 166 } 167 168 const resolveFn = factory.createIdentifier('resolve'); 169 const rejectFn = factory.createIdentifier('reject'); 170 171 export function createPromiseOf(...nodes: ts.TypeNode[]): ts.ExpressionWithTypeArguments { 172 return factory.createExpressionWithTypeArguments(PromiseType, nodes); 173 } 174 175 export function createAssignmentStatement(left: ts.Expression, right: ts.Expression): ts.ExpressionStatement { 176 return factory.createExpressionStatement(factory.createAssignment(left, right)); 177 } 178 179 export function createPromiseBody(error: ts.Identifier, statements: ts.Expression[]): ts.ExpressionStatement { 180 return factory.createExpressionStatement( 181 factory.createConditionalExpression( 182 error, 183 QuestionToken, 184 createCall(rejectFn, [error]), 185 ColonToken, 186 createCall(resolveFn, statements ? statements : undefined), 187 ), 188 ); 189 } 190 191 export function rejectOrResolve(error: ts.Identifier, statements: ts.Statement[], success: ts.Expression[]) { 192 return factory.createIfStatement( 193 error, 194 factory.createExpressionStatement(createCall(rejectFn, [error])), 195 factory.createBlock([...statements, factory.createExpressionStatement(createCall(resolveFn, success))]), 196 ); 197 } 198 199 export function CreateNewPromise( 200 body: ts.Statement[], 201 returnType?: ts.TypeNode, 202 multiLine?: boolean, 203 ): ts.NewExpression { 204 return factory.createNewExpression(PromiseType, undefined, [ 205 CreateCallbackDeclaration(resolveFn, rejectFn, body, returnType, multiLine || false), 206 ]); 207 } 208 209 export function CreateCallbackDeclaration( 210 first: ts.Identifier, 211 second: ts.Identifier, 212 body: ts.Statement[], 213 returnType?: ts.TypeNode, 214 multiLine?: boolean, 215 ): ts.ArrowFunction { 216 return factory.createArrowFunction( 217 undefined, 218 undefined, 219 [createParameter(first, undefined), createParameter(second, undefined)], 220 returnType, 221 undefined, 222 factory.createBlock(body, multiLine), 223 ); 224 } 225 226 export function createCallbackType( 227 params: ts.ParameterDeclaration[], 228 type: ts.TypeNode = VoidType, 229 ): ts.FunctionTypeNode { 230 return factory.createFunctionTypeNode(undefined, params, type); 231 } 232 233 function importFrom(pkg: string, ...things: ts.Identifier[]) { 234 return factory.createImportDeclaration( 235 undefined, 236 undefined, 237 factory.createImportClause( 238 false, 239 undefined, 240 factory.createNamedImports(things.map((t) => factory.createImportSpecifier(undefined, t))), 241 ), 242 factory.createStringLiteral(pkg), 243 ); 244 } 245 246 export function importReadable(): ts.ImportDeclaration { 247 return importFrom('stream', ReadableType); 248 } 249 250 export function importBurrow(burrowImportPath: string): ts.ImportDeclaration { 251 return importFrom( 252 burrowImportPath, 253 Address, 254 CancelStreamSignal, 255 ContractCodec, 256 Event, 257 linkerName, 258 listenerForName, 259 Result, 260 keccakName, 261 ); 262 } 263 264 export class Method { 265 readonly id: ts.Identifier; 266 type?: ts.TypeReferenceNode; 267 params: ts.ParameterDeclaration[] = []; 268 ret?: ts.TypeNode; 269 270 constructor(name: string) { 271 this.id = factory.createIdentifier(name); 272 } 273 274 parameter(name: string | ts.Identifier, type: ts.TypeNode, optional?: boolean, isVariadic?: boolean): Method { 275 this.params.push(createParameter(name, type, undefined, optional, isVariadic)); 276 return this; 277 } 278 279 parameters(arg: ts.ParameterDeclaration | ts.ParameterDeclaration[]): Method { 280 if (Array.isArray(arg)) { 281 this.params.push(...arg); 282 } else { 283 this.params.push(arg); 284 } 285 return this; 286 } 287 288 returns(type: ts.TypeNode): Method { 289 this.ret = type; 290 return this; 291 } 292 293 signature(): ts.MethodSignature { 294 return factory.createMethodSignature(undefined, this.id, undefined, undefined, this.params, this.ret); 295 } 296 297 declaration(statements: ts.Statement[], multiLine?: boolean): MethodDeclaration { 298 return factory.createMethodDeclaration( 299 undefined, 300 undefined, 301 undefined, 302 this.id, 303 undefined, 304 undefined, 305 this.params, 306 this.ret, 307 factory.createBlock(statements, multiLine), 308 ); 309 } 310 }