diff --git a/apps/obsidian/package.json b/apps/obsidian/package.json index c8171caee..6b70f9052 100644 --- a/apps/obsidian/package.json +++ b/apps/obsidian/package.json @@ -37,6 +37,9 @@ }, "dependencies": { "@codemirror/view": "^6.38.8", + "@repo/database": "workspace:*", + "@repo/utils": "workspace:*", + "@supabase/supabase-js": "catalog:", "date-fns": "^4.1.0", "nanoid": "^4.0.2", "react": "catalog:obsidian", diff --git a/apps/obsidian/scripts/compile.ts b/apps/obsidian/scripts/compile.ts index 04ea91aee..e749cb6af 100644 --- a/apps/obsidian/scripts/compile.ts +++ b/apps/obsidian/scripts/compile.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import esbuild from "esbuild"; import fs from "fs"; import path from "path"; @@ -10,6 +11,19 @@ import autoprefixer from "autoprefixer"; dotenv.config(); +// For local dev: Set SUPABASE_USE_DB=local and run `pnpm run genenv` in packages/database +let envContents: (() => Record) | null = null; +try { + const dbDotEnv = require("@repo/database/dbDotEnv"); + envContents = dbDotEnv.envContents; +} catch (error) { + if ((error as Error).message.includes("Cannot find module")) { + console.error("Build the database module before compiling obsidian"); + process.exit(1); + } + throw error; +} + const DEFAULT_FILES_INCLUDED = ["manifest.json"]; const isProd = process.env.NODE_ENV === "production"; @@ -43,6 +57,7 @@ export const args = { "@lezer/common", "@lezer/highlight", "@lezer/lr", + "tslib=window.TSLib", ...builtins, ], } as CliOpts; @@ -89,6 +104,10 @@ export const compile = ({ fs.mkdirSync(outdir, { recursive: true }); const buildPromises = [] as Promise[]; + if (!envContents) { + throw new Error("envContents not loaded. Build the database module first."); + } + const dbEnv = envContents(); buildPromises.push( builder({ absWorkingDir: process.cwd(), @@ -100,6 +119,15 @@ export const compile = ({ minify: isProd, entryNames: out, external: external, + define: { + "process.env.SUPABASE_URL": dbEnv.SUPABASE_URL + ? `"${dbEnv.SUPABASE_URL}"` + : "null", + "process.env.SUPABASE_ANON_KEY": dbEnv.SUPABASE_ANON_KEY + ? `"${dbEnv.SUPABASE_ANON_KEY}"` + : "null", + "process.env.NEXT_API_ROOT": `"${dbEnv.NEXT_API_ROOT || ""}"`, + }, plugins: [ { name: "log", diff --git a/apps/obsidian/src/components/GeneralSettings.tsx b/apps/obsidian/src/components/GeneralSettings.tsx index 78aa75bdd..86305d7bc 100644 --- a/apps/obsidian/src/components/GeneralSettings.tsx +++ b/apps/obsidian/src/components/GeneralSettings.tsx @@ -3,6 +3,7 @@ import { usePlugin } from "./PluginContext"; import { Notice, setIcon } from "obsidian"; import SuggestInput from "./SuggestInput"; import { SLACK_LOGO, WHITE_LOGO_SVG } from "~/icons"; +import { initializeSupabaseSync } from "~/utils/syncDgNodesToSupabase"; const DOCS_URL = "https://discoursegraphs.com/docs/obsidian"; const COMMUNITY_URL = @@ -157,6 +158,9 @@ const GeneralSettings = () => { const [nodeTagHotkey, setNodeTagHotkey] = useState( plugin.settings.nodeTagHotkey, ); + const [syncModeEnabled, setSyncModeEnabled] = useState( + plugin.settings.syncModeEnabled ?? false, + ); const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); const handleToggleChange = (newValue: boolean) => { @@ -190,6 +194,11 @@ const GeneralSettings = () => { } }, []); + const handleSyncModeToggle = useCallback((newValue: boolean) => { + setSyncModeEnabled(newValue); + setHasUnsavedChanges(true); + }, []); + const handleSave = async () => { const trimmedNodesFolderPath = nodesFolderPath.trim(); const trimmedCanvasFolderPath = canvasFolderPath.trim(); @@ -201,12 +210,25 @@ const GeneralSettings = () => { plugin.settings.canvasAttachmentsFolderPath = trimmedCanvasAttachmentsFolderPath; plugin.settings.nodeTagHotkey = nodeTagHotkey || ""; + plugin.settings.syncModeEnabled = syncModeEnabled; setNodesFolderPath(trimmedNodesFolderPath); setCanvasFolderPath(trimmedCanvasFolderPath); setCanvasAttachmentsFolderPath(trimmedCanvasAttachmentsFolderPath); await plugin.saveSettings(); new Notice("General settings saved"); setHasUnsavedChanges(false); + + if (syncModeEnabled) { + try { + await initializeSupabaseSync(plugin); + new Notice("Sync mode initialized successfully"); + } catch (error) { + console.error("Failed to initialize sync mode:", error); + new Notice( + `Failed to initialize sync mode: ${error instanceof Error ? error.message : String(error)}`, + ); + } + } }; return ( @@ -311,6 +333,23 @@ const GeneralSettings = () => { +
+
+
(BETA) Sync mode enable
+
+ Enable synchronization with Discourse Graph database +
+
+
+
handleSyncModeToggle(!syncModeEnabled)} + > + +
+
+
+