DEV Community

Cover image for The Domain: Building my File Organizer (Part 2)
Oscar Lopez
Oscar Lopez

Posted on

The Domain: Building my File Organizer (Part 2)

The first part, in my case, was to give shape to the project in my Notion by putting the things that i want to the project theree.

I believe it's crucial to have a clear idea of the features and how to implement them. However, I understand that this may not always be possible.

My notion dashboard in spanish

In my case, the logic es very simple .
Starting from a base directory, recursively going through the directory tree and files checking if the files match the organization criteria.

Now, we have two very simple concepts for the project:

  • recursivity
  • The organization logic

Once that is defined, we can start to shape the structures.
In this project I will use Typescript, so the first step is to shape the organization options:

  • The file name contains
  • The file extension is
  • The file name ends with
  • The file name starts with
  • The file extension is in this group

Conditions

For this, i'm going to use String Literal Types

// Conditions.ts 
export type Conditions = 
  'File Name Contains'
  | 'Extension'
  | 'File Name Ends With'
  | 'File Name Starts With'
Enter fullscreen mode Exit fullscreen mode

Pattern

After that, to enhance the semantics of the types, I will rename string as Pattern.
This is only to identify better the type of string that contain that type and if after we add Branded Types.
A Pattern is a string that represents the custom text, extension, etc. that the filename should match. For example, a condition where the filename should contain the word "Homework" to move it.

// Pattern.ts
export type Pattern = string[] 
Enter fullscreen mode Exit fullscreen mode

PathString

One of the things the program should do is move files to other directories. Therefore, it is a good idea to ensure that the destination directories exist. To accomplish this I will use a Branded Type and a library named NeverThrow to avoid throw Exceptions and move the error handling to the typed.

import { Result, ok, err } from "neverthrow"; 
// Utility Function to check if a directory exists
import { directoryExists } from "../Utils/Directory.ts";

// Brand
type PathBrand = { readonly path: unique symbol }

// Possible Errors
export type PathErrors = 'Directory Not Found'

// Branded Type
export type PathString = string & PathBrand

// Function to create the Branded Type, to make sure that the string has the featuares that we need 
// In my case, we want to check if the directory exists, and, return a Result in case that an error ocurrs
export const createPathString = async (str: string): Promise<Result<PathString,PathErrors>> => {
  const directoryExists_ = await directoryExists(str)
  if(!directoryExists_) return err('Directory Not Found')
  return ok(str as PathString)
}

Enter fullscreen mode Exit fullscreen mode

Rule

The last structure, a Rule will be the representation of what i want to do with a file, for examplee, move it or delete it, and also it would have all the information that i need to perform the action, in the case of move it the destination directory.

type MoveRule = {
  action: 'Move To', 
  destination: PathString 
}

type DeleteRule = {
  action: 'Delete' 
}
Enter fullscreen mode Exit fullscreen mode

Conclusions

This has been my progress during the week. I haven't had as much time as I would have liked, but it's taking shape. For now, I have defined how the actions of the program will be structured, the next step is to begin giving it some behavior and testing.

This is a series of articles to document my software creation process. I'm leaving you the links to the previous and next entries:

Prev

Top comments (0)