[Feature Request] Extend Plugin API for full ontology import/export parity in DB graphs
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 26
- Forks
- 8
- PR merge metrics
- No merged PRs in 30d
Description
### Problem Statement
The Plugin API for DB graphs does not support all fields that Logseq exports in its native EDN format. This prevents plugins from implementing complete ontology import/export functionality.
When users export ontology from a DB graph and attempt to re-import it via a plugin, some data is lost:
| Data Type | Fields in EDN Export | Fields Settable via API | Lost on Import |
|-----------|---------------------|------------------------|----------------|
| Properties | 14 | 10 | **4 fields (29%)** |
| Classes/Tags | 7 | 6 | **1 field (14%)** |
### What Works (Discovered Feb 2025)
Through extensive console testing, we discovered workarounds for several fields:
#### System Description Field
Using the **full namespaced key** with `upsertBlockProperty` sets the system description:
```typescript
// ❌ WRONG - creates a user property named "description"
await logseq.Editor.upsertBlockProperty(uuid, 'description', 'My description')
// ✅ CORRECT - sets the system logseq.property/description field
await logseq.Editor.upsertBlockProperty(uuid, ':logseq.property/description', 'My description')
```
The value is stored as an entity reference (Logseq creates a new entity containing the text).
#### Tabler Icons on Properties and Tags
`setBlockIcon()` **works for Tabler icons** on properties and tags:
```typescript
// ✅ Works - Tabler icon on property
const prop = await logseq.Editor.getProperty('my-property')
await logseq.Editor.setBlockIcon(prop.uuid, 'tabler-icon', 'star')
// ✅ Works - Tabler icon on tag
const tag = await logseq.Editor.getTag('MyTag')
await logseq.Editor.setBlockIcon(tag.uuid, 'tabler-icon', 'folder')
```
### What Doesn't Work
#### Emoji Icons - Lookup Table Inaccessible
`setBlockIcon()` **fails for all emoji formats**:
```typescript
await logseq.Editor.setBlockIcon(uuid, 'emoji', 'rocket') // ❌ "Can't find emoji for rocket"
await logseq.Editor.setBlockIcon(uuid, 'emoji', '🚀') // ❌ "Can't find emoji for 🚀"
await logseq.Editor.setBlockIcon(uuid, 'emoji', ':rocket:') // ❌ "Can't find emoji for :rocket:"
```
**Root cause:** Logseq's emoji lookup table is internal and not accessible to plugins. The EDN export shows emojis stored with numeric IDs (e.g., `{:type :emoji, :id "100"}`) but there's no way for plugins to discover or use these IDs.
#### Class/Tag Title - Ownership Restriction
Attempting to set `:logseq.class/title` fails:
```typescript
await logseq.Editor.upsertBlockProperty(tagUuid, ':logseq.class/title', 'My Display Title')
// ❌ Error: "Plugins can only upsert its own properties"
```
Unlike `:logseq.property/description` which works, the title field is blocked.
### Remaining Fields Not Settable via Plugin API
#### Properties
| Missing Field | Impact |
|---------------|--------|
| **icon (emoji only)** | Cannot set emoji icons (Tabler icons work) |
| **closedValues** | Cannot create enum/choice/select properties |
| **datetime type** | Must downgrade to `date` (loses time component) |
| **position** | Cannot control UI ordering |
| **default** | Cannot set default values |
#### Classes/Tags
| Missing Field | Impact |
|---------------|--------|
| **icon (emoji only)** | Cannot set emoji icons (Tabler icons work) |
| **title** | Cannot set display name (blocked by ownership restriction) |
| **position** | Cannot control UI ordering |
### Use Case
I'm building an ontology import plugin that allows users to:
1. Export ontology definitions from one DB graph
2. Share them via a marketplace/repository
3. Import them into another DB graph
Currently, imported ontologies lose emoji icons, enum configurations (closedValues), and display titles. Tabler icons and descriptions now import successfully.
### Proposed Solutions
#### 1. Expose emoji lookup or accept emoji characters directly
Either:
- **Option A:** Accept emoji characters directly in `setBlockIcon`: `setBlockIcon(uuid, 'emoji', '🚀')`
- **Option B:** Accept standard emoji names: `setBlockIcon(uuid, 'emoji', 'rocket')`
- **Option C:** Document the emoji ID format so plugins can use it
#### 2. Add `closedValues` support to `upsertProperty`
```typescript
upsertProperty(key: string, schema?: {
// Existing fields...
// Requested addition
closedValues?: Array<{
value: string;
icon?: { type: "emoji" | "tabler-icon"; id: string };
description?: string;
}>;
}): Promise
```
#### 3. Allow setting class/tag title
Either remove the ownership restriction for `:logseq.class/title` or add it to the `createTag` options:
```typescript
createTag(name: string, opts?: {
uuid?: string; // Existing
title?: string; // Requested
}): Promise
```
#### 4. Add `datetime` property type
Currently `datetime` must be downgraded to `date`, losing the time component.
### Priority Ranking
1. 🔴 **Critical:** Fix emoji icon setting (expose lookup or accept characters) - Icons are the primary visual identity of ontology elements; losing them during import significantly degrades the user experience
2. 🔴 **Critical:** Add `closedValues` support to `upsertProperty` - Required for enum/select properties
3. 🟡 **Medium:** Allow setting class/tag title
4. 🟡 **Medium:** Add `datetime` property type
5. 🟢 **Low:** Add `position` to schema APIs
### Environment
- Logseq version: 2.0.0 (DB graph mode)
- Platform: Windows
- Plugin API version: @logseq/libs latest
### What We Learned (Testing Details)
For reference, here's what we discovered through console testing:
| Feature | Method | Status |
|---------|--------|--------|
| System Description | `upsertBlockProperty(uuid, ':logseq.property/description', text)` | ✅ Works |
| Tabler Icons | `setBlockIcon(uuid, 'tabler-icon', 'iconName')` | ✅ Works |
| Emoji Icons | `setBlockIcon(uuid, 'emoji', ...)` | ❌ All formats fail |
| Class Title | `upsertBlockProperty(uuid, ':logseq.class/title', text)` | ❌ Ownership blocked |
| Icon via upsertBlockProperty | `upsertBlockProperty(uuid, ':logseq.property/icon', {...})` | ❌ Renders "Invalid icon" |
**Key insight:** `setBlockIcon` stores icons as `{type: 'tablerIcon', id: 'name'}` (camelCase), but setting this format directly via `upsertBlockProperty` still renders as "Invalid icon" - there's internal processing in `setBlockIcon` that can't be replicated.
### Additional Context
Full field-by-field reconciliation available here: [API Field Reconciliation Document](https://github.com/C0ntr0lledCha0s/logseq-ontology-sync-plugin/blob/main/docs/api-field-reconciliation.md)
This enhancement would enable a richer ecosystem of ontology sharing and template plugins for DB graphs.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the @logseq/libs entry points named in the issue: setBlockIcon, upsertProperty, upsertBlockProperty, and createTag. Read docs/api-field-reconciliation.md and reproduce the documented DB graph import/export gaps; done means the requested ontology fields, including emoji icons, closedValues, titles, datetime, and position, can round-trip through the plugin API.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100