DEV Community 👩‍💻👨‍💻

Cover image for Let's create a React File Manager Chapter XXI: Create Directory In Server
Hasan Zohdy
Hasan Zohdy

Posted on

Let's create a React File Manager Chapter XXI: Create Directory In Server

So we finished the UI part, now we'll create the route and implement it in the server then we'll implement it in the React Project.

// src/controllers/file-manager/createDirectory.ts
import { Request, Response } from "express";

/**
 * Create a directory
 */
export default async function createDirectory(
  request: Request,
  response: Response
) {
  //
}
Enter fullscreen mode Exit fullscreen mode

This was our last code for the create directory, now we need to get from the request the directory name, also the path that we'll create that directory inside it.

// src/controllers/file-manager/createDirectory.ts
import fs from "@mongez/fs";
import makeNode from "app/utils/node";
import { dataPath } from "app/utils/paths";
import { Request, Response } from "express";

/**
 * Create a directory
 */
export default async function createDirectory(
  request: Request,
  response: Response
) {
  // Get the directory name that will be created, also get the path of the directory
  const { name, path } = request.body;

  // now validate the name and path
  if (!name) {
    return response.status(400).json({
      error: "Directory name is required",
    });
  }

  if (!path) {
    return response.status(400).json({
      error: "Directory path is required",
    });
  }

  // check if the path is located in the directory path
  const fullPath = dataPath(path);

  // check if the directory exists
  if (!fs.isDirectory(fullPath)) {
    return response.status(400).json({
      error: "The path is not a directory",
    });
  }

  // check if the directory already exists
  const directoryPath = path + "/" + name;

  const directoryFullPath = dataPath(directoryPath);

  if (fs.isDirectory(directoryFullPath)) {
    return response.status(400).json({
      error: "The directory already exists",
    });
  }

  // now create the directory
  fs.makeDirectory(directoryFullPath);

  // return the directory as node

  return response.json({
    node: makeNode(directoryPath),
  });
}
Enter fullscreen mode Exit fullscreen mode

So what we've done here is five things:

  1. We've checked if the name and path are valid.
  2. We've checked if the path is a directory.
  3. We've checked if the directory already exists.
  4. We've created the directory.
  5. We've returned the directory as node.

Another thing to mention here, and also to acknowledge, is we need to tell express server that we're going to receive json data, so we need to add the following code to the src/index.ts file.

// src/index.ts
...

// create express app
const app: Express = express();

// 👇🏻 tell express to receive json data
app.use(express.json());
Enter fullscreen mode Exit fullscreen mode

Now we can give it a quick try from our React project, open home page and add the following code above the home page component.

Don't forget to restart the backend server if you was running it while you're developing.

// HomePage.tsx
import endpoint from "@mongez/http";

endpoint.post("/file-manager/directory", {
  path: "/",
  name: "new-directory",
});
Enter fullscreen mode Exit fullscreen mode

Then check the response, it should be the directory as node.

Request Body

You see the directory has two slashes //new-directory this is because the path is / and we're adding another / so it duplicates two slashes.

Let's install a small package to manage this issue.

yarn add @mongez/concat-route

Now let's update the function again.

// src/controllers/file-manager/createDirectory.ts

// 👇🏻 import the package
import concatRoute from "@mongez/concat-route";
import fs from "@mongez/fs";
import makeNode from "app/utils/node";
import { dataPath } from "app/utils/paths";
import { Request, Response } from "express";

/**
 * Create a directory
 */
export default async function createDirectory(
  request: Request,
  response: Response
) {
  // Get the directory name that will be created, also get the path of the directory
  const { name, path } = request.body;

  // now validate the name and path
  if (!name) {
    return response.status(400).json({
      error: "Directory name is required",
    });
  }

  if (!path) {
    return response.status(400).json({
      error: "Directory path is required",
    });
  }

  // check if the path is located in the directory path
  const fullPath = dataPath(path);

  // check if the directory exists
  if (!fs.isDirectory(fullPath)) {
    return response.status(400).json({
      error: "The path is not a directory",
    });
  }

  // check if the directory already exists
  // 👇🏻 use the package to concat the path and name instead of adding them manually
  const directoryPath = concatRoute(path, name);

  const directoryFullPath = dataPath(directoryPath);

  if (fs.isDirectory(directoryFullPath)) {
    return response.status(400).json({
      error: "The directory already exists",
    });
  }

  // now create the directory
  fs.makeDirectory(directoryFullPath);

  // return the directory as node

  return response.json({
    node: makeNode(directoryPath),
  });
}
Enter fullscreen mode Exit fullscreen mode

Now restart the server and let's try again to create new-directory-2.

Success Request

Much better, let's use the same function in makeNode function

// src/utils/node.ts
// import the Node type from the client directory xD
import concatRoute from "@mongez/concat-route";
import { isDirectory, size } from "@mongez/fs";
import { Node } from "./../../../client/src/apps/front-office/file-manager/Kernel/Kernel.types";
import { dataPath } from "./paths";

export type { Node };

/**
 * Generate a node object to the given path,
 * the given path should be relative to the data directory
 */
export default function makeNode(path: string, children?: string[]): Node {
  // get the full path of the node
  const fullPath = dataPath(path);

  const node: Node = {
    path,
    name: path.split("/")?.pop() || "/",
    isDirectory: isDirectory(fullPath),
    size: size(fullPath),
  };

  if (node.isDirectory) {
    node.children = (children || []).map((child) =>
      // 👇🏻 we need to check if the path is the root then we will just append it to the child
      // if its not the root then we need to append `/` to the path and then append the child
      // 👉🏻 the old one makeNode((path === "/" ? path : path + "/") + child)
      // 👇🏻 more readable and cleaner
      makeNode(concatRoute(path, child))
    );
  }

  return node;
}
Enter fullscreen mode Exit fullscreen mode

Next Chapter

In the next chapter we'll make the request in our react project in createDirectory action.

Article Repository

You can see chapter files in Github Repository

Don't forget the main branch has the latest updated code.

Tell me where you are now

If you're following up with me this series, tell me where are you now and what you're struggling with, i'll try to help you as much as i can.

Salam.

Top comments (0)

Every Week

We have a Welcome Thread where we invite members to tell us a bit about themselves. Join the conversation with us!