Skip to main content

hypermod/utils

Hypermod provides a set of utilities to help perform common codemod operations.

Installation

@hypermod/utils is pre-bundled with every codemod that is published to the public registry, so there's no need to install it manually.

However, it is also available for use outside of this project and compatible with jscodeshift.

npm install --save-dev @hypermod/utils or yarn add -D @hypermod/utils

Nodes

isNodeOfType

isNodeOfType(node, type)

The isNodeOfType function uses generics to check if a node of type ASTNode is of a specified type. If the check passes, the type of node is narrowed to the expected type, ensuring that the returned type of the function is always correct.

Returns

boolean

Example

const isImportSpecifier = isNodeOfType(node, 'ImportSpecifier');

isDecendantOfType

isDecendantOfType(j, path, type)

The isDecendantOfType function traverses the AST to determind if the given path is a child of a node of the specified type.

Returns

boolean

Example

const isChildOfImportSpecifier = isDecendantOfType(j, path, j.ImportSpecifier);

Imports

hasImportDeclaration

hasImportDeclaration(j, source, sourcePath)

Finds an import declaration by source name

Returns

boolean

Example

// src/App.js
import React from 'react';
import { hasImportDeclaration } from '@hypermod/utils';

hasImportDeclaration(j, source, 'react'); // True

getImportDeclaration

getImportDeclaration(j, source, sourcePath)

Returns an import declaration by source name

Returns

Collection: Collection containing 1 or more imports

Example

// src/App.js
import React from 'react';
import { getImportDeclaration } from '@hypermod/utils';

getImportDeclaration(j, source, 'react');

removeImportDeclaration

removeImportDeclaration(j, source, sourcePath)

Removes an import declaration by source name

Returns

void

Example

// src/App.js
import React from 'react';
import { removeImportDeclaration } from '@hypermod/utils';

removeImportDeclaration(j, source, 'react');
// src/App.js
-import React, { useEffect } from 'react';

renameImportDeclaration

renameImportDeclaration(j, source, sourcePath, newSourcePath)

Renames an import declaration by source name

Returns

void

Example

// src/App.js
import React from 'react';
import { renameImportDeclaration } from '@hypermod/utils';

renameImportDeclaration(j, source, 'react', 'preact');
// src/App.js
-import React, { useEffect } from 'react';
+import React, { useEffect } from 'preact';

getDefaultImportSpecifier

getDefaultImportSpecifier(j, source, sourcePath)

Finds a default import specifier

Returns

Collection: Collection containing all matched default import specifiers

Example

// src/App.js
import React from 'react';
import { getDefaultImportSpecifier } from '@hypermod/utils';

getDefaultImportSpecifier(j, source, 'react'); // Collection containing 'React'

getDefaultImportSpecifierName

getDefaultImportSpecifierName(j, source, sourcePath)

Finds a default import specifier and returns its name

Returns

string | null: Default import's name

Example

// src/App.js
import React from 'react';
import { getDefaultImportSpecifierName } from '@hypermod/utils';

getDefaultImportSpecifierName(j, source, 'react'); // Collection containing 'React'

hasDefaultImportSpecifier

hasDefaultImportSpecifier(j, source, sourcePath)

Attempts to find a default import specifier and returns a boolean result

Returns

boolean

Example

// src/App.js
import React from 'react';
import { hasDefaultImportSpecifier } from '@hypermod/utils';

hasDefaultImportSpecifier(j, source, 'react'); // True

removeDefaultImportSpecifier

removeDefaultImportSpecifier(j, source, sourcePath)

Attempts to remove a default import specifier

Returns

void

Example

// src/App.js
import React, { useEffect } from 'react';
import { removeDefaultImportSpecifier } from '@hypermod/utils';

removeDefaultImportSpecifier(j, source, 'React');
-import React, { useEffect } from 'react';
+import { useEffect } from 'react';

hasImportSpecifier

hasImportSpecifier(j, source, sourcePath)

Checks for an import import specifier

Returns

boolean

Example

// src/App.js
import React, { useEffect } from 'react';
import { hasImportSpecifier } from '@hypermod/utils';

hasImportSpecifier(j, source, 'react', 'useEffect'); // True

getImportSpecifier

getImportSpecifier(j, specifier, source)

Finds an import specifier by name

Returns

Collection: Collection containing all matched import specifiers

Example

// src/App.js
import React, { useEffect } from 'react';
import { getImportSpecifier } from '@hypermod/utils';

