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.
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'
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[]
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)
}
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'
}
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:
Top comments (0)