pankod/refine

View on GitHub
packages/cli/src/transformers/resource.ts

Summary

Maintainability
B
4 hrs
Test Coverage
import {
  API,
  FileInfo,
  JSXAttribute,
  JSXExpressionContainer,
  ArrayExpression,
} from "jscodeshift";

export const parser = "tsx";

export default function transformer(file: FileInfo, api: API, options: any) {
  const j = api.jscodeshift;
  const source = j(file.source);

  const rootElement = source.find(j.JSXElement, {
    openingElement: {
      name: {
        name: "Refine",
      },
    },
  });

  if (rootElement.length === 0) {
    return;
  }

  // prepare actions
  const actions = options.__actions.split(",");

  const getPath = (resourceName: string, action: string) => {
    if (action === "list") {
      return `/${resourceName}`;
    }

    if (action === "create") {
      return `/${resourceName}/create`;
    }

    if (action === "edit") {
      return `/${resourceName}/edit/:id`;
    }

    if (action === "show") {
      return `/${resourceName}/show/:id`;
    }

    return `/${resourceName}`;
  };

  const resourceProperty = [
    j.property(
      "init",
      j.identifier("name"),
      j.stringLiteral(options.__resourceName),
    ),
  ];

  actions.map((item: string) => {
    resourceProperty.push(
      j.property(
        "init",
        j.identifier(item),
        j.stringLiteral(getPath(options.__resourceName, item)),
      ),
    );
  });

  rootElement.replaceWith((path) => {
    const attributes = path.node.openingElement.attributes;
    if (!attributes) {
      return path.node;
    }

    const resourcePropIndex = attributes.findIndex(
      (attr) => attr.type === "JSXAttribute" && attr.name.name === "resources",
    );

    const resourceObjectExpression = j.objectExpression(resourceProperty);

    // if no resources prop, add it
    if (resourcePropIndex === -1) {
      attributes.push(
        j.jsxAttribute(
          j.jsxIdentifier("resources"),
          j.jsxExpressionContainer(
            j.arrayExpression([resourceObjectExpression]),
          ),
        ),
      );

      return path.node;
    }

    const resourceValue = (attributes[resourcePropIndex] as JSXAttribute)
      .value as JSXExpressionContainer;

    // resources={RESOURCE_CONSTANT} => resources={[...RESOURCE_CONSTANT, {name: "post", list: List}]}
    if (resourceValue.expression.type === "Identifier") {
      attributes[resourcePropIndex] = j.jsxAttribute(
        j.jsxIdentifier("resources"),
        j.jsxExpressionContainer(
          j.arrayExpression([
            j.spreadElement(resourceValue.expression),
            resourceObjectExpression,
          ]),
        ),
      );

      return path.node;
    }

    // resources={[...resources]} => resources={[...resources, {name: "post", list: List}]}
    const resourceArray = resourceValue.expression as ArrayExpression;
    resourceArray.elements.push(resourceObjectExpression);

    return path.node;
  });

  return source.toSource();
}