Skip to content

Commit

Permalink
Hot-Reloading Feature Implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
mohamedsalem401 committed Nov 4, 2023
1 parent abaed38 commit a7fa720
Show file tree
Hide file tree
Showing 15 changed files with 1,197 additions and 231 deletions.
82 changes: 70 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"types": "./dist/src/index.d.ts",
"dependencies": {
"@portaljs/remark-wiki-link": "^1.0.4",
"chokidar": "^3.5.3",
"gray-matter": "^4.0.3",
"knex": "^2.4.2",
"remark-gfm": "^3.0.1",
Expand Down
24 changes: 21 additions & 3 deletions src/bin/index.js → src/bin/index.ts
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,23 @@ import { MarkdownDB } from "../lib/markdowndb.js";
// TODO get these from markdowndb.config.js or something
const dbPath = "markdown.db";
const ignorePatterns = [/Excalidraw/, /\.obsidian/, /DS_Store/];
const [contentPath] = process.argv.slice(2);
const args = process.argv.slice(2);

let watch = false;
let contentPath;

// Iterate through the command-line arguments
for (let i = 0; i < args.length; i++) {
const arg = args[i];

if (arg === "--watch" || arg === "-w") {
// If --watch or -w is provided, set the watch flag to true
watch = true;
} else {
// If not an option, assume it's the contentPath
contentPath = arg;
}
}

if (!contentPath) {
throw new Error("Invalid/Missing path to markdown content folder");
Expand All @@ -18,11 +34,13 @@ const client = new MarkdownDB({
},
});

// Ignore top-level await errors
//@ts-ignore
await client.init();

//@ts-ignore
await client.indexFolder({
folderPath: contentPath,
ignorePatterns: ignorePatterns,
watch: watch,
});

process.exit();
72 changes: 72 additions & 0 deletions src/bin/watch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import chokidar from "chokidar";
import { generateFileIdFromPath } from "../lib/markdowndb.js";
import { markdownToJson } from "../lib/markdownToJson.js";
import { Knex } from "knex";
import { FolderMdJsonData } from "../lib/FolderMdJsonData.js";

class MddbFolderWatcher {
folderPath: any;
watcher: chokidar.FSWatcher | null = null;
folderMdJsonData: FolderMdJsonData;
db: Knex;
ready = false;

constructor(
db: Knex,
folderMdJsonData: FolderMdJsonData,
folderPath: string
) {
this.folderPath = folderPath;
this.folderMdJsonData = folderMdJsonData;
this.db = db;
}

createWatcher() {
this.watcher = chokidar.watch(this.folderPath, {
ignoreInitial: true,
});

this.watcher.on("add", this.handleFileAdd.bind(this));
this.watcher.on("unlink", this.handleFileDelete.bind(this));
this.watcher.on("change", this.handleFileChange.bind(this));
this.watcher.on("ready", () => {
this.ready = true;
console.log("Initial scan complete. Chokidar is ready.");
});
}

async handleFileAdd(filePath: string, filePathsToIndex: string[]) {
const newJson = markdownToJson(this.folderPath, filePath, filePathsToIndex);
await this.folderMdJsonData.addFileJson(newJson);
}

handleFileDelete(filePath: string) {
const fileId = generateFileIdFromPath(filePath);
this.folderMdJsonData.deleteFile(fileId);
}

handleFileChange(filePath: string) {
const newFileJson = markdownToJson(this.folderPath, filePath, []);
const fileId = generateFileIdFromPath(filePath);
this.folderMdJsonData.updateFileJson(fileId, newFileJson);
}

start() {
if (this.watcher === null) {
this.createWatcher();
}
this.watcher!.add(this.folderPath);
}

stop() {
if (this.watcher !== null) {
this.watcher.close();
}
}

setDatabase(db: Knex<any, any[]>) {
this.db = db;
}
}

export default MddbFolderWatcher;
81 changes: 81 additions & 0 deletions src/lib/FileJsonDataManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Knex } from "knex";
import { jsonDiff } from "./utils.js";
import { MddbFile } from "./schema.js";
import { FileJson } from "./FolderMdJsonData.js";

export class FileJsonDataManager {
private db: Knex;
private _files: FileJson[];

constructor(db: Knex, files: FileJson[]) {
this.db = db;
this._files = files;
}

async addFileJson(newFileJson: FileJson) {
this._files.push(newFileJson);
await MddbFile.insert(this.db, newFileJson.file);
}

async updateFileJson(fileId: string, newFileJson: FileJson) {
const index = this.getFileIndex(fileId);
if (index === -1) {
throw new Error(`Failed to update non-sxising file ${fileId}`);
}

const oldJson = this._files[index];
this._files[index] = newFileJson;

const fileDiff = jsonDiff(oldJson.file, newFileJson.file);
if (Object.keys(fileDiff).length === 0) {
return;
}
await MddbFile.updateFileProperties(this.db, fileId, fileDiff);
}

async deleteFile(fileId: string) {
const index = this.getFileIndex(fileId);
if (index === -1) {
throw new Error("Failed to delete file");
}
this._files.splice(index, 1);
this._files.push();
await MddbFile.deleteById(this.db, fileId);
}

getFileIndex(fileId: string) {
return this._files.findIndex((fileJson) => fileJson.file._id === fileId);
}

getFileJsonById(fileId: string) {
return this._files.find((fileJson) => fileJson.file._id === fileId);
}

getFileJsonByUrlPath(urlPath: string) {
return this._files.find((fileJson) => fileJson.file.url_path === urlPath);
}

getFileTags(fileId: string) {
const fileJson = this.getFileJsonById(fileId);

if (!fileJson) {
throw new Error(`Unable to get non-existing file ${fileId}`);
}

return fileJson.tags;
}

getLinks(fileId: string) {
const fileJson = this.getFileJsonById(fileId);

if (!fileJson) {
throw new Error(`Unable to get non-existing file ${fileId}`);
}

return fileJson.links;
}

get files() {
return this._files;
}
}
Loading

0 comments on commit a7fa720

Please sign in to comment.