Set up monorepo workspace
This commit is contained in:
parent
ae3acb9e1e
commit
eb88d35c2e
10 changed files with 207 additions and 26 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -7,8 +7,8 @@ node_modules
|
||||||
# Rust build folder
|
# Rust build folder
|
||||||
backend/target
|
backend/target
|
||||||
|
|
||||||
# Obsidian plugin build folder
|
obsidian-plugin/dist
|
||||||
plugin/dist
|
sync-client/dist
|
||||||
|
|
||||||
backend/db.sqlite3*
|
backend/db.sqlite3*
|
||||||
backend/config.yml
|
backend/config.yml
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,16 @@ import unusedImports from "eslint-plugin-unused-imports";
|
||||||
|
|
||||||
export default tseslint.config({
|
export default tseslint.config({
|
||||||
plugins: {
|
plugins: {
|
||||||
"unused-imports": unusedImports,
|
"unused-imports": unusedImports
|
||||||
},
|
},
|
||||||
extends: [eslint.configs.recommended, tseslint.configs.all],
|
extends: [eslint.configs.recommended, tseslint.configs.all],
|
||||||
ignores: ["**/types.ts", "**/*.test.ts"],
|
ignores: [
|
||||||
|
"**/types.ts",
|
||||||
|
"**/*.test.ts",
|
||||||
|
"**/dist/**/*",
|
||||||
|
"**/*.mjs",
|
||||||
|
"**/*.js"
|
||||||
|
],
|
||||||
rules: {
|
rules: {
|
||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
"@typescript-eslint/no-unused-vars": "off",
|
"@typescript-eslint/no-unused-vars": "off",
|
||||||
|
|
@ -20,8 +26,8 @@ export default tseslint.config({
|
||||||
"@typescript-eslint/max-params": [
|
"@typescript-eslint/max-params": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
max: 5,
|
max: 5
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
"unused-imports/no-unused-imports": "error",
|
"unused-imports/no-unused-imports": "error",
|
||||||
"@typescript-eslint/no-magic-numbers": "off",
|
"@typescript-eslint/no-magic-numbers": "off",
|
||||||
|
|
@ -33,14 +39,14 @@ export default tseslint.config({
|
||||||
vars: "all",
|
vars: "all",
|
||||||
varsIgnorePattern: "^_",
|
varsIgnorePattern: "^_",
|
||||||
args: "after-used",
|
args: "after-used",
|
||||||
argsIgnorePattern: "^_",
|
argsIgnorePattern: "^_"
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
projectService: true,
|
projectService: true,
|
||||||
tsconfigRootDir: import.meta.dirname,
|
tsconfigRootDir: import.meta.dirname
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
10
obsidian-plugin/manifest.json
Normal file
10
obsidian-plugin/manifest.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"id": "vault-link",
|
||||||
|
"name": "VaultLink",
|
||||||
|
"version": "0.0.30",
|
||||||
|
"minAppVersion": "0.0.0",
|
||||||
|
"description": "Self-hosted synchronization and collaboration for your Vault.",
|
||||||
|
"author": "Andras Schmelczer",
|
||||||
|
"authorUrl": "https://schmelczer.dev",
|
||||||
|
"isDesktopOnly": false
|
||||||
|
}
|
||||||
26
package.json
Normal file
26
package.json
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"name": "my-workspace",
|
||||||
|
"private": true,
|
||||||
|
"workspaces": [
|
||||||
|
"sync-client",
|
||||||
|
"obsidian-plugin"
|
||||||
|
],
|
||||||
|
"prettier": {
|
||||||
|
"trailingComma": "none",
|
||||||
|
"tabWidth": 4,
|
||||||
|
"useTabs": true,
|
||||||
|
"endOfLine": "lf"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "npm run build --workspaces",
|
||||||
|
"dev": "npm run dev --workspaces",
|
||||||
|
"test": "npm run test --workspaces",
|
||||||
|
"lint": "eslint --fix sync-client obsidian-plugin; prettier --write \"sync-client/**/*.(ts|scss|json|html)\" \"obsidian-plugin/**/*.(ts|scss|json|html)\""
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"prettier": "^3.4.2",
|
||||||
|
"eslint": "9.17.0",
|
||||||
|
"typescript-eslint": "8.18.0",
|
||||||
|
"eslint-plugin-unused-imports": "^4.1.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
import type { TAbstractFile } from "obsidian";
|
|
||||||
|
|
||||||
export interface FileEventHandler {
|
|
||||||
onCreate: (path: TAbstractFile) => Promise<void>;
|
|
||||||
onDelete: (path: TAbstractFile) => Promise<void>;
|
|
||||||
onRename: (path: TAbstractFile, oldPath: string) => Promise<void>;
|
|
||||||
onModify: (path: TAbstractFile) => Promise<void>;
|
|
||||||
}
|
|
||||||
28
sync-client/package.json
Normal file
28
sync-client/package.json
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "sync-client",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/types/src/index.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "webpack watch --mode development",
|
||||||
|
"build": "webpack --mode production",
|
||||||
|
"test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"tslib": "2.4.0",
|
||||||
|
"typescript": "5.7.2",
|
||||||
|
"sync_lib": "file:../backend/sync_lib/pkg",
|
||||||
|
"@types/jest": "^29.5.14",
|
||||||
|
"@types/node": "^16.11.6",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"ts-jest": "^29.2.5",
|
||||||
|
"p-queue": "^8.0.1",
|
||||||
|
"fetch-retry": "^6.0.0",
|
||||||
|
"byte-base64": "^1.1.0",
|
||||||
|
"openapi-fetch": "0.13.3",
|
||||||
|
"openapi-typescript": "7.4.4",
|
||||||
|
"ts-loader": "^9.5.1",
|
||||||
|
"webpack": "^5.97.1",
|
||||||
|
"webpack-cli": "^6.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
48
sync-client/src/index.ts
Normal file
48
sync-client/src/index.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
export { applyRemoteChangesLocally } from "./sync-operations/apply-remote-changes-locally";
|
||||||
|
|
||||||
|
export {
|
||||||
|
type RelativePath,
|
||||||
|
type DocumentId,
|
||||||
|
type VaultUpdateId,
|
||||||
|
type DocumentMetadata
|
||||||
|
} from "./database/document-metadata";
|
||||||
|
|
||||||
|
export { Database } from "./database/database";
|
||||||
|
|
||||||
|
export {
|
||||||
|
SyncService,
|
||||||
|
type CheckConnectionResult
|
||||||
|
} from "./services/sync-service";
|
||||||
|
|
||||||
|
export { Syncer } from "./sync-operations/syncer";
|
||||||
|
|
||||||
|
export {
|
||||||
|
SyncHistory,
|
||||||
|
SyncType,
|
||||||
|
SyncSource,
|
||||||
|
SyncStatus,
|
||||||
|
type HistoryStats,
|
||||||
|
type HistoryEntry
|
||||||
|
} from "./tracing/sync-history";
|
||||||
|
|
||||||
|
export { Logger, LogLevel } from "./tracing/logger";
|
||||||
|
|
||||||
|
export { type FileOperations } from "./file-operations";
|
||||||
|
|
||||||
|
import init from "sync_lib";
|
||||||
|
import wasmBin from "sync_lib/sync_lib_bg.wasm";
|
||||||
|
|
||||||
|
export const initialize = async (): Promise<void> => {
|
||||||
|
await init(
|
||||||
|
// eslint-disable-next-line
|
||||||
|
(wasmBin as any).default // it is loaded as a base64 string by webpack
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export {
|
||||||
|
isFileTypeMergable,
|
||||||
|
mergeText,
|
||||||
|
bytesToBase64,
|
||||||
|
base64ToBytes,
|
||||||
|
merge,
|
||||||
|
isBinary
|
||||||
|
} from "sync_lib";
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import type { Database } from "src/database/database";
|
import type { Database } from "../database/database";
|
||||||
import type {
|
import type {
|
||||||
DocumentMetadata,
|
DocumentMetadata,
|
||||||
RelativePath
|
RelativePath
|
||||||
} from "src/database/document-metadata";
|
} from "src/database/document-metadata";
|
||||||
import type { FileOperations } from "src/file-operations/file-operations";
|
import type { FileOperations } from "src/file-operations";
|
||||||
import type { SyncService } from "src/services/sync-service";
|
import type { SyncService } from "src/services/sync-service";
|
||||||
import { Logger } from "src/tracing/logger";
|
import { Logger } from "src/tracing/logger";
|
||||||
import type { SyncHistory } from "src/tracing/sync-history";
|
import type { SyncHistory } from "src/tracing/sync-history";
|
||||||
|
|
@ -102,7 +102,7 @@ export class Syncer {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const allLocalFiles = await this.operations.listAllFiles();
|
const allLocalFiles = await this.operations.listAllFiles();
|
||||||
const locallyDeletedFiles = [
|
let locallyDeletedFiles = [
|
||||||
...this.database.getDocuments().entries()
|
...this.database.getDocuments().entries()
|
||||||
].filter(([path, _]) => !allLocalFiles.includes(path));
|
].filter(([path, _]) => !allLocalFiles.includes(path));
|
||||||
|
|
||||||
|
|
@ -126,7 +126,10 @@ export class Syncer {
|
||||||
);
|
);
|
||||||
if (originalFile !== undefined) {
|
if (originalFile !== undefined) {
|
||||||
// `originalFile` hasn't been deleted but it got moved instead
|
// `originalFile` hasn't been deleted but it got moved instead
|
||||||
locallyDeletedFiles.remove(originalFile);
|
locallyDeletedFiles =
|
||||||
|
locallyDeletedFiles.filter(
|
||||||
|
(item) => item != originalFile
|
||||||
|
);
|
||||||
|
|
||||||
Logger.getInstance().debug(
|
Logger.getInstance().debug(
|
||||||
`Document ${relativePath} was not found under its current path in the database but was found under a different path ${originalFile[0]}, scheduling sync to move it`
|
`Document ${relativePath} was not found under its current path in the database but was found under a different path ${originalFile[0]}, scheduling sync to move it`
|
||||||
|
|
@ -231,7 +234,9 @@ export class Syncer {
|
||||||
this.history.addHistoryEntry({
|
this.history.addHistoryEntry({
|
||||||
status: SyncStatus.ERROR,
|
status: SyncStatus.ERROR,
|
||||||
relativePath,
|
relativePath,
|
||||||
message: `File size exceeds the maximum file size limit of ${this.database.getSettings().maxFileSizeMB}MB`,
|
message: `File size exceeds the maximum file size limit of ${
|
||||||
|
this.database.getSettings().maxFileSizeMB
|
||||||
|
}MB`,
|
||||||
type: SyncType.CREATE
|
type: SyncType.CREATE
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|
@ -332,7 +337,9 @@ export class Syncer {
|
||||||
this.history.addHistoryEntry({
|
this.history.addHistoryEntry({
|
||||||
status: SyncStatus.ERROR,
|
status: SyncStatus.ERROR,
|
||||||
relativePath,
|
relativePath,
|
||||||
message: `File size exceeds the maximum file size limit of ${this.database.getSettings().maxFileSizeMB}MB`,
|
message: `File size exceeds the maximum file size limit of ${
|
||||||
|
this.database.getSettings().maxFileSizeMB
|
||||||
|
}MB`,
|
||||||
type: SyncType.CREATE
|
type: SyncType.CREATE
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
15
sync-client/tsconfig.json
Normal file
15
sync-client/tsconfig.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"target": "ES2022",
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"lib": [
|
||||||
|
"DOM",
|
||||||
|
"ESNext"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
49
sync-client/webpack.config.js
Normal file
49
sync-client/webpack.config.js
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
module.exports = (_env, _argv) => ({
|
||||||
|
entry: "./src/index.ts",
|
||||||
|
devtool: "source-map",
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.ts$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: "ts-loader",
|
||||||
|
options: {
|
||||||
|
compilerOptions: {
|
||||||
|
declaration: true,
|
||||||
|
declarationDir: "./dist/types"
|
||||||
|
},
|
||||||
|
transpileOnly: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.wasm$/,
|
||||||
|
type: "asset/inline"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
minimize: false
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: [".ts", ".js"],
|
||||||
|
alias: {
|
||||||
|
root: __dirname,
|
||||||
|
src: path.resolve(__dirname, "src")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
clean: true,
|
||||||
|
filename: "index.js",
|
||||||
|
library: {
|
||||||
|
name: "SyncClient",
|
||||||
|
type: "umd"
|
||||||
|
},
|
||||||
|
globalObject: "this",
|
||||||
|
path: path.resolve(__dirname, "dist")
|
||||||
|
}
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue