Skip to content

ENG-1975 Define schema file contract and shared foundation for Obsidian export/import - #1180

Open
trangdoan982 wants to merge 8 commits into
mainfrom
eng-1975-schema-foundation
Open

ENG-1975 Define schema file contract and shared foundation for Obsidian export/import#1180
trangdoan982 wants to merge 8 commits into
mainfrom
eng-1975-schema-foundation

Conversation

@trangdoan982

@trangdoan982 trangdoan982 commented Jun 30, 2026

Copy link
Copy Markdown
Member

Overview of all 5 PRs:
https://www.loom.com/share/4374b7ddce4c4b7c99c73b292b752d9e

Walk through of this PR:
https://www.loom.com/share/73e448a429ef4f75b76ae8172e2508d6

Summary

Ships the shared foundation that the schema selection panel, export, and import PRs all stack on top of.

  • types.ts — adds DiscourseSchemaFile and DiscourseSchemaTemplate type definitions for the exported JSON file format, plus SchemaSelection (reused by both export and import)
  • specValidation.ts — adds dgSchemaFileSchema (Zod), parseDgSchemaFile, getDgSchemaFileName(vaultName?) (kebab-cases vault name → dg-schema-<vault>.json), and DG_SCHEMA_EXPORT_VERSION = 1
  • nativeJsonFileDialogs.ts — Electron save/open dialogs for reading and writing JSON outside the vault

Identifying the source vault: vaultId

The file records vaultId — the Obsidian appId — alongside the human-readable vaultName.

vaultName cannot identify a source space: two vaults can share a name, so it is not unique. vaultId lets an importer rebuild the source RID as:

orn:obsidian.schema:<appId>/<localId>

This is byte-identical to what the existing Supabase import path already generates for schema items (mapNodeTypeIdToLocal / mapRelationTypeToLocal in importNodes.ts / importRelations.ts). Schema imported from a file and content imported from that same vault over Supabase therefore resolve to the same importedFromRid, instead of the file-import path producing untraceable items.

The Zod field is required, not optional. The export command that produces these files ships in #1263 and has not merged, so no version: 1 files exist in the wild and there is nothing to stay backward-compatible with. A field added after this stack merges would need the optional treatment.

This field lives here rather than in #1263 because it is part of the file contract, which is this PR's scope. #1263 only populates it.

Stack

This is PR 1 of 5 for FEE-840. Stack order:

  1. This PR — shared foundation (ENG-1975)
  2. Schema selection panel UI (ENG-2083) — ENG-2083 Add schema selection panel UI for Obsidian export/import #1262
  3. Schema export command (ENG-1976) — ENG-1976 Add schema export command to Obsidian #1263
  4. Schema import data layer (ENG-1977) — ENG-1977 Add schema import data layer for Obsidian #1264
  5. Schema import UI (ENG-2084) — ENG-2084 Add schema import UI for Obsidian #1265

Test plan

  • pnpm --filter @discourse-graphs/obsidian check-types passes
  • Every downstream branch in the stack typechecks against this base
  • Omitting vaultId from a DiscourseSchemaFile literal is a compile error (verified against specExport.ts: TS2741: Property 'vaultId' is missing)
  • RID round-trips: ridToSpaceUriAndLocalId(spaceUriAndLocalIdToRid("obsidian:<appId>", localId, "schema")) recovers the original pair
  • Manual: a real export contains a non-empty vaultId matching the vault's appId

…export/import.

Adds DiscourseSchemaFile and DiscourseSchemaTemplate type definitions, plus
getDgSchemaFileName and DG_SCHEMA_EXPORT_VERSION — the minimal shared primitives
needed by both the schema export (ENG-1976) and import (ENG-1977) features.

Co-authored-by: Cursor <cursoragent@cursor.com>
@linear-code

linear-code Bot commented Jun 30, 2026

Copy link
Copy Markdown

ENG-1975

@supabase

supabase Bot commented Jun 30, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
discourse-graph Skipped Skipped Jul 30, 2026 6:12pm

Request Review

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

Open in Devin Review

Comment thread apps/obsidian/src/utils/specValidation.ts Outdated
Comment thread apps/obsidian/src/utils/specValidation.ts Outdated
@trangdoan982 trangdoan982 changed the title ENG-1975 Add schema file contract and shared foundation for Obsidian export/import ENG-1975 Define schema file contract and shared foundation for Obsidian export/import Jul 29, 2026
… types

- Delete ReactRootModal.tsx (no callers yet; DRY savings too small to justify the abstraction layer)
- Annotate each sub-schema with z.ZodType<T> so TypeScript verifies schema coverage against the authoritative types in types.ts at compile time
- Drop the `as DiscourseSchemaFile` cast from parseDgSchemaFile — no longer needed once dgSchemaFileSchema is typed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…port)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
vaultName is not unique — two vaults can share a name — so it cannot
identify the source space. Recording vaultId (the Obsidian appId) lets an
importer rebuild the source RID as orn:obsidian.schema:<appId>/<localId>,
which is what the existing Supabase import path already generates. Schema
imported from a file and content imported from that same vault over
Supabase then resolve to the same importedFromRid.

Required rather than optional: the export command that produces these
files has not shipped, so no version 1 files exist to stay compatible
with.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant