### Install Olgitbridge
Source: https://github.com/chazeon/olgitbridge/blob/main/README.md
Clone the repository, navigate to the directory, and install dependencies using npm. This is the initial setup step for the olgitbridge.
```bash
git clone https://gitlab.com/chazeon/olgitbridge.git
cd olgitbridge
npm install
```
--------------------------------
### Starting the Olgitbridge Server
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Commands to start the Olgitbridge server. Use `authbind` to bind to privileged ports (80/443) without root. The server listens on the configured port.
```bash
# Plain start
node src/server.js
```
```bash
# Using authbind to bind port 80/443 without root
authbind node src/server.js
```
```bash
# Expected console output
# [*] listening on port 5000
```
--------------------------------
### Run Sample Echo Server
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/lib/vendor/web-socket-js/README.md
Starts a sample WebSocket echo server using Ruby. The first argument specifies the domain from which HTML pages can connect.
```bash
$ ruby web-socket-ruby/samples/echo_server.rb example.com 10081
```
--------------------------------
### Start Olgitbridge Server
Source: https://github.com/chazeon/olgitbridge/blob/main/README.md
Start the olgitbridge server using Node.js. If running on ports 80 or 443, consider using authbind for elevated privileges.
```bash
authbind node src/server.js
```
--------------------------------
### Build WebSocketMain.swf
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/lib/vendor/web-socket-js/README.md
Instructions for building the WebSocketMain.swf file using the Flex 4 SDK. Ensure you have the SDK installed before running the build script.
```bash
cd flash-src
./build.sh
```
--------------------------------
### Olgitbridge Configuration (`config.js`)
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Defines runtime settings for Olgitbridge, including Overleaf server URL, data directories, cache timeouts, SSL configuration, and port settings. Edit this file before starting the server or building the Docker image.
```javascript
// config.js
const config = module.exports = { forward: { }, ssl: { } };
// URL of the target Overleaf CE/Pro server
config.olServer = 'http://overleaf.example.com';
// Base directory for all working data (must be absolute, trailing slash required)
config.baseDir = '/var/olgitbridge/';
// Subdirectories (derived from baseDir automatically)
config.bluesDir = config.baseDir + 'blues/'; // blueprint copies from Overleaf
config.hashDir = config.baseDir + 'hash/'; // zip content hashes (change detection)
config.padsDir = config.baseDir + 'pads/'; // working-tree git clones
config.reposDir = config.baseDir + 'repos/'; // bare git repositories served to clients
// How long (ms) to cache a previous downsync before re-downloading from Overleaf
config.downSyncTimeout = 30000;
// TLS — set enable: true and provide paths to key/cert files for HTTPS
config.ssl.enable = false;
config.ssl.key = '/etc/ssl/private/server.key';
config.ssl.cert = '/etc/ssl/certs/server.crt';
// Port the git bridge listens on (use 443 for direct HTTPS)
config.port = 5000;
// Optional: forward plain HTTP requests to the HTTPS endpoint
config.forward.enable = false;
config.forward.target = 'https://gitbridge.example.com';
config.forward.port = 80;
```
--------------------------------
### Olgitbridge Server Startup Logic
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Internal server startup logic that ensures necessary directories exist and creates an HTTP or HTTPS server based on the SSL configuration. The `serve` function handles all incoming requests.
```javascript
// Internally, server startup looks like this:
const start = async function() {
// Ensure working directories exist
for (let dir of [reposDir, padsDir, bluesDir, hashDir]) {
try { await fs.mkdir(dir); }
catch (e) { if (e.code !== 'EEXIST') throw e; }
}
if (config.ssl.enable) {
const httpsOptions = {
key: await fs.readFile(config.ssl.key),
cert: await fs.readFile(config.ssl.cert),
};
https.createServer(httpsOptions, serve).listen(config.port);
} else {
http.createServer(serve).listen(config.port);
}
console.log('[*] listening on port', config.port);
};
start();
```
--------------------------------
### Basic Connection and Event Handling
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/README.md
Demonstrates how to establish a connection to a socket.io server, listen for events like 'connect', 'custom event', and 'disconnect', and send basic messages.
```APIDOC
## Basic Usage
### Description
Connect to a socket.io server and handle basic events.
### Code Example
```js
var socket = io.connect('http://domain.com');
socket.on('connect', function () {
// socket connected
});
socket.on('custom event', function () {
// server emitted a custom event
});
socket.on('disconnect', function () {
// socket disconnected
});
socket.send('hi there');
```
```
--------------------------------
### Initialize and Connect WebSocket
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/lib/vendor/web-socket-js/sample.html
Sets up the WebSocket connection and event handlers. Ensure WEB_SOCKET_SWF_LOCATION is correctly set to the path of WebSocketMain.swf.
```javascript
WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf";
WEB_SOCKET_DEBUG = true;
var ws;
function init() {
ws = new WebSocket("ws://localhost:10081/");
ws.onopen = function() {
output("onopen");
};
ws.onmessage = function(e) {
output("onmessage: " + e.data);
};
ws.onclose = function() {
output("onclose");
};
ws.onerror = function() {
output("onerror");
};
}
```
--------------------------------
### io.connect(uri, [options])
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/README.md
Establishes a connection to the socket.io server. Allows configuration of various connection options.
```APIDOC
## io.connect
### Description
Connects to a socket.io server with optional configuration.
### Signature
```js
io.connect(uri, [options]);
```
### Parameters
#### uri
(string) The server URI to connect to.
#### options
(object) Optional configuration object.
##### Options:
- *resource* (string): The resource name for socket.io connections.
- *transports* (array): An array of transport methods to attempt, in order of preference.
Example: `['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling', 'jsonp-polling']`
- *'connect timeout'* (number): Milliseconds to wait for a transport to establish a connection before timing out. Default: `5000`.
- *'try multiple transports'* (boolean): Whether to try other transports if the initial one times out. Default: `true`.
- *reconnect* (boolean): Whether to automatically attempt to reconnect if the connection is lost. Default: `true`.
- *'reconnection delay'* (number): Milliseconds to wait before the first reconnection attempt. Subsequent attempts use exponential backoff. Default: `500`.
- *'max reconnection attempts'* (number): The number of reconnection attempts to make before giving up. Default: `10`.
### Properties
- *options* (object): The merged default and provided options.
- *connected* (boolean): Indicates if the socket is currently connected.
- *connecting* (boolean): Indicates if the socket is currently attempting to connect.
- *reconnecting* (boolean): Indicates if the socket is currently in the process of reconnecting.
- *transport* (object): The current transport instance.
### Methods
- *connect(λ)*: Establishes a connection. If a callback function `λ` is provided, it will be executed once the connection is established.
- *send(message)*: Sends a string message to the server.
- *disconnect*: Closes the connection to the server.
- *on(event, λ)*: Adds a listener function `λ` for a specific event `event`.
- *once(event, λ)*: Adds a one-time listener function `λ` for a specific event `event`. The listener is removed after it is triggered.
- *removeListener(event, λ)*: Removes a specific listener function `λ` for a given event `event`.
### Events
- *connect*: Fired when the connection is successfully established.
- *connecting(transport_type)*: Fired when a connection attempt is made, with the transport type.
- *connect_failed*: Fired when a connection attempt times out after all possible transports have been tried (if `tryTransportsOnConnectTimeout` is set).
- *message(message)*: Fired when a message is received from the server.
- *close*: Fired when the connection is closed. Note: Some transports may fire this for temporary disconnections.
- *disconnect*: Fired when the connection is considered disconnected.
- *reconnect(transport_type, reconnectionAttempts)*: Fired when the connection has been re-established.
- *reconnecting(reconnectionDelay, reconnectionAttempts)*: Fired when a reconnection attempt is made, providing the delay for the next attempt.
- *reconnect_failed*: Fired when all reconnection attempts have failed.
```
--------------------------------
### Utilizing Namespaces
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/README.md
Shows how to connect to specific namespaces on the server by including the namespace in the connection URI.
```APIDOC
## Namespaces
### Description
Connect to different namespaces on the socket.io server.
### Code Example
```js
// Connect to the '/chat' namespace
var chat = io.connect('http://localhost/chat');
chat.on('connect', function () {
// chat socket connected
});
// Connect to the '/news' namespace (auto-detects host)
var news = io.connect('/news');
news.on('connect', function () {
// news socket connected
});
```
```
--------------------------------
### Basic Socket.IO Connection and Event Handling
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/README.md
Connect to a Socket.IO server and listen for connection, custom events, and disconnection.
```javascript
var socket = io.connect('http://domain.com');
socket.on('connect', function () {
// socket connected
});
socket.on('custom event', function () {
// server emitted a custom event
});
socket.on('disconnect', function () {
// socket disconnected
});
socket.send('hi there');
```
--------------------------------
### Join Project via Socket.IO - olops.joinProject
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Connects to the Overleaf real-time server via Socket.IO, emits 'joinProject', and returns the full project metadata, including the root folder structure.
```APIDOC
## Join Project via Socket.IO — `olops.joinProject`
Connects to the Overleaf real-time server using a vendored Socket.IO client, emits `joinProject`, and returns the full project metadata object (including `rootFolder`). Retries automatically on timeout.
```js
const projectInfo = await olops.joinProject(
client,
'http://overleaf.example.com',
'63f1a2b3c4d5e6f7a8b9c0d1'
);
// projectInfo.rootFolder[0] contains the full recursive file/folder tree:
// {
// _id: 'abc', name: 'rootFolder',
// docs: [{ _id: '...', name: 'main.tex' }, ...],
// fileRefs: [{ _id: '...', name: 'figure.png' }, ...],
// folders: [{ _id: '...', name: 'sections', docs: [...], ... }]
// }
```
```
--------------------------------
### Integrate web-socket-js in HTML
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/lib/vendor/web-socket-js/README.md
Includes the necessary JavaScript libraries and demonstrates how to instantiate and use the WebSocket client, mimicking the native WebSocket API.
```html
```
--------------------------------
### Socket.IO Client Connection Options
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/README.md
Configuration options for establishing a Socket.IO connection, including resource, transports, timeouts, and reconnection settings.
```javascript
io.connect(uri, [options]);
```
```javascript
['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling', 'jsonp-polling']
```
```javascript
5000
```
```javascript
true
```
```javascript
true
```
```javascript
500
```
```javascript
10
```
--------------------------------
### Async Spawn Git Commands
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Use this utility to execute Git commands asynchronously. It resolves with combined stdout/stderr on success (exit code 0) or rejects with the output string on failure. Ensure the `aspawn` module is imported.
```javascript
const aspawn = require('./src/aspawn');
// Resolves with combined output string on success
const output = await aspawn('/usr/bin/git', ['status'], { cwd: '/tmp/myrepo' });
console.log(output); // "On branch main"
nothing to commit..."
// Rejects with the combined output string on non-zero exit
try {
await aspawn('/usr/bin/git', ['push'], { cwd: '/tmp/myrepo' });
} catch (err) {
console.error('git push failed:', err); // err is a string, not an Error object
}
```
--------------------------------
### Git Operations — src/git.js
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Provides an async wrapper for system Git commands: init, clone, pull, and save (stage, commit, push). Errors like 'nothing to commit' are logged, not thrown.
```javascript
const git = require('./src/git');
// Initialise a new bare repository (used when a project is first accessed)
await git.init('/var/olgitbridge/repos/63f1a2b3c4d5e6f7a8b9c0d1/');
// Clone the bare repo into the pad directory (working tree for file diffs)
await git.clone(
'/var/olgitbridge/repos/63f1a2b3c4d5e6f7a8b9c0d1/',
'/var/olgitbridge/pads/'
);
// Pull latest commits from origin (called after every git-receive-pack)
await git.pull('/var/olgitbridge/pads/63f1a2b3c4d5e6f7a8b9c0d1/');
// Stage everything, commit, and push back to the bare repo
// (used to commit a fresh downsync from Overleaf)
await git.save('[1]', '/var/olgitbridge/pads/63f1a2b3c4d5e6f7a8b9c0d1/', 'synced by olgitbridge');
// git errors (e.g. "nothing to commit") are caught and logged, not thrown
```
--------------------------------
### Join Project via Socket.IO
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Connects to the Overleaf real-time server using a Socket.IO client, emits the 'joinProject' event, and returns the full project metadata. It includes automatic retries on timeout.
```javascript
const projectInfo = await olops.joinProject(
client,
'http://overleaf.example.com',
'63f1a2b3c4d5e6f7a8b9c0d1'
);
// projectInfo.rootFolder[0] contains the full recursive file/folder tree:
// {
// _id: 'abc', name: 'rootFolder',
// docs: [{ _id: '...', name: 'main.tex' }, ...],
// fileRefs: [{ _id: '...', name: 'figure.png' }, ...],
// folders: [{ _id: '...', name: 'sections', docs: [...], ... }]
// }
```
--------------------------------
### Upsync Logic — src/upsync.js
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Compares local pad directory with Overleaf state to upload changes, new files, and remove deleted files. Requires project info (id, padDir, blueDir) and an Overleaf client.
```javascript
const upsync = require('./src/upsync');
// project must have: id, padDir, blueDir
// project.info and project.tree are populated internally by joinProject/buildTree
await upsync(client, 'http://overleaf.example.com', project);
// Actions taken per file:
// padData !== blueData → POST /project/:id/upload?folder_id=:folderId (update)
// file in pad, not blue → POST /project/:id/upload?folder_id=:folderId (new file)
// file in blue, not pad → DELETE /project/:id/doc/:id (or /file/, /folder/)
```
--------------------------------
### Downsync Overleaf Project
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Downloads the current Overleaf project as a zip, computes a content hash, and compares it to a cached hash. It only unpacks to pad and blueprint directories if the content has changed.
```javascript
const downsync = require('./src/downsync');
// Returns true → zip was new, pad/blue directories updated, caller should git-commit
// Returns false → zip hash identical to last run, no work done
const changed = await downsync(client, 'http://overleaf.example.com', project);
if (changed) {
// project.padDir now contains the latest Overleaf files
// project.blueDir is an identical copy used later as a diff baseline for upsync
await git.save(count, project.padDir, 'synced by olgitbridge');
}
```
--------------------------------
### Zip Download - olops.downloadZip
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Downloads the project as a zip file from the Overleaf server using the project ID and returns the raw binary buffer.
```APIDOC
## Zip Download — `olops.downloadZip`
Downloads `GET /Project//download/zip` and returns the raw binary buffer. The project ID is the same hex string visible in the Overleaf project URL.
```js
const zipBuffer = await olops.downloadZip(
client,
'http://overleaf.example.com',
'63f1a2b3c4d5e6f7a8b9c0d1' // project_id
);
// zipBuffer is a Buffer/ArrayBuffer; pass to unzipper for extraction:
const { Open } = require('unzipper');
const directory = await Open.buffer(zipBuffer);
await directory.extract({ path: '/var/olgitbridge/pads/63f1a2b3c4d5e6f7a8b9c0d1/' });
```
```
--------------------------------
### Docker Deployment Commands
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Commands for building and running the Olgitbridge Docker image. Mount `/var/olgitbridge/` to persist data. For HTTPS, bind-mount SSL certificate files.
```bash
# Build the image (edit config.js first)
docker build -t olgitbridge .
```
```bash
# Run with persisted data volume
docker run -d \
--name olgitbridge \
-p 5000:5000 \
-v /host/data/olgitbridge:/var/olgitbridge \
olgitbridge
```
```bash
# Run with HTTPS (bind-mount cert files)
docker run -d \
--name olgitbridge \
-p 443:443 \
-v /host/data/olgitbridge:/var/olgitbridge \
-v /etc/letsencrypt/live/example.com:/certs:ro \
olgitbridge
```
--------------------------------
### Utilizing Namespaces for Multiple Sockets
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/README.md
Connect to different namespaces on the server to manage multiple independent sockets. The host can be auto-detected if not specified.
```javascript
var chat = io.connect('http://localhost/chat');
chat.on('connect', function () {
// chat socket connected
});
var news = io.connect('/news'); // io.connect auto-detects host
news.on('connect', function () {
// news socket connected
});
```
--------------------------------
### Build File Tree — `olops.buildTree`
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Converts a nested folder structure into a flat, name-keyed tree for efficient lookups. This is essential for the upsync logic.
```APIDOC
## Build File Tree — `olops.buildTree`
### Description
Converts the nested `rootFolder` structure returned by `joinProject` into a flat, name-keyed tree used by the upsync logic for O(1) lookups.
### Usage
```js
const tree = olops.buildTree(projectInfo.rootFolder[0]);
```
### Returns
A recursive object representing the file tree:
```json
{
"type": "folder", "id": "abc", "name": "rootFolder",
"subs": {
"main.tex": { "type": "doc", "id": "...", "name": "main.tex", "branch": "" },
"figure.png": { "type": "file", "id": "...", "name": "figure.png", "branch": "" },
"sections": { "type": "folder", "id": "...", "name": "sections", "subs": { ... } }
}
}
```
```
--------------------------------
### Git Operations — `src/git.js`
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Provides an async wrapper for system Git commands, including init, clone, pull, and save (stage, commit, push).
```APIDOC
## Git Operations — `src/git.js`
### Description
A thin async wrapper around the system `git` binary (`/usr/bin/git`) covering the four operations olgitbridge needs: initialise a bare repo, clone it, pull, and stage-commit-push.
### Operations
1. **Initialize Bare Repository**
Used when a project is first accessed.
```js
await git.init('/var/olgitbridge/repos/63f1a2b3c4d5e6f7a8b9c0d1/');
```
2. **Clone Repository**
Clones the bare repo into the pad directory (working tree for file diffs).
```js
await git.clone(
'/var/olgitbridge/repos/63f1a2b3c4d5e6f7a8b9c0d1/',
'/var/olgitbridge/pads/'
);
```
3. **Pull Changes**
Pulls latest commits from origin. Called after every `git-receive-pack`.
```js
await git.pull('/var/olgitbridge/pads/63f1a2b3c4d5e6f7a8b9c0d1/');
```
4. **Save Changes**
Stages everything, commits, and pushes back to the bare repo. Used to commit a fresh downsync from Overleaf.
```js
await git.save('[1]', '/var/olgitbridge/pads/63f1a2b3c4d5e6f7a8b9c0d1/', 'synced by olgitbridge');
```
### Error Handling
Git errors (e.g., "nothing to commit") are caught and logged, not thrown.
```
--------------------------------
### Upsync — `src/upsync.js`
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Synchronizes the local pad directory with the Overleaf project state. It uploads changed/new files and removes deleted files from Overleaf.
```APIDOC
## Upsync — `src/upsync.js`
### Description
After a `git push`, compares the pad directory (updated working tree) against the blueprint directory (last known Overleaf state) and uploads only the changed or added files. Removes from Overleaf any files deleted locally.
### Usage
```js
const upsync = require('./src/upsync');
// project must have: id, padDir, blueDir
// project.info and project.tree are populated internally by joinProject/buildTree
await upsync(client, 'http://overleaf.example.com', project);
```
### Actions
- **Update/New File**: If `padData !== blueData` or file exists in pad but not blue, `POST /project/:id/upload?folder_id=:folderId` is used.
- **Delete File**: If file exists in blue but not pad, `DELETE /project/:id/doc/:id` (or `/file/`, `/folder/`) is used.
```
--------------------------------
### Include and Instantiate XMLHttpRequest
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/xmlhttprequest/README.md
Include the module in your project and create an instance of the XMLHttpRequest object. Ensure you use the lowercase string "xmlhttprequest" in your require() call, especially on case-sensitive file systems.
```javascript
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
var xhr = new XMLHttpRequest();
```
--------------------------------
### Emitting Custom Events
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/README.md
Illustrates how to emit custom events to the server with associated data.
```APIDOC
## Emitting Custom Events
### Description
Send custom events to the server with optional data.
### Code Example
```js
var socket = io.connect();
socket.emit('server custom event', { my: 'data' });
```
```
--------------------------------
### Download Project Zip Buffer
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Downloads the Overleaf project zip file from the specified project ID and returns the raw binary buffer. This buffer can then be passed to an unzipper for extraction.
```javascript
const zipBuffer = await olops.downloadZip(
client,
'http://overleaf.example.com',
'63f1a2b3c4d5e6f7a8b9c0d1' // project_id
);
// zipBuffer is a Buffer/ArrayBuffer; pass to unzipper for extraction:
const { Open } = require('unzipper');
const directory = await Open.buffer(zipBuffer);
await directory.extract({ path: '/var/olgitbridge/pads/63f1a2b3c4d5e6f7a8b9c0d1/' });
```
--------------------------------
### Build File Tree — olops.buildTree
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Converts a nested folder structure into a flat, name-keyed tree for efficient lookups. The output is a recursive object representing the project's file hierarchy.
```javascript
const tree = olops.buildTree(projectInfo.rootFolder[0]);
// Returns a recursive object:
// {
// type: 'folder', id: 'abc', name: 'rootFolder',
// subs: {
// 'main.tex': { type: 'doc', id: '...', name: 'main.tex', branch: },
// 'figure.png': { type: 'file', id: '...', name: 'figure.png', branch: },
// 'sections': { type: 'folder', id: '...', name: 'sections', subs: { ... } }
// }
// }
```
--------------------------------
### Add Folder — `olops.addFolder`
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Creates a new folder within an Overleaf project. It returns the new folder's ID, which can be used for subsequent uploads.
```APIDOC
## Add Folder — `olops.addFolder`
### Description
Creates a new folder inside an Overleaf project by POSTing to `/project/:id/folder`. Returns the new folder's `_id` for use in subsequent uploads.
### Usage
```js
const res = await olops.addFolder(
client,
'http://overleaf.example.com',
'63f1a2b3c4d5e6f7a8b9c0d1', // project_id
'parent_folder_id_here', // parent folder_id
'sections' // new folder name
);
const newFolderId = res.data._id;
```
### Behavior
If the folder already exists, `upsync` catches 'file already exists' and returns the sentinel string 'EXISTS' instead of throwing.
```
--------------------------------
### Downsync - src/downsync.js
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Downloads the Overleaf project as a zip, computes a content hash, and unpacks files only if the content has changed since the last run.
```APIDOC
## Downsync — `src/downsync.js`
Downloads the current Overleaf project as a zip, computes a content hash (path + size + CRC32 of each entry), compares it to the cached hash, and only unpacks to the pad and blueprint directories when content has changed.
```js
const downsync = require('./src/downsync');
// Returns true → zip was new, pad/blue directories updated, caller should git-commit
// Returns false → zip hash identical to last run, no work done
const changed = await downsync(client, 'http://overleaf.example.com', project);
if (changed) {
// project.padDir now contains the latest Overleaf files
// project.blueDir is an identical copy used later as a diff baseline for upsync
await git.save(count, project.padDir, 'synced by olgitbridge');
}
```
```
--------------------------------
### Add Folder — olops.addFolder
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Creates a new folder within an Overleaf project. Returns the new folder's ID for subsequent operations. Handles existing folders by returning 'EXISTS' instead of throwing.
```javascript
const res = await olops.addFolder(
client,
'http://overleaf.example.com',
'63f1a2b3c4d5e6f7a8b9c0d1', // project_id
'parent_folder_id_here', // parent folder_id
'sections' // new folder name
);
const newFolderId = res.data._id;
// If the folder already exists, upsync catches 'file already exists'
// and returns the sentinel string 'EXISTS' instead of throwing.
```
--------------------------------
### Cloning an Overleaf Project via Git
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Clones an Overleaf project using its project ID. Git will prompt for Overleaf email and password for authentication. The `.git` suffix is also accepted.
```bash
# Clone a project — git will prompt for Overleaf email and password
git clone http://gitbridge.example.com:5000/
# or with .git suffix (both are accepted):
git clone http://gitbridge.example.com:5000/.git
```
```bash
# Example with inline credentials (not recommended for production)
git clone http://user@example.com:password@gitbridge.example.com:5000/63f1a2b3c4d5e6f7a8b9c0d1
```
--------------------------------
### HTTP Basic Authentication - handleAuth
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Handles HTTP Basic Authentication for incoming requests. It checks for the Authorization header, decodes credentials, and serializes concurrent user requests.
```APIDOC
## HTTP Basic Authentication — `handleAuth`
On every request the server challenges git clients with HTTP 401 if no `Authorization` header is present, then uses the supplied Overleaf credentials to log in. A per-user semaphore ensures only one concurrent session per email address.
```js
// Internally inside src/server.js — called on every incoming request
const handleAuth = async function(req, res, client, project_id) {
let auth = req.headers.authorization;
if (!auth) {
// 401 triggers git's credential helper to prompt the user
res.writeHead(401, { 'WWW-Authenticate': 'Basic realm="olgitbridge"' });
res.end('Authorization is needed');
return false;
}
// Decode "Basic base64(email:password)"
auth = Buffer.from(auth.replace(/^Basic /, ''), 'base64').toString('utf8').split(':');
const email = auth[0];
const password = auth[1];
// Serialise concurrent requests from the same user
const uflag = await users.get(email);
try {
await olops.login(client, olServer, email, password);
await olops.getProjectPage(client, olServer, project_id);
} catch(e) {
users.release(email, uflag);
if (e.response.status === 401) { res.writeHead(401, 'Unauthorized'); res.end(); return; }
throw e;
}
return Object.freeze({ email, uflag });
};
```
```
--------------------------------
### Handle HTTP Basic Authentication
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Handles incoming HTTP requests, checks for the Authorization header, and decodes Overleaf credentials. It serializes concurrent requests from the same user and throws a 401 error if authentication fails.
```javascript
const handleAuth = async function(req, res, client, project_id) {
let auth = req.headers.authorization;
if (!auth) {
// 401 triggers git's credential helper to prompt the user
res.writeHead(401, { 'WWW-Authenticate': 'Basic realm="olgitbridge"' });
res.end('Authorization is needed');
return false;
}
// Decode "Basic base64(email:password)"
auth = Buffer.from(auth.replace(/^Basic /, ''), 'base64').toString('utf8').split(':');
const email = auth[0];
const password = auth[1];
// Serialise concurrent requests from the same user
const uflag = await users.get(email);
try {
await olops.login(client, olServer, email, password);
await olops.getProjectPage(client, olServer, project_id);
} catch(e) {
users.release(email, uflag);
if (e.response.status === 401) { res.writeHead(401, 'Unauthorized'); res.end(); return; }
throw e;
}
return Object.freeze({ email, uflag });
};
```
--------------------------------
### Overleaf Login with Axios Client
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Logs into Overleaf by fetching the login page, extracting the CSRF token, and POSTing credentials. The axios client automatically retains the session cookie.
```javascript
const olops = require('./src/olops');
const client = olops.client(); // axios instance with cookie jar
await olops.login(client, 'http://overleaf.example.com', 'alice@example.com', 's3cr3t');
// Session cookie is now stored in the client's CookieJar and sent on all subsequent requests.
// Throws with e.response.status === 401 if credentials are wrong.
```
--------------------------------
### CSRF Token Extraction - olops.getProjectPage
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Fetches the project page after login to extract the CSRF token from the meta tag and sets it as a default header for the axios client.
```APIDOC
## CSRF Token Extraction — `olops.getProjectPage`
Fetches `/project/` after login and stores the CSRF token found in the page's `` tag as a default header on the axios client, making it available for all subsequent mutating API calls.
```js
await olops.getProjectPage(client, 'http://overleaf.example.com', '63f1a2b3c4d5e6f7a8b9c0d1');
// After this call:
// client.defaults.headers.common['x-csrf-token'] === ''
```
```
--------------------------------
### Upload File — olops.upload
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Uploads a single file or document to Overleaf via multipart/form-data POST. Requires Overleaf client, project ID, folder ID, filename, and file data as a Buffer. Throws errors on non-2xx responses.
```javascript
const data = await fs.readFile('/var/olgitbridge/pads//main.tex');
await olops.upload(
client,
'http://overleaf.example.com',
'63f1a2b3c4d5e6f7a8b9c0d1', // project_id
'root_folder_id_here', // folder_id (from buildTree)
'main.tex', // filename
data // Buffer
);
// Throws Error(' ') on non-2xx responses
```
--------------------------------
### Extract CSRF Token from Project Page
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Fetches the Overleaf project page after login and extracts the CSRF token from a meta tag. This token is then set as a default header for subsequent mutating API calls.
```javascript
await olops.getProjectPage(client, 'http://overleaf.example.com', '63f1a2b3c4d5e6f7a8b9c0d1');
// After this call:
// client.defaults.headers.common['x-csrf-token'] === ''
```
--------------------------------
### Pushing Changes to Overleaf via Git
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Commits and pushes local changes back to Overleaf. Olgitbridge compares the push against the last downloaded blueprint and uploads only the modified files.
```bash
# Make changes and push back to Overleaf
cd 63f1a2b3c4d5e6f7a8b9c0d1
echo "\section{New Section}" >> main.tex
git add main.tex
git commit -m "Add new section"
git push
# olgitbridge diffs the push against the last downloaded blueprint
# and uploads only the changed files back to Overleaf
```
--------------------------------
### Set SWF Location for Cross-Domain Hosting
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/lib/vendor/web-socket-js/README.md
Configure the JavaScript to point to the SWF file when hosting HTML and SWF files on different domains. This allows cross-domain communication but reduces security by allowing arbitrary TCP data.
```javascript
WEB_SOCKET_SWF_LOCATION = "URL of your WebSocketMainInsecure.swf";
```
--------------------------------
### Forcing Disconnection
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/README.md
Demonstrates how to manually disconnect the socket client from the server.
```APIDOC
## Forcing Disconnection
### Description
Manually close the connection to the socket.io server.
### Code Example
```js
var socket = io.connect();
socket.on('connect', function () {
socket.disconnect();
});
```
```
--------------------------------
### File Upload — `olops.upload`
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Uploads a single file or document to Overleaf using a multipart/form-data POST request to the project's upload endpoint.
```APIDOC
## File Upload — `olops.upload`
### Description
Uploads a single file or document to Overleaf using a `multipart/form-data` POST to the project upload endpoint.
### Usage
```js
const data = await fs.readFile('/var/olgitbridge/pads//main.tex');
await olops.upload(
client,
'http://overleaf.example.com',
'63f1a2b3c4d5e6f7a8b9c0d1', // project_id
'root_folder_id_here', // folder_id (from buildTree)
'main.tex', // filename
data // Buffer
);
```
### Error Handling
Throws `Error(' ')` on non-2xx responses.
```
--------------------------------
### Overleaf Logout - olops.logout
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Logs out of the Overleaf session by fetching the project dashboard for a fresh CSRF token and then POSTing to the logout endpoint.
```APIDOC
## Overleaf Logout — `olops.logout`
Fetches the project dashboard (to obtain a fresh CSRF token) and then POSTs to `/logout`, cleanly ending the Overleaf session.
```js
// Called automatically at the end of every git request
await olops.logout(client, 'http://overleaf.example.com');
// The session cookie is invalidated on the Overleaf server.
```
```
--------------------------------
### Overleaf Login - olops.login
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Logs into Overleaf by fetching the login page, extracting the CSRF token, and POSTing credentials. The axios client automatically manages the session cookie.
```APIDOC
## Overleaf Login — `olops.login`
Fetches the Overleaf login page, extracts the CSRF token from a hidden form field, and POSTs credentials. The axios client retains the session cookie automatically via `tough-cookie`.
```js
const olops = require('./src/olops');
const client = olops.client(); // axios instance with cookie jar
await olops.login(client, 'http://overleaf.example.com', 'alice@example.com', 's3cr3t');
// Session cookie is now stored in the client's CookieJar and sent on all subsequent requests.
// Throws with e.response.status === 401 if credentials are wrong.
```
```
--------------------------------
### Semaphore — `src/semaphore.js`
Source: https://context7.com/chazeon/olgitbridge/llms.txt
A promise-based FIFO semaphore designed to serialize concurrent requests, ensuring that operations like Git or user requests are processed sequentially.
```APIDOC
## Semaphore — `src/semaphore.js`
### Description
A promise-based FIFO semaphore used to serialise concurrent git or user requests. Each `request()` call returns a unique frozen flag object; the same flag must be passed to `release()`.
### Usage
```js
const Semaphore = require('./src/semaphore');
const sem = new Semaphore();
async function worker(id) {
const flag = await sem.request(); // blocks if another worker holds the semaphore
try {
console.log(`Worker ${id} has the lock`);
await doExclusiveWork();
} finally {
sem.release(flag); // MUST pass the same flag returned by request()
}
}
// Concurrent calls are queued and served in FIFO order
Promise.all([worker(1), worker(2), worker(3)]);
// Output: Worker 1 has the lock → Worker 2 has the lock → Worker 3 has the lock
```
```
--------------------------------
### Enable Debugging for web-socket-js
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/lib/vendor/web-socket-js/README.md
Enables debug logging for the web-socket-js library. This is useful for troubleshooting by outputting errors to the browser's developer console.
```javascript
WEB_SOCKET_DEBUG = true;
```
--------------------------------
### Emitting Custom Events
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/README.md
Emit custom events to the server with associated data. This allows for more structured communication beyond the default 'message' event.
```javascript
var socket = io.connect();
socket.emit('server custom event', { my: 'data' });
```
--------------------------------
### Send Message via WebSocket
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/lib/vendor/web-socket-js/sample.html
Sends a message from an input field to the WebSocket server. The message is then logged to the console.
```javascript
function onSubmit() {
var input = document.getElementById("input");
ws.send(input.value);
output("send: " + input.value);
input.value = "";
input.focus();
}
```
--------------------------------
### Overleaf Logout
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Logs out of the Overleaf session by fetching the project dashboard for a CSRF token and then POSTing to the logout endpoint. This invalidates the session cookie on the server.
```javascript
// Called automatically at the end of every git request
await olops.logout(client, 'http://overleaf.example.com');
// The session cookie is invalidated on the Overleaf server.
```
--------------------------------
### Semaphore for Concurrency Control — src/semaphore.js
Source: https://context7.com/chazeon/olgitbridge/llms.txt
A promise-based FIFO semaphore to serialize concurrent requests. Each request returns a flag that must be passed to release().
```javascript
const Semaphore = require('./src/semaphore');
const sem = new Semaphore();
async function worker(id) {
const flag = await sem.request(); // blocks if another worker holds the semaphore
try {
console.log(`Worker ${id} has the lock`);
await doExclusiveWork();
} finally {
sem.release(flag); // MUST pass the same flag returned by request()
}
}
// Concurrent calls are queued and served in FIFO order
Promise.all([worker(1), worker(2), worker(3)]);
// Output: Worker 1 has the lock → Worker 2 has the lock → Worker 3 has the lock
```
--------------------------------
### Output Log Messages
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/lib/vendor/web-socket-js/sample.html
Appends messages to the log element on the page, escaping HTML special characters to prevent rendering issues.
```javascript
function output(str) {
var log = document.getElementById("log");
var escaped = str.replace(/&/, "&").replace(/, "<"). replace(/>/, ">").replace(/"/, """);
log.innerHTML = escaped + "
" + log.innerHTML;
}
```
--------------------------------
### Delete Entity — `olops.remove`
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Deletes a document, binary file, or folder from an Overleaf project using the appropriate REST endpoint.
```APIDOC
## Delete Entity — `olops.remove`
### Description
Deletes a document, binary file, or folder from an Overleaf project using the appropriate REST endpoint.
### Usage
```js
// Remove a doc
await olops.remove(client, 'http://overleaf.example.com', '63f1a2...', 'doc', 'doc_id_here');
// Remove a binary file
await olops.remove(client, 'http://overleaf.example.com', '63f1a2...', 'file', 'file_id_here');
// Remove a folder (recursively on Overleaf's side)
await olops.remove(client, 'http://overleaf.example.com', '63f1a2...', 'folder', 'folder_id_here');
```
### Error Handling
Throws `Error()` for unknown entity types.
```
--------------------------------
### Delete Entity — olops.remove
Source: https://context7.com/chazeon/olgitbridge/llms.txt
Deletes a document, binary file, or folder from an Overleaf project using the appropriate REST endpoint. Throws an error for unknown entity types.
```javascript
// Remove a doc
await olops.remove(client, 'http://overleaf.example.com', '63f1a2...', 'doc', 'doc_id_here');
// Remove a binary file
await olops.remove(client, 'http://overleaf.example.com', '63f1a2...', 'file', 'file_id_here');
// Remove a folder (recursively on Overleaf's side)
await olops.remove(client, 'http://overleaf.example.com', '63f1a2...', 'folder', 'folder_id_here');
// Throws Error() for unknown entity types
```
--------------------------------
### Forcing Disconnection
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/README.md
Manually disconnect the socket from the server. This is often done within a 'connect' event handler to immediately close the connection.
```javascript
var socket = io.connect();
socket.on('connect', function () {
socket.disconnect();
});
```
--------------------------------
### Close WebSocket Connection
Source: https://github.com/chazeon/olgitbridge/blob/main/lib/socket.io-client/lib/vendor/web-socket-js/sample.html
Closes the active WebSocket connection.
```javascript
function onCloseClick() {
ws.close();
}
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.