# GTC-Sync An Obsidian plugin that synchronizes Obsidian notes with GTC (An ERP by Etudes Informatiques et Services) through a WebSocket. ## Overview The plugin maintains a persistent WebSocket connection with a GTC-Sync server. Synchronization is **bidirectional**: local changes are pushed to the server, and the server can remotely control the Obsidian vault. Only notes that have an `IdNote` field in their YAML frontmatter participate in synchronization. ```yaml --- IdNote: --- ``` --- ## Data flow ### Plugin → Server When a note with `IdNote` is modified or renamed, the plugin automatically sends its content to the server (`note.saved`) after a 1-second debounce. The payload includes the content line by line and file metadata (creation and modification dates). Only the **active file** triggers an outgoing sync. Changes applied by Obsidian Sync from other devices are not propagated. On **rename**, the plugin also synchronizes every note that references the renamed file (Obsidian resolved links are re-evaluated). ### Server → Plugin The server can send JSON commands that the plugin executes directly on the vault: | Command | Action | |---|---| | `note.read` | Read content and metadata of a note | | `note.create` | Create a new note | | `note.replace` | Fully replace the content of a note | | `note.move` | Move / rename a note | | `note.findByProperty` | Find a note by frontmatter property | | `note.open` | Open a note in the Obsidian editor | | `check` | Verify that the plugin is reachable | --- ## WebSocket protocol Messages are JSON objects. Each exchange uses an `id` field (unique identifier generated by the plugin) to match responses to requests. **Authentication**: on connection open, if a token is configured, the plugin sends `{ type: "auth", token }` before any other exchange. The server replies with `auth.ok` or `auth.error`. **Outgoing requests (plugin → server)**: the plugin waits for the response with a 10-second timeout. Past that delay, the request is rejected. **Incoming commands (server → plugin)**: the plugin executes the command and replies with `{ id, ok: true, result }` or `{ id, ok: false, error }`. **Session replacement**: if another plugin instance connects with the same token, the server sends `session.replaced`. The plugin stops auto-reconnecting and shows an alert. --- ## Loop prevention Any remote write (`note.create`, `note.replace`, `note.move`) temporarily marks the file in `updatingFiles`. The vault `modify` event ignores those files to prevent a remote change from immediately triggering an outgoing sync back to the server. --- ## Quick notes A **quick note** is a blank note created with a server-assigned `IdNote`. It lets you link a new Obsidian note to an existing entry on the server side. Several ways to create one: - Left ribbon icon (pen) - File/folder context menu → **Create quick note** - Command palette → `GTC-Sync: Create quick note` The note is created in the folder of the target file, or the active file's folder if no target is selected. Its name follows the format `Quick Note YYYY-MM-DD HH-MM-SS.md`. You can also **link an existing note** to a server identifier via the context menu → **Send to quick note**: this injects an `IdNote` into the selected note's frontmatter. --- ## Connection indicators The connection status is shown in two places: - **Status bar** (bottom of the window): `GTC-Sync : ●` with a tooltip - **Left ribbon** (icon): changes based on current state | State | Icon | Meaning | |---|---|---| | `connecting` | loader | Connection in progress | | `connected` | wifi | Connected to the server | | `disconnected` | wifi-off | Disconnected, auto-reconnect in 3 s | | `auth-error` | shield-off | Invalid token, reconnection disabled | When a synced note is opened or modified while the plugin is disconnected, an alert modal appears with a **Reconnect** button. --- ## Error handling Server errors on save are surfaced via modals: - **Code 74**: the note is reserved by another user — local changes may be lost. - **Code 78**: the note does not exist anymore. - **Other codes**: generic error modal showing the code and message returned by the server. --- ## Settings Accessible via *Obsidian Settings → GTC-Sync*. | Setting | Description | Default | |---|---|---| | WebSocket URL | Server address | `ws://127.0.0.1:8080` | | WebSocket token | Authentication token | *(empty)* | | Auto connect | Automatically connect when the plugin loads | enabled | | Debug mode | Verbose logs in the developer console (F12) | disabled | Settings are stored **locally** via `localStorage` (key `gtc-sync-plugin-local-settings`) and are **not synchronized** by Obsidian Sync across devices. Changing the URL or token automatically restarts the connection. --- ## Available commands | ID | Name | Action | |---|---|---| | `gtc-sync:create-quick-note` | Create quick note | Creates a note linked to a server IdNote | | `gtc-sync:connect-websocket` | Connect WebSocket | Manually starts the connection | | `gtc-sync:disconnect-websocket` | Disconnect WebSocket | Manually stops the connection | --- ## Language support The plugin adapts to the Obsidian interface language automatically. All user-facing text — menus, commands, notices, modals, settings, error messages, and debug logs — is available in: - **English** (default) - **French** (`fr`) Language detection uses Obsidian's internal locale (`window.moment.locale()`). No configuration is needed: switching Obsidian's language in its settings is enough. To add a new language, open `src/i18n.ts`, duplicate the `en` block, fill in the translations, and register the new locale in the `detectLang` function. --- ## Development ```bash # Development (watch + inline sourcemaps) npm run dev # Production build (TypeScript check + optimized bundle) npm run build ``` Validation is done manually inside Obsidian. There is no automated test suite. ### Source structure | File | Role | |---|---| | `src/main.ts` | Plugin entry point, lifecycle, settings tab, Obsidian event handling | | `src/websocketClient.ts` | WS connection, auto-reconnect, incoming command routing, outgoing request/response | | `src/vaultApi.ts` | Obsidian vault abstraction (read / create / replace / move / open / findByProperty) | | `src/types.ts` | `CommandRequest` and `CommandResponse` types | | `src/alertModal.ts` | Alert modal (server errors, disconnection) |