diff --git a/__fixtures__/v-next/outputosmojs/ibc/applications/fee/v1/query.lcd.ts b/__fixtures__/v-next/outputosmojs/ibc/applications/fee/v1/query.lcd.ts index 80256b2223..324c300921 100644 --- a/__fixtures__/v-next/outputosmojs/ibc/applications/fee/v1/query.lcd.ts +++ b/__fixtures__/v-next/outputosmojs/ibc/applications/fee/v1/query.lcd.ts @@ -46,7 +46,7 @@ export class LCDQueryClient { if (typeof params?.queryHeight !== "undefined") { options.params.query_height = params.queryHeight; } - const endpoint = `ibc/apps/fee/v1/channels/${params.packetId.channel_id}/ports/${params.packetId.port_id}/sequences/${params.packetId.sequence}/incentivized_packet`; + const endpoint = `ibc/apps/fee/v1/channels/${params.packet_id.channel_id}/ports/${params.packet_id.port_id}/sequences/${params.packet_id.sequence}/incentivized_packet`; return QueryIncentivizedPacketResponse.fromSDKJSON(await this.req.get(endpoint, options)); } /* Gets all incentivized packets for a specific channel */ @@ -65,17 +65,17 @@ export class LCDQueryClient { } /* TotalRecvFees returns the total receive fees for a packet given its identifier */ async totalRecvFees(_params: QueryTotalRecvFeesRequest = {}): Promise { - const endpoint = `ibc/apps/fee/v1/channels/${params.packetId.channel_id}/ports/${params.packetId.port_id}/sequences/${params.packetId.sequence}/total_recv_fees`; + const endpoint = `ibc/apps/fee/v1/channels/${params.packet_id.channel_id}/ports/${params.packet_id.port_id}/sequences/${params.packet_id.sequence}/total_recv_fees`; return QueryTotalRecvFeesResponse.fromSDKJSON(await this.req.get(endpoint)); } /* TotalAckFees returns the total acknowledgement fees for a packet given its identifier */ async totalAckFees(_params: QueryTotalAckFeesRequest = {}): Promise { - const endpoint = `ibc/apps/fee/v1/channels/${params.packetId.channel_id}/ports/${params.packetId.port_id}/sequences/${params.packetId.sequence}/total_ack_fees`; + const endpoint = `ibc/apps/fee/v1/channels/${params.packet_id.channel_id}/ports/${params.packet_id.port_id}/sequences/${params.packet_id.sequence}/total_ack_fees`; return QueryTotalAckFeesResponse.fromSDKJSON(await this.req.get(endpoint)); } /* TotalTimeoutFees returns the total timeout fees for a packet given its identifier */ async totalTimeoutFees(_params: QueryTotalTimeoutFeesRequest = {}): Promise { - const endpoint = `ibc/apps/fee/v1/channels/${params.packetId.channel_id}/ports/${params.packetId.port_id}/sequences/${params.packetId.sequence}/total_timeout_fees`; + const endpoint = `ibc/apps/fee/v1/channels/${params.packet_id.channel_id}/ports/${params.packet_id.port_id}/sequences/${params.packet_id.sequence}/total_timeout_fees`; return QueryTotalTimeoutFeesResponse.fromSDKJSON(await this.req.get(endpoint)); } /* Payee returns the registered payee address for a specific channel given the relayer address */ diff --git a/packages/ast/package.json b/packages/ast/package.json index 155ed78fe8..0cd89c78fa 100644 --- a/packages/ast/package.json +++ b/packages/ast/package.json @@ -62,18 +62,19 @@ "url": "https://github.com/cosmology-tech/telescope/issues" }, "devDependencies": { + "@babel/parser": "^7.23.6", "@cosmology/proto-parser": "^1.5.3", "@types/jest": "^29.5.0", "ast-stringify": "0.1.0", "cross-env": "^7.0.2", "deepmerge": "4.3.1", - "eslint": "8.38.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-prettier": "^4.0.0", + "eslint": "8.38.0", "esprima": "4.0.1", "glob": "8.0.3", - "jest": "^29.5.0", "jest-in-case": "^1.0.2", + "jest": "^29.5.0", "mkdirp": "3.0.0", "prettier": "^2.8.7", "regenerator-runtime": "^0.13.11", @@ -82,11 +83,10 @@ "typescript": "5.0.4" }, "dependencies": { - "@babel/parser": "^7.23.6", "@babel/types": "7.23.6", "@cosmology/types": "^1.5.3", "@cosmology/utils": "^1.5.3", "case": "1.6.3", "dotty": "0.1.2" } -} +} \ No newline at end of file diff --git a/packages/ast/src/clients/lcd/class/__snapshots__/lcd.test.ts.snap b/packages/ast/src/clients/lcd/class/__snapshots__/lcd.test.ts.snap index 58c8f70aea..62ab620754 100644 --- a/packages/ast/src/clients/lcd/class/__snapshots__/lcd.test.ts.snap +++ b/packages/ast/src/clients/lcd/class/__snapshots__/lcd.test.ts.snap @@ -758,5 +758,3 @@ exports[`service info template 5`] = ` ], } `; - -exports[`template tags 1`] = `"\`/\${params.cosmos}/feegrant/v1beta1/\${params.allowance}/\${params.granter}/\${params.grantee}\`"`; diff --git a/packages/ast/src/clients/lcd/class/lcd.keepCase.test.ts b/packages/ast/src/clients/lcd/class/lcd.keepCase.test.ts index d482c4bfe4..5cf97c8308 100644 --- a/packages/ast/src/clients/lcd/class/lcd.keepCase.test.ts +++ b/packages/ast/src/clients/lcd/class/lcd.keepCase.test.ts @@ -1,16 +1,13 @@ import { - getUrlTemplateString, - createAggregatedLCDClient, - createLCDClient, - makeTemplateTagLegacy + createLCDClient } from './lcd'; import { traverse } from '@cosmology/proto-parser' import { getNestedProto } from '@cosmology/utils' import { defaultTelescopeOptions, ProtoService } from '@cosmology/types'; -import generate from '@babel/generator'; import { GenericParseContext } from '../../../encoding'; import { getTestProtoStore, expectCode, printCode } from '../../../../test-utils'; const store = getTestProtoStore(); +// @ts-ignore store.options.prototypes.parser.keepCase = true; store.traverseAll(); diff --git a/packages/ast/src/clients/lcd/class/lcd.test.ts b/packages/ast/src/clients/lcd/class/lcd.test.ts index b271d1892f..1254d3e8ca 100644 --- a/packages/ast/src/clients/lcd/class/lcd.test.ts +++ b/packages/ast/src/clients/lcd/class/lcd.test.ts @@ -1,15 +1,12 @@ import { getUrlTemplateString, - createAggregatedLCDClient, - createLCDClient, - makeTemplateTagLegacy + createLCDClient } from './lcd'; import { traverse } from '@cosmology/proto-parser' import { getNestedProto } from '@cosmology/utils' import { defaultTelescopeOptions, ProtoService } from '@cosmology/types'; -import generate from '@babel/generator'; import { GenericParseContext } from '../../../encoding'; -import { getTestProtoStore, expectCode, printCode } from '../../../../test-utils'; +import { getTestProtoStore, expectCode } from '../../../../test-utils'; const store = getTestProtoStore(); store.traverseAll(); @@ -21,20 +18,6 @@ it('service info template', () => { expect(getUrlTemplateString('/cosmos/feegrant/v1beta1/allowance/{granter}/{grantee}')).toMatchSnapshot(); }); -it('template tags', () => { - const info = { - url: '/{cosmos}/feegrant/v1beta1/{allowance}/{granter}/{grantee}', - pathParams: [ - 'cosmos', - 'allowance', - 'granter', - 'grantee' - ] - }; - // @ts-ignore - expectCode(makeTemplateTagLegacy(info)); -}) - it('osmosis LCDClient', () => { const ref = store.findProto('osmosis/gamm/v1beta1/query.proto'); const res = traverse(store, ref); diff --git a/packages/ast/src/clients/lcd/class/lcd.ts b/packages/ast/src/clients/lcd/class/lcd.ts index 2de8ab5735..87067ba23f 100644 --- a/packages/ast/src/clients/lcd/class/lcd.ts +++ b/packages/ast/src/clients/lcd/class/lcd.ts @@ -3,28 +3,6 @@ import { ProtoService, ProtoServiceMethod, ProtoServiceMethodInfo } from '@cosmo import { GenericParseContext } from '../../../encoding'; import { arrowFunctionExpression, callExpression, classMethod, classProperty, identifier, objectPattern } from '../../../utils'; -// this is the ONLY time ast uses babel/parser -import { parse } from '@babel/parser'; - -const getAstFromString = (str: string) => { - const plugins = [ - 'objectRestSpread', - 'classProperties', - 'optionalCatchBinding', - 'asyncGenerators', - 'decorators-legacy', - 'typescript', - 'dynamicImport' - ]; - const ast = parse(str, { - sourceType: 'module', - // @ts-ignore - plugins - }); - return ast; -}; - - const getResponseTypeName = ( context: GenericParseContext, name: string @@ -254,7 +232,7 @@ export const getUrlTemplateString = (url: string) => { }; const routeRegexForReplace = /[^\{\}\\-\_\\.$/a-zA-Z0-9]+/g; -export const makeTemplateTag = (info: ProtoServiceMethodInfo) => { +export function makeTemplateTag(info: ProtoServiceMethodInfo, noLeadingSlash: boolean = true): t.TemplateLiteral { const route = info.url .split('/') .filter(a => a !== '') @@ -262,93 +240,44 @@ export const makeTemplateTag = (info: ProtoServiceMethodInfo) => { if (a.startsWith('{')) { // clean weird routes like this one: // /ibc/apps/transfer/v1/denom_traces/{hash=**} - return `$${a}` - .replace(routeRegexForReplace, '') - .replace('{', `{params.`) + return a.replace(routeRegexForReplace, '') } else { return a; } }) .join('/'); - - // clean route here - - const parsed = getAstFromString(`\`${route}\``); - // @ts-ignore - const ast: t.TemplateLiteral = parsed.program.body[0].expression; - - ast.expressions = ast.expressions.map((expr: t.MemberExpression) => { - let name; - switch (expr.object.type) { - case 'MemberExpression': { - // e.g. params.thing.another - const memberExpr: t.MemberExpression = expr.object; - // @ts-ignore - name = memberExpr.property.name; - name = info.casing?.[name] ? info.casing[name] : name; - // @ts-ignore - expr.object.property.name = name; - break; - } - case 'Identifier': { - // e.g. params.thing - // @ts-ignore - const identifier: t.Identifier = expr.property; - name = identifier.name; - name = info.casing?.[name] ? info.casing[name] : name; - // @ts-ignore - expr.property.name = name; - break; - } - case 'Identifier': - break; - default: - throw new Error('unknown expression type in route parsing'); + const segments = route.split('/'); + const expressions: (t.Identifier | t.MemberExpression)[] = []; + const quasis = []; + let accumulatedPath = ''; + let isFirst = true; + + segments.forEach((segment, _index) => { + if (noLeadingSlash && segment === '') return; + + if (segment.startsWith('{') && segment.endsWith('}')) { + // Dynamic segment + const paramName = segment.slice(1, -1); + // Push the accumulated static text as a quasi before adding the expression + quasis.push(t.templateElement({ raw: accumulatedPath + '/', cooked: accumulatedPath }, false)); + accumulatedPath = ''; // Reset accumulated path after adding to quasis + + // expressions.push(t.identifier(`params.${paramName}`)); + expressions.push(t.memberExpression(t.identifier('params'), t.identifier(info.casing?.[paramName] ? info.casing[paramName] : paramName))); + // Prepare the next quasi to start with a slash if this is not the last segment + isFirst = false; + } else { + // Accumulate static text, ensuring to prepend a slash if it's not the first segment + accumulatedPath += (isFirst ? '' : '/') + segment; + isFirst = false; } - return expr; - }).filter(Boolean); - return ast; -}; - -// do we need to set end prop in ast? -// we may want to t.templateElement!!! -export const makeTemplateTagLegacy = (info: ProtoServiceMethodInfo) => { - if (!info.url) throw new Error('no URL on service method'); - - const parts = getUrlTemplateString(info.url); - const templateElts = parts.strs.map(raw => t.templateElement({ raw })) - - // Number of TemplateLiteral quasis should be exactly one more than the number of expressions - - const pathParams = info.pathParams.map(param => { - const name = info.casing?.[param] ? info.casing[param] : param; - return t.memberExpression( - t.identifier('params'), - t.identifier(name) - ); }); - if (parts.atEnd) { - templateElts.push(t.templateElement({ raw: '' })); - } - - // THIS MEANS WE PROBABLY HAVE A BUG - if (templateElts.length !== pathParams.length + 1) { - templateElts.push(t.templateElement({ raw: '' })); - } - - templateElts.forEach((el, n) => { - if (n === templateElts.length - 1) { - // remove trailing slash... - el.value.raw = el.value.raw.replace(/\/$/, ''); - } - }); + // Add the final accumulated static text as the last quasi + quasis.push(t.templateElement({ raw: accumulatedPath, cooked: accumulatedPath }, true)); // Mark the last quasi as tail - return t.templateLiteral( - templateElts, - pathParams - ); -}; + return t.templateLiteral(quasis, expressions); +} const makeComment = (comment: string) => { return [{ type: 'CommentBlock', value: ` ${comment} ` }] @@ -416,10 +345,10 @@ const buildRequestMethod = ( t.objectProperty( t.identifier('pagination'), paginationDefaultFromPartial ? t.callExpression( - t.memberExpression(t.identifier("PageRequest"), t.identifier("fromPartial")), - [t.objectExpression([])] + t.memberExpression(t.identifier("PageRequest"), t.identifier("fromPartial")), + [t.objectExpression([])] ) : - t.identifier('undefined'), + t.identifier('undefined'), false, false ) diff --git a/packages/ast/types/clients/lcd/class/lcd.d.ts b/packages/ast/types/clients/lcd/class/lcd.d.ts index 2c76dc09af..4888289f06 100644 --- a/packages/ast/types/clients/lcd/class/lcd.d.ts +++ b/packages/ast/types/clients/lcd/class/lcd.d.ts @@ -5,7 +5,6 @@ export declare const getUrlTemplateString: (url: string) => { strs: any[]; atEnd: boolean; }; -export declare const makeTemplateTag: (info: ProtoServiceMethodInfo) => t.TemplateLiteral; -export declare const makeTemplateTagLegacy: (info: ProtoServiceMethodInfo) => t.TemplateLiteral; +export declare function makeTemplateTag(info: ProtoServiceMethodInfo, noLeadingSlash?: boolean): t.TemplateLiteral; export declare const createLCDClient: (context: GenericParseContext, service: ProtoService) => t.ExportNamedDeclaration; export declare const createAggregatedLCDClient: (context: GenericParseContext, services: ProtoService[], clientName: string) => t.ExportNamedDeclaration;