UNPKG

@spotinst/spinnaker-deck

Version:

Spinnaker-Deck service, forked with support to Spotinst

99 lines (85 loc) 3.28 kB
'use strict'; // @ts-check /** * Migrate REST().path('foo', 'bar').path('baz').get() to REST('/foo/bar/baz').get() * * @typedef {import('estree').Arg} CallExpression * @typedef {import('estree').Literal} Literal * @typedef {import('estree').ImportSpecifier} ImportSpecifier */ const _ = require('lodash/fp'); const { getNodeType, getCallChain, getCallingIdentifierName } = require('../utils/utils'); const getCallName = _.get('callee.property.name'); /** @type {RuleModule} */ module.exports = { create(context) { return { /** * Look for chains of CallExpressions that are part of a REST().path() call * @param node {CallExpression} */ CallExpression(node) { const callingIdentifierName = getCallingIdentifierName(node); if (node.parent.type === 'MemberExpression' || callingIdentifierName !== 'REST') { return undefined; } // an array of CallExpressions, i.e. for API.one().all().get() -> [.one, .all, .get] const callChain = getCallChain(node); // Look for a REST().path().whatever() call if (!callChain[1] || getCallName(callChain[1]) !== 'path') { return; } /** @type {CallExpression} */ const restCall = callChain[0]; /** @type {CallExpression} */ const pathCall = callChain[1]; /** @type {Literal} */ const restArg = restCall.arguments[0]; /** @type {Literal} */ const firstPathArg = pathCall.arguments[0]; // Only REST('literal').path('literal', ...) // Ignores: REST(variable) and REST().path(variable) if ((restArg && restArg.type !== 'Literal') || getNodeType(firstPathArg) !== 'Literal') { return undefined; } const message = `Prefer REST('/foo/bar') over REST().path('foo', 'bar')`; function fix(fixer) { const fixes = []; const restCallEnd = restCall.range[1]; if (restArg) { // REST('/foo').path('bar') // Join '/foo' and '/bar' and replace the rest arg // REST('/foo/bar').path('bar'); fixes.push(fixer.replaceText(restArg, `'${restArg.value}/${firstPathArg.value}'`)); } else { // REST().path('foo') // Insert text between the parentheses // REST('foo').path('foo'); fixes.push(fixer.insertTextAfterRange([restCallEnd - 1, restCallEnd - 1], `'/${firstPathArg.value}'`)); } if (pathCall.arguments.length === 1) { // REST('foo').path('foo'); // Remove the entire .path() call // REST('foo'); fixes.push(fixer.removeRange([restCallEnd, pathCall.range[1]])); } else { /** @type {Literal} */ const secondPathArg = pathCall.arguments[1]; // Remove the first .path() call argument fixes.push(fixer.removeRange([firstPathArg.range[0], secondPathArg.range[0]])); } return fixes; } context.report({ node, message, fix }); }, }; }, meta: { fixable: 'code', type: 'problem', docs: { description: 'Migrate from API.xyz() to REST(path)', recommended: 'error', }, }, };