Skip to content
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ main.js

# obsidian
data.json

# Claude
.claude
132 changes: 132 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# CLAUDE.md
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the CLAUDE.md file was added accidentally. It looks like a temporary artifact produced by the Claude AI assistant, not something intended for the repo. Can you remove it from this PR?


This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

IMPORTANT: in all interactions and commit messages, be extremely concise and sacrifice grammar for the sake of concision.

## Project Overview

This is an Obsidian plugin that exposes a secure REST API for programmatic interaction with Obsidian vaults. It allows external tools and automation to read, create, update, delete notes, execute commands, and search content via HTTP/HTTPS requests.

# Development Guidelines

## Test-Driven Development

Write tests before implementing functionality. Follow this cycle:

1. Write a failing test that defines the desired behavior
2. Implement the minimum code needed to make the test pass
3. Refactor while keeping tests green

When creating new features or fixing bugs, start by adding or modifying tests. Ensure all tests pass before considering work complete. Place tests in appropriate directories following the project's existing test structure.

## GitHub Issue Integration

Before starting work, check if a relevant GitHub issue exists. If working on a specific issue, reference it in commit messages using the issue number (e.g., "Fixes #123" or "Addresses #123").

When encountering bugs or identifying potential improvements during development, create GitHub issues to track them rather than immediately implementing fixes outside the current scope.

For significant changes, review related issues to understand context and avoid duplicate work. Update issue status and add comments when making meaningful progress.

## Code Quality

Maintain consistency with existing code style and architecture patterns. Keep changes focused on the task at hand. Write clear commit messages that explain why changes were made, not just what changed.


## Development Commands

### Build and Development
- `npm run dev` - Start development build with watch mode (uses esbuild)
- `npm run build` - Build for production (runs TypeScript type checking first, then esbuild bundle)
- `npm test` - Run Jest test suite

### Documentation
- `npm run build-docs` - Generate OpenAPI documentation from Jsonnet source
- `npm run serve-docs` - Serve Swagger UI for API documentation (requires Docker)

## Architecture

### Core Components

**Main Plugin (`src/main.ts`)**
- `LocalRestApi` class: Plugin entry point that manages HTTPS/HTTP server lifecycle
- Generates self-signed certificates on first run using node-forge
- Creates secure (HTTPS on port 27124) and optional insecure (HTTP on port 27123) servers
- Delegates request handling to `RequestHandler`

**Request Handler (`src/requestHandler.ts`)**
- `RequestHandler` class: Core Express.js application that defines all API routes
- Implements bearer token authentication middleware
- Handles all vault operations (read/write/patch/delete files)
- Supports periodic notes (daily, weekly, monthly, yearly)
- Implements search functionality (simple search and JSON logic queries)
- Provides command execution capabilities
- Uses markdown-patch library for PATCH operations on notes

**Public API (`src/api.ts`)**
- `LocalRestApiPublicApi` class: Allows other Obsidian plugins to register custom API extensions
- Plugins get their own Express router to add custom routes
- Extensions can be unregistered when plugins unload

### Key API Endpoints

The plugin exposes these endpoint categories:
- `/active/` - Operations on currently active file
- `/vault/*` - Operations on vault files by path
- `/periodic/:period/` - Daily/weekly/monthly/yearly note operations
- `/commands/` - List and execute Obsidian commands
- `/search/` - Content search with various query methods
- `/open/*` - Open files in Obsidian

All endpoints (except certificate and docs) require bearer token authentication via `Authorization` header.

### Testing

The test suite uses Jest with ts-jest for TypeScript support. Tests mock the Obsidian API using `mocks/obsidian.ts`. The main test file is `src/requestHandler.test.ts`.

To run a single test file:
```bash
npm test -- requestHandler.test.ts
```

### Build Process

Uses esbuild for bundling:
- Entry point: `src/main.ts`
- Output: `main.js` (CommonJS format)
- External dependencies: Obsidian API and built-in Node modules
- YAML files loaded as text (for OpenAPI spec embedding)
- Development builds include inline source maps

### TypeScript Configuration

- Target: ES6
- Module: ESNext with Node resolution
- Strict type checking enabled (`noImplicitAny`)
- Test files excluded from main compilation

## Important Patterns

### Authentication
All API requests (except `/`, certificate endpoint, and OpenAPI spec) require bearer token authentication. The API key is auto-generated on first run using SHA-256 hash of random bytes.

### Content Types
The API accepts multiple content types:
- `text/markdown` - Standard markdown content
- `application/json` - JSON data
- `application/vnd.olrapi.note+json` - Special note format with frontmatter
- `application/vnd.olrapi.jsonlogic+json` - JSON Logic queries for filtering
- `application/vnd.olrapi.dataview.dql+txt` - Dataview query language

### PATCH Operations
Uses the `markdown-patch` library for structured updates. Supports:
- Heading-based insertions (specify heading boundary and position)
- Target-based patches with operation types (insert, append, prepend, replace)
- Content-type-aware patching

### Certificate Management
Self-signed certificates are auto-generated with:
- 2048-bit RSA keypairs
- 365-day validity
- Subject Alternative Names support for custom hostnames
- Must be trusted by client browsers for HTTPS connections
60 changes: 60 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
.PHONY: help build install dev clean
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that this might be helpful for you, but I'm not sure I want to take on maintenance of this particular part of this PR and instead would rather we keep all scripts in package.json. Could I trouble you into removing this?

I know that it seems harmless to add unrelated things in a single PR, but unfortunately every bit of code that's added is a liability that will require future maintenance, support, and updates as time goes on, and I really need to be careful about what I agree to maintain going forward.


# Default vault path - override with: make install VAULT_PATH=/path/to/vault
VAULT_PATH ?= $(HOME)/Documents/Obsidian/MyVault
PLUGIN_DIR = $(VAULT_PATH)/.obsidian/plugins/obsidian-local-rest-api

help:
@echo "Local REST API Development Commands"
@echo ""
@echo " make build - Build plugin (creates main.js)"
@echo " make install - Install plugin to Obsidian vault"
@echo " make dev - Build in watch mode"
@echo " make clean - Remove build artifacts"
@echo ""
@echo "Installation:"
@echo " 1. Set VAULT_PATH: export VAULT_PATH=/path/to/your/vault"
@echo " 2. Run: make build install"
@echo " 3. In Obsidian: Settings → Community Plugins → Enable 'Local REST API'"
@echo " 4. Get API key from plugin settings"
@echo ""
@echo "Testing:"
@echo " make test - Run tests"
@echo ""
@echo "Current vault path: $(VAULT_PATH)"

build:
@echo "Building plugin..."
npm run build
@echo "✓ Build complete: main.js created"

install: build
@echo "Installing to Obsidian vault..."
@if [ ! -d "$(VAULT_PATH)" ]; then \
echo "Error: Vault not found at $(VAULT_PATH)"; \
echo "Set VAULT_PATH: export VAULT_PATH=/path/to/your/vault"; \
exit 1; \
fi
@mkdir -p "$(PLUGIN_DIR)"
@cp main.js "$(PLUGIN_DIR)/"
@cp manifest.json "$(PLUGIN_DIR)/"
@cp styles.css "$(PLUGIN_DIR)/"
@echo "✓ Installed to $(PLUGIN_DIR)"
@echo ""
@echo "Next steps:"
@echo " 1. Restart Obsidian (or reload plugins)"
@echo " 2. Settings → Community Plugins"
@echo " 3. Enable 'Local REST API'"
@echo " 4. Find API key in plugin settings"

dev:
@echo "Starting dev mode (watch)..."
npm run dev

test:
npm test

clean:
@echo "Cleaning build artifacts..."
@rm -f main.js
@echo "✓ Clean complete"
Loading
Loading