getImportSpecifier(j, source, 'useEffect'); // Collection containing 'useEffect'

getImportSpecifierName

getImportSpecifierName(j, specifier, source)

Returns the local name of an import. This is useful for cases where an import specifier is potentially aliased.

Returns

string | null: specifier name or null if not found

Example

// src/App.js
import React, { useEffect as foo } from 'react';
import { getImportSpecifierName } from '@hypermod/utils';

getImportSpecifierName(j, source, 'useEffect', 'react'); // 'foo'

insertImportSpecifier

insertImportSpecifier(j, source, specifier)

Inserts an import specifier

Returns

void

Example

// src/App.js
import React, { useEffect } from 'react';
import { insertImportSpecifier } from '@hypermod/utils';

insertImportSpecifier(j, source, 'useMemo', 'react'); // Collection containing 'useEffect'
// src/App.js
-import React, { useEffect } from 'react';
+import React, { useEffect, useMemo } from 'react';

removeImportSpecifier

removeImportSpecifier(j, source, specifier)

Removes an import specifier

Returns

void

Example

// src/App.js
import React, { useEffect } from 'react';
import { removeImportSpecifier } from '@hypermod/utils';

removeImportSpecifier(j, source, 'useMemo', 'react'); // Collection containing 'useEffect'
// src/App.js
-import React, { useEffect } from 'react';
+import React, { useEffect, useMemo } from 'react';

JSX

getJSXAttributes

getJSXAttributes(j, source, attributeName)

Finds a JSX attributeName (aka prop) by name

Returns

Collection: Collection containing all matched jsx attributes

Example

// src/App.js
import React from 'react';

const App = () => <Button primary>Say hello</Button>;
import { getJSXAttributes } from '@hypermod/utils';

getJSXAttributes(j, source, 'primary'); // Collection containing 'primary'

hasJSXAttributes

hasJSXAttributes(j, source, attributeName)

Finds a JSX attributeName (aka prop) by name and returns true if found

Returns

boolean

Example

// src/App.js
import React from 'react';

const App = () => <Button primary>Say hello</Button>;
import { hasJSXAttributes } from '@hypermod/utils';

hasJSXAttributes(j, source, 'primary'); // Found!

Comments

insertCommentBefore

insertCommentBefore(j, source, message, prefix)

Appends a comment before the provided node

Returns

void

Example

// src/App.js
import React from 'react';

const App = () => <Button primary>Say hello</Button>;
import { insertCommentBefore } from '@hypermod/utils';

insertCommentBefore(
j,
path.find(j.ImportDeclaration),
'This should be removed in favour of mylib',
);
// src/App.js
import React from 'react';

// TODO: (@hypermod) This should be removed in favour of mylib
const App = () => <Button primary>Say hello</Button>;

insertCommentToStartOfFile

insertCommentToStartOfFile(j, source, message)

Appends a comment to the start of a file

Returns

void

Example

// src/App.js
import React from 'react';

const App = () => <Button primary>Say hello</Button>;
import { insertCommentToStartOfFile } from '@hypermod/utils';

insertCommentToStartOfFile(
j,
path.find(j.ImportDeclaration),
'This should be removed in favour of mylib',
);
// src/App.js
// TODO: (Codemod) This should be removed in favour of mylib
import React from 'react';

const App = () => <Button primary>Say hello</Button>;

Motions

applyMotions

applyMotions(j, source, motions)

A helper function to apply an array of motions in sequence.

Returns

void

Example

import { applyMotions } from '@hypermod/utils';
import { sortImports } from './motions';

applyMotions(j, j(fileInfo.source), [sortImports, removeVar]);

Testing

applyTransform

applyTransform(transform, input, options = { parser: 'babel' })

Runs a transform against the provided code and returns the resulting file.

We provide this method as opposed to jscodeshift's test utils to maintain jest's skip/only and snapshot features

Returns

Promise<string>: Resulting file after transform has been applied

Example

import * as transformer from '../transform';
import { applyTransform } from '@hypermod/utils';

it('should wrap avatar in a tooltip if name is defined', async () => {
const result = await applyTransform(
transformer,
`
import Avatar from 'avatar';

const App = () => {
return <Avatar name="foo" />;
}
`,
{ parser: 'tsx' },
);

expect(result).toMatchInlineSnapshot(`
"import Tooltip from 'tooltip';
import Avatar from 'avatar';

const App = () => {
return <Tooltip content=\\"foo\\"><Avatar name=\\"foo\\" /></Tooltip>;
}"
`);
});