Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hot-Reloading Feature Implementation #46

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading