Fix import path and add readme

This commit is contained in:
vorotamoroz
2026-03-11 14:57:36 +01:00
parent 0742773e1e
commit 4a0d5e99d0
16 changed files with 233 additions and 53 deletions

181
src/apps/webapp/README.md Normal file
View File

@@ -0,0 +1,181 @@
# LiveSync WebApp
Browser-based implementation of Obsidian LiveSync using the FileSystem API.
Note: (I vrtmrz have not tested this so much yet).
## Features
- 🌐 Runs entirely in the browser
- 📁 Uses FileSystem API to access your local vault
- 🔄 Syncs with CouchDB, Object Storage server (compatible with Obsidian LiveSync plugin)
- 🚫 No server-side code required!!
- 💾 Settings stored in `.livesync/settings.json` within your vault
- 👁️ Real-time file watching (Chrome 124+ with FileSystemObserver)
## Requirements
- **FileSystem API support**:
- Chrome/Edge 86+ (required)
- Opera 72+ (required)
- Safari 15.2+ (experimental, limited support)
- Firefox: Not supported yet
- **FileSystemObserver support** (optional, for real-time file watching):
- Chrome 124+ (recommended)
- Without this, files are only scanned on startup
## Getting Started
### Installation
```bash
# Install dependencies (ensure you are in repository root directory, not src/apps/cli)
# due to shared dependencies with webapp and main library
npm install
```
### Development
```bash
# Build the project (ensure you are in `src/apps/webapp` directory)
cd src/apps/webapp
npm run dev
```
This will start a development server at `http://localhost:3000`.
### Build
```bash
# Build the project (ensure you are in `src/apps/webapp` directory)
cd src/apps/webapp
npm run build
```
The built files will be in the `dist` directory.
### Usage
1. Open the webapp in your browser
2. Grant directory access when prompted
3. Configure CouchDB connection by editing `.livesync/settings.json` in your vault
- You can also copy data.json from Obsidian's plug-in folder.
Example `.livesync/settings.json`:
```json
{
"couchDB_URI": "https://your-couchdb-server.com",
"couchDB_USER": "your-username",
"couchDB_PASSWORD": "your-password",
"couchDB_DBNAME": "your-database",
"isConfigured": true,
"liveSync": true,
"syncOnSave": true
}
```
After editing, reload the page.
## Architecture
### Directory Structure
```
webapp/
├── adapters/ # FileSystem API adapters
│ ├── FSAPITypes.ts
│ ├── FSAPIPathAdapter.ts
│ ├── FSAPITypeGuardAdapter.ts
│ ├── FSAPIConversionAdapter.ts
│ ├── FSAPIStorageAdapter.ts
│ ├── FSAPIVaultAdapter.ts
│ └── FSAPIFileSystemAdapter.ts
├── managers/ # Event managers
│ ├── FSAPIStorageEventManagerAdapter.ts
│ └── StorageEventManagerFSAPI.ts
├── serviceModules/ # Service implementations
│ ├── FileAccessFSAPI.ts
│ ├── ServiceFileAccessImpl.ts
│ ├── DatabaseFileAccess.ts
│ └── FSAPIServiceModules.ts
├── main.ts # Application entry point
├── index.html # HTML entry
├── package.json
├── vite.config.ts
└── README.md
```
### Key Components
1. **Adapters**: Implement `IFileSystemAdapter` interface using FileSystem API
2. **Managers**: Handle storage events and file watching
3. **Service Modules**: Integrate with LiveSyncBaseCore
4. **Main**: Application initialization and lifecycle management
### Service Hub
Uses `BrowserServiceHub` which provides:
- Database service (IndexedDB via PouchDB)
- Settings service (file-based in `.livesync/settings.json`)
- Replication service
- File processing service
- And more...
## Limitations
- **Real-time file watching**: Requires Chrome 124+ with FileSystemObserver
- Without it, changes are only detected on manual refresh
- **Performance**: Slower than native file system access
- **Permissions**: Requires user to grant directory access (cached via IndexedDB)
- **Browser support**: Limited to browsers with FileSystem API support
## Differences from CLI Version
- Uses `BrowserServiceHub` instead of `HeadlessServiceHub`
- Uses FileSystem API instead of Node.js `fs`
- Settings stored in `.livesync/settings.json` in vault
- Real-time file watching only with FileSystemObserver (Chrome 124+)
## Differences from Obsidian Plugin
- No Obsidian-specific modules (UI, settings dialog, etc.)
- Simplified configuration
- No plugin/theme sync features
- No internal file handling (`.obsidian` folder)
## Development Notes
- TypeScript configuration: Uses project's tsconfig.json
- Module resolution: Aliased paths via Vite config
- External dependencies: Bundled by Vite
## Troubleshooting
### "Failed to get directory access"
- Make sure you're using a supported browser
- Try refreshing the page
- Clear browser cache and IndexedDB
### "Settings not found"
- Check that `.livesync/settings.json` exists in your vault directory
- Verify the JSON format is valid
- Create the file manually if needed
### "File watching not working"
- Make sure you're using Chrome 124 or later
- Check browser console for FileSystemObserver messages
- Try manually triggering sync if automatic watching isn't available
### "Sync not working"
- Verify CouchDB credentials
- Check browser console for errors
- Ensure CouchDB server is accessible (CORS enabled)
## License
Same as the main Obsidian LiveSync project.

View File

@@ -1,5 +1,5 @@
import type { UXFileInfoStub, UXFolderInfo } from "../../../lib/src/common/types";
import type { IConversionAdapter } from "../../../lib/src/serviceModules/adapters";
import type { UXFileInfoStub, UXFolderInfo } from "@lib/common/types";
import type { IConversionAdapter } from "@lib/serviceModules/adapters";
import type { FSAPIFile, FSAPIFolder } from "./FSAPITypes";
/**

View File

@@ -1,5 +1,5 @@
import type { FilePath, UXStat } from "../../../lib/src/common/types";
import type { IFileSystemAdapter } from "../../../lib/src/serviceModules/adapters";
import type { FilePath, UXStat } from "@lib/common/types";
import type { IFileSystemAdapter } from "@lib/serviceModules/adapters";
import { FSAPIPathAdapter } from "./FSAPIPathAdapter";
import { FSAPITypeGuardAdapter } from "./FSAPITypeGuardAdapter";
import { FSAPIConversionAdapter } from "./FSAPIConversionAdapter";
@@ -75,7 +75,7 @@ export class FSAPIFileSystemAdapter implements IFileSystemAdapter<FSAPIFile, FSA
}
/**
*
*
*/
async getAbstractFileByPathInsensitive(p: FilePath | string): Promise<FSAPIFile | null> {
const pathStr = this.normalisePath(p);

View File

@@ -1,5 +1,5 @@
import type { FilePath } from "../../../lib/src/common/types";
import type { IPathAdapter } from "../../../lib/src/serviceModules/adapters";
import type { FilePath } from "@lib/common/types";
import type { IPathAdapter } from "@lib/serviceModules/adapters";
import type { FSAPIFile } from "./FSAPITypes";
/**

View File

@@ -1,5 +1,5 @@
import type { UXDataWriteOptions } from "../../../lib/src/common/types";
import type { IStorageAdapter } from "../../../lib/src/serviceModules/adapters";
import type { UXDataWriteOptions } from "@lib/common/types";
import type { IStorageAdapter } from "@lib/serviceModules/adapters";
import type { FSAPIStat } from "./FSAPITypes";
/**

View File

@@ -1,4 +1,4 @@
import type { ITypeGuardAdapter } from "../../../lib/src/serviceModules/adapters";
import type { ITypeGuardAdapter } from "@lib/serviceModules/adapters";
import type { FSAPIFile, FSAPIFolder } from "./FSAPITypes";
/**

View File

@@ -1,4 +1,4 @@
import type { FilePath, UXStat } from "../../../lib/src/common/types";
import type { FilePath, UXStat } from "@lib/common/types";
/**
* FileSystem API file representation

View File

@@ -1,5 +1,5 @@
import type { FilePath, UXDataWriteOptions } from "../../../lib/src/common/types";
import type { IVaultAdapter } from "../../../lib/src/serviceModules/adapters";
import type { FilePath, UXDataWriteOptions } from "@lib/common/types";
import type { IVaultAdapter } from "@lib/serviceModules/adapters";
import type { FSAPIFile, FSAPIFolder } from "./FSAPITypes";
/**

View File

@@ -3,16 +3,19 @@
* Browser-based version of Self-hosted LiveSync plugin using FileSystem API
*/
import { BrowserServiceHub } from "../../lib/src/services/BrowserServices";
import { LiveSyncBaseCore } from "../../LiveSyncBaseCore";
import { ServiceContext } from "../../lib/src/services/base/ServiceBase";
import { BrowserServiceHub } from "@lib/services/BrowserServices";
import { LiveSyncBaseCore } from "@/LiveSyncBaseCore";
import { ServiceContext } from "@lib/services/base/ServiceBase";
import { initialiseServiceModulesFSAPI } from "./serviceModules/FSAPIServiceModules";
import type { ObsidianLiveSyncSettings } from "../../lib/src/common/types";
import type { BrowserAPIService } from "../../lib/src/services/implements/browser/BrowserAPIService";
import type { InjectableSettingService } from "../../lib/src/services/implements/injectable/InjectableSettingService";
// import { SetupManager } from "@/modules/features/SetupManager";
import type { ObsidianLiveSyncSettings } from "@lib/common/types";
import type { BrowserAPIService } from "@lib/services/implements/browser/BrowserAPIService";
import type { InjectableSettingService } from "@lib/services/implements/injectable/InjectableSettingService";
import { useOfflineScanner } from "@lib/serviceFeatures/offlineScanner";
import { useRedFlagFeatures } from "@/serviceFeatures/redFlag";
import { useCheckRemoteSize } from "@lib/serviceFeatures/checkRemoteSize";
import { SetupManager } from "@/modules/features/SetupManager";
// import { ModuleObsidianSettingsAsMarkdown } from "@/modules/features/ModuleObsidianSettingAsMarkdown";
// import { ModuleSetupObsidian } from "@/modules/features/ModuleSetupObsidian";
import { ModuleSetupObsidian } from "@/modules/features/ModuleSetupObsidian";
// import { ModuleObsidianMenu } from "@/modules/essentialObsidian/ModuleObsidianMenu";
const SETTINGS_DIR = ".livesync";
@@ -105,7 +108,8 @@ class LiveSyncWebApp {
// new ModuleObsidianEvents(this, core),
// new ModuleObsidianSettingDialogue(this, core),
// new ModuleObsidianMenu(core),
// new ModuleSetupObsidian(core),
new ModuleSetupObsidian(core),
new SetupManager(core),
// new ModuleObsidianSettingsAsMarkdown(core),
// new ModuleLog(this, core),
// new ModuleObsidianDocumentHistory(this, core),
@@ -116,8 +120,12 @@ class LiveSyncWebApp {
// new ModuleIntegratedTest(this, core),
// new SetupManager(core),
],
() => [],// No add-ons
() => [],
() => [], // No add-ons
(core) => {
useOfflineScanner(core);
useRedFlagFeatures(core);
useCheckRemoteSize(core);
}
);
// Start the core

View File

@@ -1,6 +1,6 @@
import type { FilePath, UXFileInfoStub, UXInternalFileInfoStub } from "../../../lib/src/common/types";
import type { FileEventItem } from "../../../lib/src/common/types";
import type { IStorageEventManagerAdapter } from "../../../lib/src/managers/adapters";
import type { FilePath, UXFileInfoStub, UXInternalFileInfoStub } from "@lib/common/types";
import type { FileEventItem } from "@lib/common/types";
import type { IStorageEventManagerAdapter } from "@lib/managers/adapters";
import type {
IStorageEventTypeGuardAdapter,
IStorageEventPersistenceAdapter,
@@ -8,8 +8,8 @@ import type {
IStorageEventStatusAdapter,
IStorageEventConverterAdapter,
IStorageEventWatchHandlers,
} from "../../../lib/src/managers/adapters";
import type { FileEventItemSentinel } from "../../../lib/src/managers/StorageEventManager";
} from "@lib/managers/adapters";
import type { FileEventItemSentinel } from "@lib/managers/StorageEventManager";
import type { FSAPIFile, FSAPIFolder } from "../adapters/FSAPITypes";
/**

View File

@@ -1,10 +1,7 @@
import {
StorageEventManagerBase,
type StorageEventManagerBaseDependencies,
} from "../../../lib/src/managers/StorageEventManager";
import { StorageEventManagerBase, type StorageEventManagerBaseDependencies } from "@lib/managers/StorageEventManager";
import { FSAPIStorageEventManagerAdapter } from "./FSAPIStorageEventManagerAdapter";
import type { IMinimumLiveSyncCommands, LiveSyncBaseCore } from "../../../LiveSyncBaseCore";
import type { ServiceContext } from "../../../lib/src/services/base/ServiceBase";
import type { IMinimumLiveSyncCommands, LiveSyncBaseCore } from "@/LiveSyncBaseCore";
import type { ServiceContext } from "@lib/services/base/ServiceBase";
export class StorageEventManagerFSAPI extends StorageEventManagerBase<FSAPIStorageEventManagerAdapter> {
core: LiveSyncBaseCore<ServiceContext, IMinimumLiveSyncCommands>;

View File

@@ -13,9 +13,5 @@
"devDependencies": {
"typescript": "5.9.3",
"vite": "^7.3.1"
},
"imports": {
"../../src/worker/bgWorker.ts": "../../src/worker/bgWorker.mock.ts",
"@lib/worker/bgWorker.ts": "@lib/worker/bgWorker.mock.ts"
}
}

View File

@@ -1,8 +1,8 @@
import {
ServiceDatabaseFileAccessBase,
type ServiceDatabaseFileAccessDependencies,
} from "../../../lib/src/serviceModules/ServiceDatabaseFileAccessBase";
import type { DatabaseFileAccess } from "../../../lib/src/interfaces/DatabaseFileAccess";
} from "@lib/serviceModules/ServiceDatabaseFileAccessBase";
import type { DatabaseFileAccess } from "@lib/interfaces/DatabaseFileAccess";
/**
* FileSystem API-specific implementation of ServiceDatabaseFileAccess

View File

@@ -1,14 +1,15 @@
import type { InjectableServiceHub } from "../../../lib/src/services/implements/injectable/InjectableServiceHub";
import { ServiceRebuilder } from "../../../lib/src/serviceModules/Rebuilder";
import { ServiceFileHandler } from "../../../serviceModules/FileHandler";
import { StorageAccessManager } from "../../../lib/src/managers/StorageProcessingManager";
import type { ServiceModules } from "../../../types";
import type { LiveSyncBaseCore } from "../../../LiveSyncBaseCore";
import type { ServiceContext } from "../../../lib/src/services/base/ServiceBase";
import type { InjectableServiceHub } from "@lib/services/implements/injectable/InjectableServiceHub";
import { ServiceRebuilder } from "@lib/serviceModules/Rebuilder";
import { StorageAccessManager } from "@lib/managers/StorageProcessingManager";
import type { LiveSyncBaseCore } from "@/LiveSyncBaseCore";
import type { ServiceContext } from "@lib/services/base/ServiceBase";
import { FileAccessFSAPI } from "./FileAccessFSAPI";
import { ServiceFileAccessFSAPI } from "./ServiceFileAccessImpl";
import { ServiceDatabaseFileAccessFSAPI } from "./DatabaseFileAccess";
import { StorageEventManagerFSAPI } from "../managers/StorageEventManagerFSAPI";
import type { ServiceModules } from "@lib/interfaces/ServiceModule";
import { ServiceFileHandler } from "@/serviceModules/FileHandler";
/**
* Initialize service modules for FileSystem API webapp version

View File

@@ -1,4 +1,4 @@
import { FileAccessBase, type FileAccessBaseDependencies } from "../../../lib/src/serviceModules/FileAccessBase";
import { FileAccessBase, type FileAccessBaseDependencies } from "@lib/serviceModules/FileAccessBase";
import { FSAPIFileSystemAdapter } from "../adapters/FSAPIFileSystemAdapter";
/**

View File

@@ -1,7 +1,4 @@
import {
ServiceFileAccessBase,
type StorageAccessBaseDependencies,
} from "../../../lib/src/serviceModules/ServiceFileAccessBase";
import { ServiceFileAccessBase, type StorageAccessBaseDependencies } from "@lib/serviceModules/ServiceFileAccessBase";
import { FSAPIFileSystemAdapter } from "../adapters/FSAPIFileSystemAdapter";
/**