vertex-notes 0.3.1 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +130 -130
  2. package/bin/run.js +3 -3
  3. package/dist/{chunk-JGE6NM2D.js → chunk-23CKP3YP.js} +1 -2
  4. package/dist/{chunk-PBF5EE4Y.js → chunk-DRIWYEQE.js} +0 -1
  5. package/dist/{chunk-HJR4UBO3.js → chunk-QQO4JMNC.js} +2 -3
  6. package/dist/{chunk-QEOOUDO3.js → chunk-XJVEK2OB.js} +552 -47
  7. package/dist/commands/capture.js +3 -4
  8. package/dist/commands/daily.js +3 -4
  9. package/dist/commands/delete.js +3 -4
  10. package/dist/commands/edit.js +3 -8
  11. package/dist/commands/export.js +3 -4
  12. package/dist/commands/hello.js +1 -2
  13. package/dist/commands/help.js +1 -2
  14. package/dist/commands/howto.js +0 -1
  15. package/dist/commands/import.js +3 -4
  16. package/dist/commands/interactive.js +45 -4
  17. package/dist/commands/login.js +2 -3
  18. package/dist/commands/logout.js +1 -2
  19. package/dist/commands/new.js +3 -4
  20. package/dist/commands/notes.js +3 -4
  21. package/dist/commands/restore.js +3 -4
  22. package/dist/commands/search.js +3 -4
  23. package/dist/commands/status.js +3 -4
  24. package/dist/commands/syntax.js +0 -1
  25. package/dist/commands/tags.js +3 -4
  26. package/dist/commands/today.js +3 -4
  27. package/dist/commands/trash/empty.js +4 -5
  28. package/dist/commands/trash/index.js +3 -4
  29. package/dist/commands/view.js +3 -4
  30. package/dist/commands/whoami.js +1 -2
  31. package/dist/index.js +0 -1
  32. package/dist/lib/client.js +3 -4
  33. package/dist/lib/config.js +1 -2
  34. package/dist/lib/file-cleanup.js +2 -3
  35. package/package.json +56 -54
  36. package/dist/chunk-HJR4UBO3.js.map +0 -1
  37. package/dist/chunk-JGE6NM2D.js.map +0 -1
  38. package/dist/chunk-PBF5EE4Y.js.map +0 -1
  39. package/dist/chunk-QEOOUDO3.js.map +0 -1
  40. package/dist/commands/capture.js.map +0 -1
  41. package/dist/commands/daily.js.map +0 -1
  42. package/dist/commands/delete.js.map +0 -1
  43. package/dist/commands/edit.js.map +0 -1
  44. package/dist/commands/export.js.map +0 -1
  45. package/dist/commands/hello.js.map +0 -1
  46. package/dist/commands/help.js.map +0 -1
  47. package/dist/commands/howto.js.map +0 -1
  48. package/dist/commands/import.js.map +0 -1
  49. package/dist/commands/interactive.js.map +0 -1
  50. package/dist/commands/login.js.map +0 -1
  51. package/dist/commands/logout.js.map +0 -1
  52. package/dist/commands/new.js.map +0 -1
  53. package/dist/commands/notes.js.map +0 -1
  54. package/dist/commands/restore.js.map +0 -1
  55. package/dist/commands/search.js.map +0 -1
  56. package/dist/commands/status.js.map +0 -1
  57. package/dist/commands/syntax.js.map +0 -1
  58. package/dist/commands/tags.js.map +0 -1
  59. package/dist/commands/today.js.map +0 -1
  60. package/dist/commands/trash/empty.js.map +0 -1
  61. package/dist/commands/trash/index.js.map +0 -1
  62. package/dist/commands/view.js.map +0 -1
  63. package/dist/commands/whoami.js.map +0 -1
  64. package/dist/index.js.map +0 -1
  65. package/dist/lib/client.js.map +0 -1
  66. package/dist/lib/config.js.map +0 -1
  67. package/dist/lib/file-cleanup.js.map +0 -1
  68. package/dist/lib/md-to-tiptap.js +0 -250
  69. package/dist/lib/md-to-tiptap.js.map +0 -1
package/package.json CHANGED
@@ -1,54 +1,56 @@
1
- {
2
- "name": "vertex-notes",
3
- "version": "0.3.1",
4
- "description": "Vertex — keyboard-first knowledge workspace CLI",
5
- "type": "module",
6
- "bin": {
7
- "vertex": "bin/run.js"
8
- },
9
- "main": "dist/index.js",
10
- "files": [
11
- "bin",
12
- "dist",
13
- "README.md"
14
- ],
15
- "keywords": [
16
- "vertex",
17
- "notes",
18
- "cli",
19
- "knowledge",
20
- "todo",
21
- "markdown",
22
- "productivity"
23
- ],
24
- "author": "Sahil Kumar Sinha",
25
- "license": "MIT",
26
- "repository": {
27
- "type": "git",
28
- "url": "git+https://github.com/sahilcodes2002/vertex.git"
29
- },
30
- "engines": {
31
- "node": ">=18"
32
- },
33
- "scripts": {
34
- "build": "tsup",
35
- "typecheck": "tsc --noEmit",
36
- "clean": "rm -rf dist",
37
- "prepublishOnly": "pnpm build"
38
- },
39
- "dependencies": {
40
- "@oclif/core": "^4.2.0",
41
- "@supabase/supabase-js": "^2.49.0"
42
- },
43
- "devDependencies": {
44
- "@vertex/core": "workspace:*",
45
- "tsup": "^8.4.0",
46
- "typescript": "^5.7.0",
47
- "oclif": "^4.17.0"
48
- },
49
- "oclif": {
50
- "bin": "vertex",
51
- "dirname": "vertex",
52
- "commands": "./dist/commands"
53
- }
54
- }
1
+ {
2
+ "name": "vertex-notes",
3
+ "version": "0.3.4",
4
+ "description": "Vertex — keyboard-first knowledge workspace CLI",
5
+ "type": "module",
6
+ "bin": {
7
+ "vertex": "bin/run.js"
8
+ },
9
+ "main": "dist/index.js",
10
+ "files": [
11
+ "bin",
12
+ "dist",
13
+ "README.md"
14
+ ],
15
+ "keywords": [
16
+ "vertex",
17
+ "notes",
18
+ "cli",
19
+ "knowledge",
20
+ "todo",
21
+ "markdown",
22
+ "productivity"
23
+ ],
24
+ "author": "Sahil Kumar Sinha",
25
+ "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/sahilcodes2002/vertex.git"
29
+ },
30
+ "engines": {
31
+ "node": ">=18"
32
+ },
33
+ "scripts": {
34
+ "build": "tsup",
35
+ "typecheck": "tsc --noEmit",
36
+ "clean": "rm -rf dist",
37
+ "prepublishOnly": "pnpm build"
38
+ },
39
+ "dependencies": {
40
+ "@oclif/core": "^4.11.0",
41
+ "@supabase/supabase-js": "^2.49.0",
42
+ "ws": "^8.18.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/ws": "^8.18.0",
46
+ "@vertex/core": "workspace:*",
47
+ "tsup": "^8.4.0",
48
+ "typescript": "^5.7.0",
49
+ "oclif": "^4.17.0"
50
+ },
51
+ "oclif": {
52
+ "bin": "vertex",
53
+ "dirname": "vertex",
54
+ "commands": "./dist/commands"
55
+ }
56
+ }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/client.ts"],"sourcesContent":["import { createSupabaseClient, type SupabaseClient } from \"@vertex/core\";\nimport { loadConfig, saveConfig } from \"./config.js\";\n\nlet cachedClient: SupabaseClient | null = null;\n\nexport async function getClient(): Promise<SupabaseClient> {\n if (cachedClient) return cachedClient;\n\n const config = loadConfig();\n if (!config.accessToken || !config.refreshToken) {\n throw new Error(\"Not logged in. Run: vertex login\");\n }\n\n const client = createSupabaseClient(config.supabaseUrl, config.supabaseAnonKey);\n\n const { data, error } = await client.auth.setSession({\n access_token: config.accessToken,\n refresh_token: config.refreshToken,\n });\n\n if (error) {\n throw new Error(`Session expired. Run: vertex login\\n${error.message}`);\n }\n\n if (data.session) {\n saveConfig({\n accessToken: data.session.access_token,\n refreshToken: data.session.refresh_token,\n userId: data.session.user.id,\n email: data.session.user.email,\n });\n }\n\n cachedClient = client;\n return client;\n}\n\nexport async function getUserId(): Promise<string> {\n const config = loadConfig();\n if (config.userId) return config.userId;\n const client = await getClient();\n const { data } = await client.auth.getUser();\n if (!data.user) throw new Error(\"Not logged in. Run: vertex login\");\n return data.user.id;\n}\n"],"mappings":";;;;;;;;;AAGA,IAAI,eAAsC;AAE1C,eAAsB,YAAqC;AACzD,MAAI,aAAc,QAAO;AAEzB,QAAM,SAAS,WAAW;AAC1B,MAAI,CAAC,OAAO,eAAe,CAAC,OAAO,cAAc;AAC/C,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AAEA,QAAM,SAAS,qBAAqB,OAAO,aAAa,OAAO,eAAe;AAE9E,QAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK,WAAW;AAAA,IACnD,cAAc,OAAO;AAAA,IACrB,eAAe,OAAO;AAAA,EACxB,CAAC;AAED,MAAI,OAAO;AACT,UAAM,IAAI,MAAM;AAAA,EAAuC,MAAM,OAAO,EAAE;AAAA,EACxE;AAEA,MAAI,KAAK,SAAS;AAChB,eAAW;AAAA,MACT,aAAa,KAAK,QAAQ;AAAA,MAC1B,cAAc,KAAK,QAAQ;AAAA,MAC3B,QAAQ,KAAK,QAAQ,KAAK;AAAA,MAC1B,OAAO,KAAK,QAAQ,KAAK;AAAA,IAC3B,CAAC;AAAA,EACH;AAEA,iBAAe;AACf,SAAO;AACT;AAEA,eAAsB,YAA6B;AACjD,QAAM,SAAS,WAAW;AAC1B,MAAI,OAAO,OAAQ,QAAO,OAAO;AACjC,QAAM,SAAS,MAAM,UAAU;AAC/B,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,KAAK,QAAQ;AAC3C,MAAI,CAAC,KAAK,KAAM,OAAM,IAAI,MAAM,kCAAkC;AAClE,SAAO,KAAK,KAAK;AACnB;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/file-cleanup.ts"],"sourcesContent":["import { loadConfig } from \"./config.js\";\n\nconst R2_WORKER_URL = \"https://vertex-r2.codessahil.workers.dev\";\n\nexport async function cleanupRemovedFiles(\n removedFiles: Array<{ src: string; filesize: number }>,\n): Promise<void> {\n const config = loadConfig();\n const token = config.accessToken;\n if (!token) return;\n\n for (const file of removedFiles) {\n try {\n const parsed = new URL(file.src);\n if (parsed.origin === new URL(R2_WORKER_URL).origin) {\n await fetch(file.src, {\n method: \"DELETE\",\n headers: { Authorization: `Bearer ${token}` },\n });\n }\n } catch {\n // best-effort\n }\n }\n}\n"],"mappings":";;;;;AAEA,IAAM,gBAAgB;AAEtB,eAAsB,oBACpB,cACe;AACf,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAO;AAEZ,aAAW,QAAQ,cAAc;AAC/B,QAAI;AACF,YAAM,SAAS,IAAI,IAAI,KAAK,GAAG;AAC/B,UAAI,OAAO,WAAW,IAAI,IAAI,aAAa,EAAE,QAAQ;AACnD,cAAM,MAAM,KAAK,KAAK;AAAA,UACpB,QAAQ;AAAA,UACR,SAAS,EAAE,eAAe,UAAU,KAAK,GAAG;AAAA,QAC9C,CAAC;AAAA,MACH;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/config.ts"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nconst CONFIG_DIR = join(homedir(), \".vertex\");\nconst CONFIG_FILE = join(CONFIG_DIR, \"config.json\");\n\nexport interface VertexConfig {\n supabaseUrl: string;\n supabaseAnonKey: string;\n accessToken?: string;\n refreshToken?: string;\n userId?: string;\n email?: string;\n}\n\nconst DEFAULTS: Pick<VertexConfig, \"supabaseUrl\" | \"supabaseAnonKey\"> = {\n supabaseUrl: \"https://cywzmrkevzpjswplzfkc.supabase.co\",\n supabaseAnonKey: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImN5d3ptcmtldnpwanN3cGx6ZmtjIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzUyNTg0MzcsImV4cCI6MjA5MDgzNDQzN30.hKmzSHKuxvzJnhJCjctYCwvWXXdmpCukrNObasHCJG4\",\n};\n\nexport function loadConfig(): VertexConfig {\n if (!existsSync(CONFIG_FILE)) return { ...DEFAULTS };\n try {\n const raw = readFileSync(CONFIG_FILE, \"utf-8\");\n return { ...DEFAULTS, ...JSON.parse(raw) };\n } catch {\n return { ...DEFAULTS };\n }\n}\n\nexport function saveConfig(config: Partial<VertexConfig>): void {\n mkdirSync(CONFIG_DIR, { recursive: true });\n const existing = loadConfig();\n const merged = { ...existing, ...config };\n writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2), \"utf-8\");\n}\n\nexport function clearConfig(): void {\n if (existsSync(CONFIG_FILE)) {\n writeFileSync(CONFIG_FILE, JSON.stringify(DEFAULTS, null, 2), \"utf-8\");\n }\n}\n\nexport function isLoggedIn(): boolean {\n const config = loadConfig();\n return !!(config.accessToken && config.refreshToken);\n}\n"],"mappings":";AAAA,SAAS,cAAc,eAAe,WAAW,kBAAkB;AACnE,SAAS,eAAe;AACxB,SAAS,YAAY;AAErB,IAAM,aAAa,KAAK,QAAQ,GAAG,SAAS;AAC5C,IAAM,cAAc,KAAK,YAAY,aAAa;AAWlD,IAAM,WAAkE;AAAA,EACtE,aAAa;AAAA,EACb,iBAAiB;AACnB;AAEO,SAAS,aAA2B;AACzC,MAAI,CAAC,WAAW,WAAW,EAAG,QAAO,EAAE,GAAG,SAAS;AACnD,MAAI;AACF,UAAM,MAAM,aAAa,aAAa,OAAO;AAC7C,WAAO,EAAE,GAAG,UAAU,GAAG,KAAK,MAAM,GAAG,EAAE;AAAA,EAC3C,QAAQ;AACN,WAAO,EAAE,GAAG,SAAS;AAAA,EACvB;AACF;AAEO,SAAS,WAAW,QAAqC;AAC9D,YAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,QAAM,WAAW,WAAW;AAC5B,QAAM,SAAS,EAAE,GAAG,UAAU,GAAG,OAAO;AACxC,gBAAc,aAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,GAAG,OAAO;AACrE;AAEO,SAAS,cAAoB;AAClC,MAAI,WAAW,WAAW,GAAG;AAC3B,kBAAc,aAAa,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,OAAO;AAAA,EACvE;AACF;AAEO,SAAS,aAAsB;AACpC,QAAM,SAAS,WAAW;AAC1B,SAAO,CAAC,EAAE,OAAO,eAAe,OAAO;AACzC;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../core/src/client.ts","../../core/src/auth.ts","../../core/src/storage.ts","../../core/src/notes.ts","../../core/src/tags.ts","../../core/src/links.ts","../../core/src/blocks.ts","../../core/src/snapshots.ts","../../core/src/search.ts","../../core/src/graph.ts","../../core/src/templates.ts","../../core/src/export.ts","../../core/src/md-to-tiptap.ts","../../core/src/index.ts"],"sourcesContent":["import { createClient, type SupabaseClient } from \"@supabase/supabase-js\";\n\nexport type { SupabaseClient };\n\nlet defaultClient: SupabaseClient | null = null;\n\nexport function createSupabaseClient(\n url: string,\n anonKey: string,\n): SupabaseClient {\n return createClient(url, anonKey, {\n auth: {\n autoRefreshToken: true,\n persistSession: true,\n },\n });\n}\n\nexport function initSupabaseClient(url: string, anonKey: string): void {\n defaultClient = createSupabaseClient(url, anonKey);\n}\n\nexport function getSupabaseClient(): SupabaseClient {\n if (!defaultClient) {\n throw new Error(\n \"Supabase client not initialized. Call initSupabaseClient() first.\",\n );\n }\n return defaultClient;\n}\n","import type { SupabaseClient, User, Session } from \"@supabase/supabase-js\";\nimport type { Profile } from \"./types\";\n\nexport type { User, Session };\n\nexport type OAuthProvider = \"google\" | \"github\";\n\nexport async function signInWithOAuth(\n client: SupabaseClient,\n provider: OAuthProvider,\n redirectTo?: string,\n) {\n return client.auth.signInWithOAuth({\n provider,\n options: { redirectTo },\n });\n}\n\nexport async function signInWithEmail(\n client: SupabaseClient,\n email: string,\n password: string,\n) {\n return client.auth.signInWithPassword({ email, password });\n}\n\nexport async function signUpWithEmail(\n client: SupabaseClient,\n email: string,\n password: string,\n) {\n return client.auth.signUp({ email, password });\n}\n\nexport async function signOut(client: SupabaseClient) {\n return client.auth.signOut();\n}\n\nexport async function getUser(client: SupabaseClient) {\n return client.auth.getUser();\n}\n\nexport async function getSession(client: SupabaseClient) {\n return client.auth.getSession();\n}\n\nexport async function getProfile(\n client: SupabaseClient,\n userId: string,\n): Promise<Profile | null> {\n const { data, error } = await client\n .from(\"profiles\")\n .select(\"*\")\n .eq(\"id\", userId)\n .maybeSingle();\n\n if (error) return null;\n return data as Profile;\n}\n\nexport function onAuthStateChange(\n client: SupabaseClient,\n callback: (event: string, session: unknown) => void,\n) {\n return client.auth.onAuthStateChange(callback);\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\n\nexport const DEFAULT_STORAGE_CAP = 50 * 1024 * 1024;\n\nexport async function getStorageInfo(\n client: SupabaseClient,\n userId: string,\n): Promise<{ used: number; cap: number }> {\n const { data, error } = await client\n .from(\"profiles\")\n .select(\"storage_used, storage_cap\")\n .eq(\"id\", userId)\n .maybeSingle();\n if (error || !data) return { used: 0, cap: DEFAULT_STORAGE_CAP };\n return {\n used: (data.storage_used as number) ?? 0,\n cap: (data.storage_cap as number) ?? DEFAULT_STORAGE_CAP,\n };\n}\n\nexport async function getStorageUsed(\n client: SupabaseClient,\n userId: string,\n): Promise<number> {\n const { used } = await getStorageInfo(client, userId);\n return used;\n}\n\nexport async function getStorageCap(\n client: SupabaseClient,\n userId: string,\n): Promise<number> {\n const { cap } = await getStorageInfo(client, userId);\n return cap;\n}\n\nexport async function checkStorageCap(\n client: SupabaseClient,\n userId: string,\n fileSize: number,\n): Promise<{ allowed: boolean; used: number; cap: number }> {\n const { used, cap } = await getStorageInfo(client, userId);\n return { allowed: used + fileSize <= cap, used, cap };\n}\n\nexport async function incrementStorageUsed(\n client: SupabaseClient,\n userId: string,\n bytes: number,\n): Promise<void> {\n const used = await getStorageUsed(client, userId);\n await client\n .from(\"profiles\")\n .update({ storage_used: used + bytes })\n .eq(\"id\", userId);\n}\n\nexport async function decrementStorageUsed(\n client: SupabaseClient,\n userId: string,\n bytes: number,\n): Promise<void> {\n const used = await getStorageUsed(client, userId);\n await client\n .from(\"profiles\")\n .update({ storage_used: Math.max(0, used - bytes) })\n .eq(\"id\", userId);\n}\n\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return \"0 B\";\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Note, NoteType } from \"./types\";\nimport { decrementStorageUsed } from \"./storage\";\n\nexport type FileCleanupFn = (urls: Array<{ src: string; filesize: number }>) => Promise<void>;\n\nexport interface CreateNoteParams {\n user_id: string;\n title?: string;\n slug?: string;\n note_type?: NoteType;\n daily_date?: string;\n}\n\nasync function uniqueTitle(\n client: SupabaseClient,\n userId: string,\n title: string,\n excludeNoteId?: string,\n): Promise<string> {\n const { data } = await client\n .from(\"notes\")\n .select(\"title\")\n .eq(\"user_id\", userId)\n .is(\"deleted_at\", null);\n\n const existing = new Set(\n ((data ?? []) as Array<{ title: string }>)\n .filter(() => true)\n .map((n) => n.title),\n );\n\n if (excludeNoteId) {\n const { data: self } = await client\n .from(\"notes\")\n .select(\"title\")\n .eq(\"id\", excludeNoteId)\n .single();\n if (self) existing.delete((self as { title: string }).title);\n }\n\n if (!existing.has(title)) return title;\n\n let counter = 1;\n while (existing.has(`${title}(${counter})`)) counter++;\n return `${title}(${counter})`;\n}\n\nexport async function createNote(\n client: SupabaseClient,\n params: CreateNoteParams,\n): Promise<Note> {\n const title = await uniqueTitle(client, params.user_id, params.title ?? \"Untitled\");\n const { data, error } = await client\n .from(\"notes\")\n .insert({\n user_id: params.user_id,\n title,\n slug: params.slug ?? null,\n note_type: params.note_type ?? \"regular\",\n daily_date: params.daily_date ?? null,\n })\n .select()\n .single();\n\n if (error) throw error;\n return data as Note;\n}\n\nexport async function getNote(\n client: SupabaseClient,\n noteId: string,\n): Promise<Note | null> {\n const { data, error } = await client\n .from(\"notes\")\n .select(\"*\")\n .eq(\"id\", noteId)\n .is(\"deleted_at\", null)\n .single();\n\n if (error) return null;\n return data as Note;\n}\n\nexport async function updateNote(\n client: SupabaseClient,\n noteId: string,\n updates: Partial<Pick<Note, \"title\" | \"slug\" | \"is_pinned\">>,\n userId?: string,\n): Promise<Note> {\n const payload = { ...updates };\n if (payload.title && userId) {\n payload.title = await uniqueTitle(client, userId, payload.title, noteId);\n }\n const { data, error } = await client\n .from(\"notes\")\n .update(payload)\n .eq(\"id\", noteId)\n .select()\n .single();\n\n if (error) throw error;\n return data as Note;\n}\n\nexport async function softDeleteNote(\n client: SupabaseClient,\n noteId: string,\n): Promise<void> {\n const { error } = await client\n .from(\"notes\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", noteId);\n\n if (error) throw error;\n}\n\nexport async function restoreNote(\n client: SupabaseClient,\n noteId: string,\n): Promise<void> {\n const { error } = await client\n .from(\"notes\")\n .update({ deleted_at: null })\n .eq(\"id\", noteId);\n\n if (error) throw error;\n}\n\nexport async function hardDeleteNote(\n client: SupabaseClient,\n noteId: string,\n onFilesRemoved?: FileCleanupFn,\n): Promise<void> {\n const { data: blocks } = await client\n .from(\"blocks\")\n .select(\"type, metadata, user_id\")\n .eq(\"note_id\", noteId);\n\n const fileUrls: Array<{ src: string; filesize: number }> = [];\n let userId: string | null = null;\n\n for (const b of (blocks ?? []) as Array<{ type: string; metadata: Record<string, unknown>; user_id: string }>) {\n if (!userId) userId = b.user_id;\n const tiptap = b.metadata?.tiptap as Record<string, unknown> | undefined;\n const attrs = (tiptap?.attrs ?? {}) as Record<string, unknown>;\n const src = attrs.src as string | undefined;\n if (src && (b.type === \"file\" || b.type === \"image\") && !src.startsWith(\"data:\")) {\n fileUrls.push({ src, filesize: (attrs.filesize as number) ?? 0 });\n }\n }\n\n for (const file of fileUrls) {\n try {\n const parsed = new URL(file.src);\n if (parsed.pathname.includes(\"/storage/v1/object/public/\")) {\n const pathParts = parsed.pathname.split(\"/storage/v1/object/public/\");\n if (pathParts.length >= 2) {\n const fullPath = decodeURIComponent(pathParts[1]);\n const slashIdx = fullPath.indexOf(\"/\");\n if (slashIdx !== -1) {\n await client.storage.from(fullPath.substring(0, slashIdx)).remove([fullPath.substring(slashIdx + 1)]);\n }\n }\n }\n if (userId && file.filesize > 0) {\n await decrementStorageUsed(client, userId, file.filesize).catch(() => {});\n }\n } catch {\n // best-effort\n }\n }\n\n if (fileUrls.length > 0 && onFilesRemoved) {\n await onFilesRemoved(fileUrls).catch(() => {});\n }\n\n const { error } = await client\n .from(\"notes\")\n .delete()\n .eq(\"id\", noteId);\n\n if (error) throw error;\n\n if (userId) {\n await cleanupOrphanedTags(client, userId);\n }\n}\n\nasync function cleanupOrphanedTags(client: SupabaseClient, userId: string): Promise<void> {\n try {\n const { data: tags } = await client\n .from(\"tags\")\n .select(\"id\")\n .eq(\"user_id\", userId);\n\n if (!tags || tags.length === 0) return;\n\n for (const tag of tags) {\n const { count: blockCount } = await client\n .from(\"block_tags\")\n .select(\"*\", { count: \"exact\", head: true })\n .eq(\"tag_id\", tag.id);\n\n const { count: noteCount } = await client\n .from(\"note_tags\")\n .select(\"*\", { count: \"exact\", head: true })\n .eq(\"tag_id\", tag.id);\n\n if ((blockCount ?? 0) === 0 && (noteCount ?? 0) === 0) {\n await client.from(\"tag_edges\").delete().or(`parent_id.eq.${tag.id},child_id.eq.${tag.id}`);\n await client.from(\"tags\").delete().eq(\"id\", tag.id);\n }\n }\n } catch {\n // best-effort\n }\n}\n\nexport async function emptyTrash(\n client: SupabaseClient,\n userId: string,\n onFilesRemoved?: FileCleanupFn,\n): Promise<number> {\n const { data } = await client\n .from(\"notes\")\n .select(\"id\")\n .eq(\"user_id\", userId)\n .not(\"deleted_at\", \"is\", null);\n\n if (!data || data.length === 0) return 0;\n\n const ids = (data as Array<{ id: string }>).map((n) => n.id);\n for (const id of ids) {\n await hardDeleteNote(client, id, onFilesRemoved);\n }\n return ids.length;\n}\n\nexport interface ListNotesParams {\n user_id: string;\n note_type?: NoteType;\n is_pinned?: boolean;\n include_deleted?: boolean;\n limit?: number;\n offset?: number;\n}\n\nexport async function listNotes(\n client: SupabaseClient,\n params: ListNotesParams,\n): Promise<Note[]> {\n let query = client\n .from(\"notes\")\n .select(\"*\")\n .eq(\"user_id\", params.user_id)\n .order(\"updated_at\", { ascending: false });\n\n if (!params.include_deleted) {\n query = query.is(\"deleted_at\", null);\n }\n if (params.note_type) {\n query = query.eq(\"note_type\", params.note_type);\n }\n if (params.is_pinned !== undefined) {\n query = query.eq(\"is_pinned\", params.is_pinned);\n }\n if (params.limit) {\n query = query.limit(params.limit);\n }\n if (params.offset) {\n query = query.range(params.offset, params.offset + (params.limit ?? 50) - 1);\n }\n\n const { data, error } = await query;\n if (error) throw error;\n return (data ?? []) as Note[];\n}\n\nexport async function getOrCreateDailyNote(\n client: SupabaseClient,\n userId: string,\n date: string,\n): Promise<Note> {\n const { data: existing } = await client\n .from(\"notes\")\n .select(\"*\")\n .eq(\"user_id\", userId)\n .eq(\"note_type\", \"daily\")\n .eq(\"daily_date\", date)\n .single();\n\n if (existing) return existing as Note;\n\n const dateObj = new Date(date + \"T00:00:00\");\n const title = dateObj.toLocaleDateString(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n\n return createNote(client, {\n user_id: userId,\n title,\n slug: date,\n note_type: \"daily\",\n daily_date: date,\n });\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Tag, TagEdge } from \"./types\";\n\nexport async function createTag(\n client: SupabaseClient,\n userId: string,\n name: string,\n color?: string,\n): Promise<Tag> {\n const { data, error } = await client\n .from(\"tags\")\n .insert({ user_id: userId, name: name.toLowerCase(), color: color ?? null })\n .select()\n .single();\n\n if (error) throw error;\n return data as Tag;\n}\n\nexport async function getOrCreateTag(\n client: SupabaseClient,\n userId: string,\n name: string,\n color?: string,\n): Promise<Tag> {\n const normalized = name.toLowerCase();\n const { data: existing } = await client\n .from(\"tags\")\n .select(\"*\")\n .eq(\"user_id\", userId)\n .eq(\"name\", normalized)\n .single();\n\n if (existing) return existing as Tag;\n return createTag(client, userId, normalized, color);\n}\n\nexport async function getUserTags(\n client: SupabaseClient,\n userId: string,\n): Promise<Tag[]> {\n const { data, error } = await client\n .from(\"tags\")\n .select(\"*\")\n .eq(\"user_id\", userId)\n .order(\"name\");\n\n if (error) throw error;\n return (data ?? []) as Tag[];\n}\n\nexport async function updateTag(\n client: SupabaseClient,\n tagId: string,\n updates: Partial<Pick<Tag, \"name\" | \"color\">>,\n): Promise<Tag> {\n const payload: Record<string, unknown> = {};\n if (updates.name !== undefined) payload.name = updates.name.toLowerCase();\n if (updates.color !== undefined) payload.color = updates.color;\n\n const { data, error } = await client\n .from(\"tags\")\n .update(payload)\n .eq(\"id\", tagId)\n .select()\n .single();\n\n if (error) throw error;\n return data as Tag;\n}\n\nexport async function deleteTag(\n client: SupabaseClient,\n tagId: string,\n): Promise<void> {\n const { error } = await client.from(\"tags\").delete().eq(\"id\", tagId);\n if (error) throw error;\n}\n\nexport async function addTagEdge(\n client: SupabaseClient,\n userId: string,\n parentId: string,\n childId: string,\n): Promise<TagEdge> {\n const { data, error } = await client\n .from(\"tag_edges\")\n .insert({ parent_id: parentId, child_id: childId, user_id: userId })\n .select()\n .single();\n\n if (error) throw error;\n return data as TagEdge;\n}\n\nexport async function removeTagEdge(\n client: SupabaseClient,\n parentId: string,\n childId: string,\n): Promise<void> {\n const { error } = await client\n .from(\"tag_edges\")\n .delete()\n .eq(\"parent_id\", parentId)\n .eq(\"child_id\", childId);\n\n if (error) throw error;\n}\n\nexport async function getTagParents(\n client: SupabaseClient,\n tagId: string,\n): Promise<Tag[]> {\n const { data, error } = await client\n .from(\"tag_edges\")\n .select(\"parent_id\")\n .eq(\"child_id\", tagId);\n\n if (error) throw error;\n if (!data || data.length === 0) return [];\n\n const parentIds = data.map((e) => (e as TagEdge).parent_id);\n const { data: tags, error: tagErr } = await client\n .from(\"tags\")\n .select(\"*\")\n .in(\"id\", parentIds);\n\n if (tagErr) throw tagErr;\n return (tags ?? []) as Tag[];\n}\n\nexport async function getTagChildren(\n client: SupabaseClient,\n tagId: string,\n): Promise<Tag[]> {\n const { data, error } = await client\n .from(\"tag_edges\")\n .select(\"child_id\")\n .eq(\"parent_id\", tagId);\n\n if (error) throw error;\n if (!data || data.length === 0) return [];\n\n const childIds = data.map((e) => (e as TagEdge).child_id);\n const { data: tags, error: tagErr } = await client\n .from(\"tags\")\n .select(\"*\")\n .in(\"id\", childIds);\n\n if (tagErr) throw tagErr;\n return (tags ?? []) as Tag[];\n}\n\nexport async function getTagDescendants(\n client: SupabaseClient,\n tagId: string,\n): Promise<string[]> {\n const { data, error } = await client.rpc(\"get_tag_descendants\", {\n root_tag_id: tagId,\n });\n\n if (error) throw error;\n return ((data ?? []) as Array<{ tag_id: string }>).map((r) => r.tag_id);\n}\n\nexport async function addBlockTag(\n client: SupabaseClient,\n blockId: string,\n tagId: string,\n): Promise<void> {\n const { error } = await client\n .from(\"block_tags\")\n .upsert({ block_id: blockId, tag_id: tagId }, { onConflict: \"block_id,tag_id\" });\n\n if (error) throw error;\n}\n\nexport async function removeBlockTag(\n client: SupabaseClient,\n blockId: string,\n tagId: string,\n): Promise<void> {\n const { error } = await client\n .from(\"block_tags\")\n .delete()\n .eq(\"block_id\", blockId)\n .eq(\"tag_id\", tagId);\n\n if (error) throw error;\n}\n\nexport async function getBlocksByTag(\n client: SupabaseClient,\n userId: string,\n tagId: string,\n includeDescendants = true,\n): Promise<string[]> {\n let tagIds: string[];\n if (includeDescendants) {\n tagIds = await getTagDescendants(client, tagId);\n } else {\n tagIds = [tagId];\n }\n\n const { data, error } = await client\n .from(\"block_tags\")\n .select(\"block_id, blocks!inner(user_id)\")\n .in(\"tag_id\", tagIds);\n\n if (error) throw error;\n return ((data ?? []) as Array<{ block_id: string }>).map((r) => r.block_id);\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Link, LinkTargetType, BacklinkResult, Block } from \"./types\";\n\nexport async function createLink(\n client: SupabaseClient,\n userId: string,\n sourceBlockId: string,\n targetType: LinkTargetType,\n targetId: string,\n): Promise<Link> {\n const { data, error } = await client\n .from(\"links\")\n .insert({\n user_id: userId,\n source_block_id: sourceBlockId,\n target_type: targetType,\n target_id: targetId,\n })\n .select()\n .single();\n\n if (error) throw error;\n return data as Link;\n}\n\nexport async function deleteLinksForBlock(\n client: SupabaseClient,\n sourceBlockId: string,\n): Promise<void> {\n const { error } = await client\n .from(\"links\")\n .delete()\n .eq(\"source_block_id\", sourceBlockId);\n\n if (error) throw error;\n}\n\nexport async function getBacklinksForNote(\n client: SupabaseClient,\n noteId: string,\n): Promise<BacklinkResult[]> {\n const { data, error } = await client\n .from(\"links\")\n .select(\"source_block_id, blocks!inner(id, note_id, content, type, position, metadata, user_id, created_at, updated_at, deleted_at)\")\n .eq(\"target_type\", \"note\")\n .eq(\"target_id\", noteId);\n\n if (error) throw error;\n if (!data || data.length === 0) return [];\n\n const blockRows = data as unknown as Array<{ source_block_id: string; blocks: Record<string, unknown> }>;\n const noteIds = [...new Set(blockRows.map((r) => r.blocks.note_id as string))];\n\n const { data: notes } = await client\n .from(\"notes\")\n .select(\"id, title\")\n .in(\"id\", noteIds);\n\n const noteMap = new Map((notes ?? []).map((n: Record<string, unknown>) => [n.id as string, n.title as string]));\n\n return blockRows.map((r) => ({\n source_block: r.blocks as unknown as Block,\n source_note_title: noteMap.get(r.blocks.note_id as string) ?? \"Untitled\",\n }));\n}\n\nexport async function syncLinksForNote(\n client: SupabaseClient,\n userId: string,\n noteId: string,\n wikiLinks: Array<{ blockId?: string; targetNoteTitle: string }>,\n): Promise<void> {\n const { data: existingBlocks } = await client\n .from(\"blocks\")\n .select(\"id\")\n .eq(\"note_id\", noteId);\n\n if (existingBlocks) {\n const blockIds = existingBlocks.map((b: Record<string, unknown>) => b.id as string);\n if (blockIds.length > 0) {\n await client\n .from(\"links\")\n .delete()\n .in(\"source_block_id\", blockIds);\n }\n }\n\n if (wikiLinks.length === 0) return;\n\n const titles = [...new Set(wikiLinks.map((l) => l.targetNoteTitle))];\n const { data: targetNotes } = await client\n .from(\"notes\")\n .select(\"id, title\")\n .eq(\"user_id\", userId)\n .in(\"title\", titles);\n\n if (!targetNotes || targetNotes.length === 0) return;\n\n const titleToId = new Map(\n (targetNotes as Array<{ id: string; title: string }>).map((n) => [n.title, n.id]),\n );\n\n const newBlocks = await client\n .from(\"blocks\")\n .select(\"id\")\n .eq(\"note_id\", noteId)\n .order(\"position\");\n\n if (!newBlocks.data) return;\n const firstBlockId = (newBlocks.data[0] as Record<string, unknown>)?.id as string | undefined;\n\n const linksToInsert = wikiLinks\n .map((l) => {\n const targetId = titleToId.get(l.targetNoteTitle);\n if (!targetId) return null;\n return {\n user_id: userId,\n source_block_id: l.blockId ?? firstBlockId,\n target_type: \"note\" as LinkTargetType,\n target_id: targetId,\n };\n })\n .filter((l): l is NonNullable<typeof l> => l !== null && l.source_block_id !== undefined);\n\n if (linksToInsert.length > 0) {\n await client.from(\"links\").insert(linksToInsert);\n }\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Block, BlockType, BlockMetadata } from \"./types\";\nimport { getOrCreateTag, addTagEdge, addBlockTag } from \"./tags\";\nimport { syncLinksForNote } from \"./links\";\n\nexport interface CreateBlockParams {\n note_id: string;\n user_id: string;\n type?: BlockType;\n content?: string;\n position: number;\n metadata?: BlockMetadata;\n}\n\nexport async function createBlock(\n client: SupabaseClient,\n params: CreateBlockParams,\n): Promise<Block> {\n const { data, error } = await client\n .from(\"blocks\")\n .insert({\n note_id: params.note_id,\n user_id: params.user_id,\n type: params.type ?? \"text\",\n content: params.content ?? \"\",\n position: params.position,\n metadata: params.metadata ?? {},\n })\n .select()\n .single();\n\n if (error) throw error;\n return data as Block;\n}\n\nexport async function getBlocksForNote(\n client: SupabaseClient,\n noteId: string,\n): Promise<Block[]> {\n const { data, error } = await client\n .from(\"blocks\")\n .select(\"*\")\n .eq(\"note_id\", noteId)\n .is(\"deleted_at\", null)\n .order(\"position\", { ascending: true });\n\n if (error) throw error;\n return (data ?? []) as Block[];\n}\n\nexport async function updateBlock(\n client: SupabaseClient,\n blockId: string,\n updates: Partial<Pick<Block, \"content\" | \"type\" | \"position\" | \"metadata\">>,\n): Promise<Block> {\n const { data, error } = await client\n .from(\"blocks\")\n .update(updates)\n .eq(\"id\", blockId)\n .select()\n .single();\n\n if (error) throw error;\n return data as Block;\n}\n\nexport async function deleteBlock(\n client: SupabaseClient,\n blockId: string,\n): Promise<void> {\n const { error } = await client\n .from(\"blocks\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", blockId);\n\n if (error) throw error;\n}\n\nexport async function upsertBlocks(\n client: SupabaseClient,\n blocks: Array<{\n id?: string;\n note_id: string;\n user_id: string;\n type: BlockType;\n content: string;\n position: number;\n metadata: BlockMetadata;\n }>,\n): Promise<Block[]> {\n const { data, error } = await client\n .from(\"blocks\")\n .upsert(blocks, { onConflict: \"id\" })\n .select();\n\n if (error) throw error;\n return (data ?? []) as Block[];\n}\n\nconst saveLocks = new Map<string, Promise<void>>();\n\nexport async function saveNoteContent(\n client: SupabaseClient,\n noteId: string,\n userId: string,\n tiptapJson: Record<string, unknown>,\n): Promise<void> {\n const existing = saveLocks.get(noteId);\n const doSave = async () => {\n if (existing) await existing.catch(() => {});\n await _saveNoteContentInner(client, noteId, userId, tiptapJson);\n };\n const promise = doSave();\n saveLocks.set(noteId, promise);\n try {\n await promise;\n } finally {\n if (saveLocks.get(noteId) === promise) saveLocks.delete(noteId);\n }\n}\n\nasync function _saveNoteContentInner(\n client: SupabaseClient,\n noteId: string,\n userId: string,\n tiptapJson: Record<string, unknown>,\n): Promise<void> {\n const nodes = tiptapJson.content as Array<Record<string, unknown>> | undefined;\n if (!nodes) return;\n\n const blocksToInsert = nodes.map((node, index) => ({\n note_id: noteId,\n user_id: userId,\n type: mapTiptapTypeToBlockType(node.type as string),\n content: extractPlainText(node),\n position: (index + 1) * 1.0,\n metadata: { tiptap: node },\n }));\n\n if (blocksToInsert.length === 0) return;\n\n const { error } = await client\n .from(\"blocks\")\n .delete()\n .eq(\"note_id\", noteId);\n\n if (error) throw error;\n\n const { error: insertError } = await client\n .from(\"blocks\")\n .insert(blocksToInsert);\n\n if (insertError) throw insertError;\n\n const { data: insertedBlocks } = await client\n .from(\"blocks\")\n .select(\"id, content, type\")\n .eq(\"note_id\", noteId)\n .order(\"position\");\n\n const blockRows = (insertedBlocks ?? []) as Array<{ id: string; content: string; type: string }>;\n\n await client.from(\"block_tags\").delete().in(\"block_id\", blockRows.map((b) => b.id));\n await client.from(\"note_tags\").delete().eq(\"note_id\", noteId);\n\n const noteTagIds = new Set<string>();\n\n const SKIP_TAG_TYPES = new Set([\"code\", \"mermaid\", \"math\", \"image\", \"divider\", \"chart\", \"file\"]);\n\n for (const block of blockRows) {\n if (SKIP_TAG_TYPES.has(block.type)) continue;\n\n const leafTags = extractLeafTags(block.content);\n for (const tagName of leafTags) {\n const tag = await getOrCreateTag(client, userId, tagName);\n await addBlockTag(client, block.id, tag.id).catch(() => {});\n noteTagIds.add(tag.id);\n }\n\n const scopedTags = extractScopedTags(block.content);\n for (const { parent, child } of scopedTags) {\n const parentTag = await getOrCreateTag(client, userId, parent);\n const childTag = await getOrCreateTag(client, userId, child);\n await addTagEdge(client, userId, parentTag.id, childTag.id).catch(() => {});\n }\n }\n\n for (const tagId of noteTagIds) {\n await client\n .from(\"note_tags\")\n .upsert({ note_id: noteId, tag_id: tagId }, { onConflict: \"note_id,tag_id\" });\n }\n\n const fullText = blockRows.map((b) => b.content).join(\" \");\n\n const wikiLinkTitles = extractWikiLinks(fullText);\n if (wikiLinkTitles.length > 0) {\n await syncLinksForNote(client, userId, noteId, wikiLinkTitles.map((t) => ({ targetNoteTitle: t })));\n }\n}\n\nfunction mapTiptapTypeToBlockType(tiptapType: string): BlockType {\n const MAP: Record<string, BlockType> = {\n paragraph: \"text\",\n heading: \"heading\",\n codeBlock: \"code\",\n taskList: \"todo\",\n taskItem: \"todo\",\n blockquote: \"text\",\n bulletList: \"text\",\n orderedList: \"text\",\n image: \"image\",\n mermaidBlock: \"mermaid\",\n mathBlock: \"math\",\n calloutBlock: \"callout\",\n queryBlock: \"query\",\n horizontalRule: \"divider\",\n fileBlock: \"file\",\n linkPreview: \"text\",\n inlineMath: \"text\",\n };\n return MAP[tiptapType] ?? \"text\";\n}\n\nfunction extractPlainText(node: Record<string, unknown>): string {\n if (typeof node.text === \"string\") return node.text;\n const content = node.content as Array<Record<string, unknown>> | undefined;\n if (!content) return \"\";\n return content.map(extractPlainText).join(\"\");\n}\n\nfunction extractLeafTags(text: string): string[] {\n const matches = text.match(/#([a-zA-Z][a-zA-Z0-9_-]*(?:\\/[a-zA-Z][a-zA-Z0-9_-]*)*)/g);\n if (!matches) return [];\n const tags = new Set<string>();\n for (const m of matches) {\n const full = m.slice(1).toLowerCase();\n if (full.includes(\"/\")) {\n const parts = full.split(\"/\");\n tags.add(parts[parts.length - 1]);\n } else {\n tags.add(full);\n }\n }\n return [...tags];\n}\n\nfunction extractScopedTags(text: string): Array<{ parent: string; child: string }> {\n const matches = text.match(/#([a-zA-Z][a-zA-Z0-9_-]*(?:\\/[a-zA-Z][a-zA-Z0-9_-]*)+)/g);\n if (!matches) return [];\n const edges: Array<{ parent: string; child: string }> = [];\n for (const m of matches) {\n const parts = m.slice(1).toLowerCase().split(\"/\");\n for (let i = 0; i < parts.length - 1; i++) {\n edges.push({ parent: parts[i], child: parts[i + 1] });\n }\n }\n return edges;\n}\n\nfunction extractWikiLinks(text: string): string[] {\n const matches = text.match(/\\[\\[([^\\]]+)\\]\\]/g);\n if (!matches) return [];\n return [...new Set(matches.map((m) => m.slice(2, -2)))];\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Snapshot } from \"./types\";\n\nfunction generateHash(): string {\n const chars = \"0123456789abcdef\";\n let hash = \"\";\n for (let i = 0; i < 8; i++) {\n hash += chars[Math.floor(Math.random() * chars.length)];\n }\n return hash;\n}\n\nexport async function createSnapshot(\n client: SupabaseClient,\n noteId: string,\n userId: string,\n content: Record<string, unknown>,\n message?: string,\n): Promise<Snapshot | null> {\n const latest = await getLatestSnapshot(client, noteId);\n if (latest && JSON.stringify(latest.content) === JSON.stringify(content)) {\n return null;\n }\n\n const { data, error } = await client\n .from(\"snapshots\")\n .insert({\n note_id: noteId,\n user_id: userId,\n content,\n hash: generateHash(),\n message: message ?? null,\n })\n .select()\n .single();\n\n if (error) throw error;\n return data as Snapshot;\n}\n\nexport async function listSnapshots(\n client: SupabaseClient,\n noteId: string,\n limit = 50,\n): Promise<Snapshot[]> {\n const { data, error } = await client\n .from(\"snapshots\")\n .select(\"*\")\n .eq(\"note_id\", noteId)\n .order(\"created_at\", { ascending: false })\n .limit(limit);\n\n if (error) throw error;\n return (data ?? []) as Snapshot[];\n}\n\nexport async function getSnapshot(\n client: SupabaseClient,\n snapshotId: string,\n): Promise<Snapshot | null> {\n const { data, error } = await client\n .from(\"snapshots\")\n .select(\"*\")\n .eq(\"id\", snapshotId)\n .single();\n\n if (error) return null;\n return data as Snapshot;\n}\n\nexport async function getLatestSnapshot(\n client: SupabaseClient,\n noteId: string,\n): Promise<Snapshot | null> {\n const { data, error } = await client\n .from(\"snapshots\")\n .select(\"*\")\n .eq(\"note_id\", noteId)\n .order(\"created_at\", { ascending: false })\n .limit(1)\n .single();\n\n if (error) return null;\n return data as Snapshot;\n}\n\nexport interface DiffResult {\n added: string[];\n removed: string[];\n unchanged: string[];\n}\n\nexport function diffSnapshots(\n older: Record<string, unknown>,\n newer: Record<string, unknown>,\n): DiffResult {\n const olderBlocks = extractBlockTexts(older);\n const newerBlocks = extractBlockTexts(newer);\n\n const olderSet = new Set(olderBlocks);\n const newerSet = new Set(newerBlocks);\n\n const added = newerBlocks.filter((b) => !olderSet.has(b));\n const removed = olderBlocks.filter((b) => !newerSet.has(b));\n const unchanged = newerBlocks.filter((b) => olderSet.has(b));\n\n return { added, removed, unchanged };\n}\n\nfunction extractBlockTexts(tiptapJson: Record<string, unknown>): string[] {\n const content = tiptapJson.content as Array<Record<string, unknown>> | undefined;\n if (!content) return [];\n return content.map((node) => {\n return extractText(node).trim();\n }).filter(Boolean);\n}\n\nfunction extractText(node: Record<string, unknown>): string {\n if (typeof node.text === \"string\") return node.text;\n const children = node.content as Array<Record<string, unknown>> | undefined;\n if (!children) return \"\";\n return children.map(extractText).join(\"\");\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Block, Note, BlockType } from \"./types\";\nimport { getTagDescendants } from \"./tags\";\n\nexport interface SearchResult {\n block: Block;\n noteId: string;\n noteTitle: string;\n matchType: \"text\" | \"tag\" | \"type\";\n}\n\nexport async function fullTextSearch(\n client: SupabaseClient,\n userId: string,\n query: string,\n limit = 30,\n): Promise<SearchResult[]> {\n const { data, error } = await client\n .from(\"blocks\")\n .select(\"*, notes!inner(id, title)\")\n .eq(\"user_id\", userId)\n .is(\"deleted_at\", null)\n .textSearch(\"content\", query, { type: \"websearch\" })\n .limit(limit);\n\n if (error) throw error;\n\n return ((data ?? []) as Array<Record<string, unknown>>).map((row) => {\n const notes = row.notes as Record<string, unknown>;\n return {\n block: row as unknown as Block,\n noteId: notes.id as string,\n noteTitle: notes.title as string,\n matchType: \"text\" as const,\n };\n });\n}\n\nexport async function searchByTag(\n client: SupabaseClient,\n userId: string,\n tagName: string,\n includeDescendants = true,\n): Promise<SearchResult[]> {\n const { data: tags } = await client\n .from(\"tags\")\n .select(\"id\")\n .eq(\"user_id\", userId)\n .eq(\"name\", tagName.toLowerCase())\n .single();\n\n if (!tags) return [];\n const tagId = (tags as Record<string, string>).id;\n\n let tagIds: string[];\n if (includeDescendants) {\n tagIds = await getTagDescendants(client, tagId);\n } else {\n tagIds = [tagId];\n }\n\n const { data, error } = await client\n .from(\"block_tags\")\n .select(\"block_id, blocks!inner(*, notes!inner(id, title))\")\n .in(\"tag_id\", tagIds);\n\n if (error) throw error;\n\n return ((data ?? []) as Array<Record<string, unknown>>).map((row) => {\n const block = row.blocks as Record<string, unknown>;\n const notes = block.notes as Record<string, unknown>;\n return {\n block: block as unknown as Block,\n noteId: notes.id as string,\n noteTitle: notes.title as string,\n matchType: \"tag\" as const,\n };\n });\n}\n\nexport async function searchByType(\n client: SupabaseClient,\n userId: string,\n blockType: BlockType,\n limit = 50,\n): Promise<SearchResult[]> {\n const { data, error } = await client\n .from(\"blocks\")\n .select(\"*, notes!inner(id, title)\")\n .eq(\"user_id\", userId)\n .eq(\"type\", blockType)\n .is(\"deleted_at\", null)\n .limit(limit);\n\n if (error) throw error;\n\n return ((data ?? []) as Array<Record<string, unknown>>).map((row) => {\n const notes = row.notes as Record<string, unknown>;\n return {\n block: row as unknown as Block,\n noteId: notes.id as string,\n noteTitle: notes.title as string,\n matchType: \"type\" as const,\n };\n });\n}\n\nexport interface QueryFilter {\n text?: string;\n tag?: string;\n type?: BlockType;\n status?: \"open\" | \"done\";\n hasLink?: boolean;\n}\n\nexport function parseQuery(input: string): QueryFilter {\n const filter: QueryFilter = {};\n const parts = input.trim().split(/\\s+/);\n const textParts: string[] = [];\n\n for (const part of parts) {\n if (part.startsWith(\"#\")) {\n const raw = part.slice(1).toLowerCase();\n filter.tag = raw.includes(\"/\") ? raw.split(\"/\").pop()! : raw;\n } else if (part.startsWith(\"type:\")) {\n filter.type = part.slice(5) as BlockType;\n } else if (part.startsWith(\"status:\")) {\n filter.status = part.slice(7) as \"open\" | \"done\";\n } else if (part === \"has:link\") {\n filter.hasLink = true;\n } else {\n textParts.push(part);\n }\n }\n\n if (textParts.length > 0) {\n filter.text = textParts.join(\" \");\n }\n\n return filter;\n}\n\nexport async function executeQuery(\n client: SupabaseClient,\n userId: string,\n input: string,\n limit = 30,\n): Promise<SearchResult[]> {\n const filter = parseQuery(input);\n let results: SearchResult[] = [];\n\n if (filter.tag) {\n results = await searchByTag(client, userId, filter.tag);\n } else if (filter.type) {\n results = await searchByType(client, userId, filter.type, limit);\n } else if (filter.text) {\n results = await fullTextSearch(client, userId, filter.text, limit);\n }\n\n if (filter.status && results.length > 0) {\n const isDone = filter.status === \"done\";\n results = results.filter((r) => {\n const meta = r.block.metadata as Record<string, unknown>;\n if (meta.status === filter.status) return true;\n const json = JSON.stringify(meta);\n if (isDone) return json.includes('\"checked\":true');\n return json.includes('\"checked\":false') || (json.includes('\"taskItem\"') && !json.includes('\"checked\":true'));\n });\n }\n\n return results;\n}\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\n\nexport interface GraphNode {\n id: string;\n label: string;\n type: \"note\" | \"tag\";\n color?: string;\n}\n\nexport interface GraphEdge {\n source: string;\n target: string;\n type: \"link\" | \"tag\";\n}\n\nexport interface GraphData {\n nodes: GraphNode[];\n edges: GraphEdge[];\n}\n\nexport async function getGraphData(\n client: SupabaseClient,\n userId: string,\n): Promise<GraphData> {\n const nodes: GraphNode[] = [];\n const edges: GraphEdge[] = [];\n\n const { data: notes } = await client\n .from(\"notes\")\n .select(\"id, title\")\n .eq(\"user_id\", userId)\n .is(\"deleted_at\", null);\n\n for (const n of (notes ?? []) as Array<{ id: string; title: string }>) {\n nodes.push({ id: n.id, label: n.title, type: \"note\" });\n }\n\n const { data: links } = await client\n .from(\"links\")\n .select(\"source_block_id, target_id, target_type, blocks!inner(note_id)\")\n .eq(\"user_id\", userId)\n .eq(\"target_type\", \"note\");\n\n for (const l of (links ?? []) as unknown as Array<{ target_id: string; blocks: { note_id: string } }>) {\n const sourceNoteId = l.blocks.note_id;\n const targetNoteId = l.target_id;\n if (sourceNoteId && targetNoteId && sourceNoteId !== targetNoteId) {\n edges.push({ source: sourceNoteId, target: targetNoteId, type: \"link\" });\n }\n }\n\n const { data: tags } = await client\n .from(\"tags\")\n .select(\"id, name, color\")\n .eq(\"user_id\", userId);\n\n for (const t of (tags ?? []) as Array<{ id: string; name: string; color: string | null }>) {\n nodes.push({ id: `tag-${t.id}`, label: `#${t.name}`, type: \"tag\", color: t.color ?? undefined });\n }\n\n const { data: noteTags } = await client\n .from(\"note_tags\")\n .select(\"note_id, tag_id\");\n\n for (const nt of (noteTags ?? []) as Array<{ note_id: string; tag_id: string }>) {\n edges.push({ source: nt.note_id, target: `tag-${nt.tag_id}`, type: \"tag\" });\n }\n\n const { data: tagEdges } = await client\n .from(\"tag_edges\")\n .select(\"parent_id, child_id\")\n .eq(\"user_id\", userId);\n\n for (const te of (tagEdges ?? []) as Array<{ parent_id: string; child_id: string }>) {\n edges.push({ source: `tag-${te.parent_id}`, target: `tag-${te.child_id}`, type: \"tag\" });\n }\n\n return { nodes, edges };\n}\n","export interface NoteTemplate {\n id: string;\n name: string;\n content: Record<string, unknown>;\n}\n\nexport const NOTE_TEMPLATES: NoteTemplate[] = [\n {\n id: \"blank\",\n name: \"Blank Note\",\n content: { type: \"doc\", content: [{ type: \"paragraph\" }] },\n },\n {\n id: \"meeting\",\n name: \"Meeting Notes\",\n content: {\n type: \"doc\",\n content: [\n { type: \"heading\", attrs: { level: 1 }, content: [{ type: \"text\", text: \"Meeting Notes\" }] },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Attendees\" }] },\n { type: \"paragraph\", content: [{ type: \"text\", text: \"- \" }] },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Agenda\" }] },\n { type: \"paragraph\", content: [{ type: \"text\", text: \"1. \" }] },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Discussion\" }] },\n { type: \"paragraph\" },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Action Items\" }] },\n { type: \"taskList\", content: [{ type: \"taskItem\", attrs: { checked: false }, content: [{ type: \"paragraph\" }] }] },\n ],\n },\n },\n {\n id: \"daily-standup\",\n name: \"Daily Standup\",\n content: {\n type: \"doc\",\n content: [\n { type: \"heading\", attrs: { level: 1 }, content: [{ type: \"text\", text: \"Daily Standup\" }] },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Yesterday\" }] },\n { type: \"taskList\", content: [{ type: \"taskItem\", attrs: { checked: true }, content: [{ type: \"paragraph\" }] }] },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Today\" }] },\n { type: \"taskList\", content: [{ type: \"taskItem\", attrs: { checked: false }, content: [{ type: \"paragraph\" }] }] },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Blockers\" }] },\n { type: \"paragraph\" },\n ],\n },\n },\n {\n id: \"project\",\n name: \"Project Plan\",\n content: {\n type: \"doc\",\n content: [\n { type: \"heading\", attrs: { level: 1 }, content: [{ type: \"text\", text: \"Project Name\" }] },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Overview\" }] },\n { type: \"paragraph\" },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Goals\" }] },\n { type: \"paragraph\", content: [{ type: \"text\", text: \"- \" }] },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Timeline\" }] },\n { type: \"paragraph\" },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Tasks\" }] },\n { type: \"taskList\", content: [{ type: \"taskItem\", attrs: { checked: false }, content: [{ type: \"paragraph\" }] }] },\n { type: \"heading\", attrs: { level: 2 }, content: [{ type: \"text\", text: \"Notes\" }] },\n { type: \"paragraph\" },\n ],\n },\n },\n];\n","import type { SupabaseClient } from \"@supabase/supabase-js\";\nimport type { Note } from \"./types\";\n\nfunction extractTextFromNode(node: Record<string, unknown>): string {\n if (typeof node.text === \"string\") return node.text;\n const content = node.content as Array<Record<string, unknown>> | undefined;\n if (!content) return \"\";\n return content.map(extractTextFromNode).join(\"\");\n}\n\nfunction extractInlineMarkdown(node: Record<string, unknown>): string {\n if (node.type === \"inlineMath\") {\n const formula = (node.attrs as Record<string, unknown>)?.formula as string ?? \"\";\n return `$${formula}$`;\n }\n if (typeof node.text === \"string\") {\n const marks = (node.marks ?? []) as Array<{ type: string; attrs?: Record<string, unknown> }>;\n let text = node.text;\n const linkMark = marks.find((m) => m.type === \"link\");\n if (linkMark) {\n const href = (linkMark.attrs?.href as string) ?? \"\";\n return `[${text}](${href})`;\n }\n for (const mark of marks) {\n if (mark.type === \"bold\") text = `**${text}**`;\n else if (mark.type === \"italic\") text = `*${text}*`;\n else if (mark.type === \"code\") text = `\\`${text}\\``;\n else if (mark.type === \"strike\") text = `~~${text}~~`;\n }\n return text;\n }\n const content = node.content as Array<Record<string, unknown>> | undefined;\n if (!content) return \"\";\n return content.map(extractInlineMarkdown).join(\"\");\n}\n\nfunction tiptapNodeToMarkdown(node: Record<string, unknown>): string[] {\n const type = node.type as string;\n const attrs = (node.attrs ?? {}) as Record<string, unknown>;\n const content = (node.content ?? []) as Array<Record<string, unknown>>;\n const lines: string[] = [];\n\n switch (type) {\n case \"heading\": {\n const level = (attrs.level as number) ?? 1;\n lines.push(`${\"#\".repeat(level)} ${extractInlineMarkdown({ content } as Record<string, unknown>)}`);\n break;\n }\n case \"paragraph\": {\n lines.push(extractInlineMarkdown({ content } as Record<string, unknown>));\n break;\n }\n case \"taskList\": {\n for (const child of content) {\n const childAttrs = (child.attrs ?? {}) as Record<string, unknown>;\n const checked = childAttrs.checked ? \"x\" : \" \";\n const text = extractInlineMarkdown(child);\n lines.push(`- [${checked}] ${text}`);\n }\n break;\n }\n case \"taskItem\": {\n const checked = attrs.checked ? \"x\" : \" \";\n lines.push(`- [${checked}] ${extractInlineMarkdown({ content } as Record<string, unknown>)}`);\n break;\n }\n case \"bulletList\": {\n for (const child of content) {\n const text = extractInlineMarkdown(child);\n lines.push(`- ${text}`);\n }\n break;\n }\n case \"orderedList\": {\n content.forEach((child, i) => {\n const text = extractInlineMarkdown(child);\n lines.push(`${i + 1}. ${text}`);\n });\n break;\n }\n case \"codeBlock\": {\n const lang = (attrs.language as string) ?? \"\";\n lines.push(\"```\" + lang, extractTextFromNode(node), \"```\");\n break;\n }\n case \"mermaidBlock\": {\n lines.push(\"```mermaid\", extractTextFromNode(node), \"```\");\n break;\n }\n case \"mathBlock\": {\n lines.push(\"$$\", extractTextFromNode(node), \"$$\");\n break;\n }\n case \"calloutBlock\": {\n const variant = (attrs.variant as string) ?? \"info\";\n const text = extractInlineMarkdown({ content } as Record<string, unknown>);\n lines.push(`> [!${variant}]`, ...text.split(\"\\n\").map((l) => `> ${l}`));\n break;\n }\n case \"queryBlock\": {\n const text = extractTextFromNode(node).trim();\n lines.push(`> [!query]`, `> ${text}`);\n break;\n }\n case \"blockquote\": {\n const text = extractInlineMarkdown({ content } as Record<string, unknown>);\n lines.push(...text.split(\"\\n\").map((l) => `> ${l}`));\n break;\n }\n case \"horizontalRule\": {\n lines.push(\"---\");\n break;\n }\n case \"image\": {\n const src = attrs.src as string ?? \"\";\n const alt = (attrs.alt as string) ?? \"\";\n lines.push(`![${alt}](${src})`);\n break;\n }\n case \"linkPreview\": {\n const url = attrs.url as string ?? \"\";\n lines.push(`> [!embed]`, `> ${url}`);\n break;\n }\n case \"fileBlock\": {\n const src = attrs.src as string ?? \"\";\n const filename = (attrs.filename as string) ?? \"file\";\n const filesize = (attrs.filesize as number) ?? 0;\n const filetype = (attrs.filetype as string) ?? \"\";\n lines.push(`> [!file]`, `> [${filename}](${src})`, `> ${filetype} ${filesize}`);\n break;\n }\n default: {\n const text = extractTextFromNode(node);\n if (text.trim()) lines.push(text);\n break;\n }\n }\n\n return lines;\n}\n\nexport async function exportNoteAsJson(\n client: SupabaseClient,\n noteId: string,\n): Promise<string> {\n const { data: note } = await client\n .from(\"notes\")\n .select(\"*\")\n .eq(\"id\", noteId)\n .single();\n\n const { data: blocks } = await client\n .from(\"blocks\")\n .select(\"*\")\n .eq(\"note_id\", noteId)\n .is(\"deleted_at\", null)\n .order(\"position\");\n\n return JSON.stringify({ note, blocks }, null, 2);\n}\n\nexport async function exportNoteAsMarkdown(\n client: SupabaseClient,\n noteId: string,\n): Promise<string> {\n const { data: note } = await client\n .from(\"notes\")\n .select(\"title\")\n .eq(\"id\", noteId)\n .single();\n\n const { data: blocks } = await client\n .from(\"blocks\")\n .select(\"type, content, metadata\")\n .eq(\"note_id\", noteId)\n .is(\"deleted_at\", null)\n .order(\"position\");\n\n if (!blocks) return \"\";\n\n const title = (note as Record<string, string>)?.title ?? \"Untitled\";\n const lines: string[] = [`# ${title}`, \"\"];\n\n for (const block of blocks as Array<{ type: string; content: string; metadata: Record<string, unknown> }>) {\n const tiptap = block.metadata.tiptap as Record<string, unknown> | undefined;\n if (tiptap) {\n lines.push(...tiptapNodeToMarkdown(tiptap), \"\");\n } else {\n if (block.content.trim()) lines.push(block.content, \"\");\n }\n }\n\n return lines.join(\"\\n\");\n}\n","interface TiptapNode {\n type: string;\n attrs?: Record<string, unknown>;\n content?: TiptapNode[];\n text?: string;\n marks?: Array<{ type: string; attrs?: Record<string, unknown> }>;\n}\n\nexport function markdownToTiptap(md: string): Record<string, unknown> {\n const lines = md.split(\"\\n\");\n const nodes: TiptapNode[] = [];\n let i = 0;\n\n while (i < lines.length) {\n const line = lines[i];\n\n if (line.match(/^#{1,4}\\s/)) {\n const match = line.match(/^(#{1,4})\\s(.*)$/);\n if (match) {\n nodes.push({\n type: \"heading\",\n attrs: { level: match[1].length },\n content: parseInline(match[2]),\n });\n }\n i++;\n continue;\n }\n\n if (line.match(/^```mermaid/)) {\n const mermaidLines: string[] = [];\n i++;\n while (i < lines.length && !lines[i].startsWith(\"```\")) {\n mermaidLines.push(lines[i]);\n i++;\n }\n if (i < lines.length) i++;\n nodes.push({\n type: \"mermaidBlock\",\n content: [{ type: \"text\", text: mermaidLines.join(\"\\n\") }],\n });\n continue;\n }\n\n if (line.startsWith(\"```\")) {\n const langMatch = line.match(/^```(\\w*)/);\n const language = langMatch?.[1] || \"plaintext\";\n const codeLines: string[] = [];\n i++;\n while (i < lines.length && !lines[i].startsWith(\"```\")) {\n codeLines.push(lines[i]);\n i++;\n }\n if (i < lines.length) i++;\n nodes.push({\n type: \"codeBlock\",\n attrs: { language },\n content: [{ type: \"text\", text: codeLines.join(\"\\n\") }],\n });\n continue;\n }\n\n if (line.startsWith(\"$$\")) {\n const mathLines: string[] = [];\n i++;\n while (i < lines.length && !lines[i].startsWith(\"$$\")) {\n mathLines.push(lines[i]);\n i++;\n }\n if (i < lines.length) i++;\n nodes.push({\n type: \"mathBlock\",\n content: [{ type: \"text\", text: mathLines.join(\"\\n\") }],\n });\n continue;\n }\n\n if (line.match(/^>\\s*\\[!(\\w+)\\]\\s*$/)) {\n const variantMatch = line.match(/^>\\s*\\[!(\\w+)\\]\\s*$/);\n const variant = variantMatch?.[1] ?? \"info\";\n\n if (variant === \"query\") {\n const queryLines: string[] = [];\n i++;\n while (i < lines.length && lines[i].match(/^>\\s/)) {\n queryLines.push(lines[i].replace(/^>\\s?/, \"\"));\n i++;\n }\n nodes.push({\n type: \"queryBlock\",\n content: [{ type: \"text\", text: queryLines.join(\"\\n\") }],\n });\n continue;\n }\n\n if (variant === \"embed\") {\n i++;\n const embedUrl = lines[i]?.replace(/^>\\s?/, \"\").trim() ?? \"\";\n i++;\n nodes.push({\n type: \"linkPreview\",\n attrs: { url: embedUrl },\n });\n continue;\n }\n\n if (variant === \"file\") {\n i++;\n const linkLine = lines[i]?.replace(/^>\\s?/, \"\") ?? \"\";\n const linkMatch = linkLine.match(/^\\[(.+?)\\]\\((.+?)\\)$/);\n i++;\n const metaLine = lines[i]?.replace(/^>\\s?/, \"\") ?? \"\";\n const metaParts = metaLine.split(\" \");\n i++;\n nodes.push({\n type: \"fileBlock\",\n attrs: {\n filename: linkMatch?.[1] ?? \"file\",\n src: linkMatch?.[2] ?? \"\",\n filetype: metaParts[0] ?? \"\",\n filesize: parseInt(metaParts[1] ?? \"0\", 10) || 0,\n },\n });\n continue;\n }\n\n const calloutLines: string[] = [];\n i++;\n while (i < lines.length && lines[i].match(/^>\\s/)) {\n calloutLines.push(lines[i].replace(/^>\\s?/, \"\"));\n i++;\n }\n nodes.push({\n type: \"calloutBlock\",\n attrs: { variant },\n content: [{ type: \"paragraph\", content: parseInline(calloutLines.join(\"\\n\")) }],\n });\n continue;\n }\n\n if (line.match(/^>\\s/)) {\n const quoteLines: string[] = [];\n while (i < lines.length && lines[i].match(/^>\\s?/)) {\n quoteLines.push(lines[i].replace(/^>\\s?/, \"\"));\n i++;\n }\n nodes.push({\n type: \"blockquote\",\n content: [{ type: \"paragraph\", content: parseInline(quoteLines.join(\"\\n\")) }],\n });\n continue;\n }\n\n if (line.match(/^---\\s*$/)) {\n nodes.push({ type: \"horizontalRule\" });\n i++;\n continue;\n }\n\n if (line.match(/^!\\[.*?\\]\\(.*?\\)$/)) {\n const imgMatch = line.match(/^!\\[(.*?)\\]\\((.*?)\\)$/);\n if (imgMatch) {\n nodes.push({\n type: \"image\",\n attrs: { src: imgMatch[2], alt: imgMatch[1] },\n });\n }\n i++;\n continue;\n }\n\n if (line.match(/^[-*]\\s\\[[ x]\\]\\s/)) {\n const taskItems: TiptapNode[] = [];\n while (i < lines.length && lines[i].match(/^[-*]\\s\\[[ x]\\]\\s/)) {\n const m = lines[i].match(/^[-*]\\s\\[([ x])\\]\\s(.*)$/);\n if (m) {\n taskItems.push({\n type: \"taskItem\",\n attrs: { checked: m[1] === \"x\" },\n content: [{ type: \"paragraph\", content: parseInline(m[2]) }],\n });\n }\n i++;\n }\n nodes.push({ type: \"taskList\", content: taskItems });\n continue;\n }\n\n if (line.match(/^[-*]\\s/)) {\n const items: TiptapNode[] = [];\n while (i < lines.length && lines[i].match(/^[-*]\\s/)) {\n const text = lines[i].replace(/^[-*]\\s/, \"\");\n items.push({\n type: \"listItem\",\n content: [{ type: \"paragraph\", content: parseInline(text) }],\n });\n i++;\n }\n nodes.push({ type: \"bulletList\", content: items });\n continue;\n }\n\n if (line.match(/^\\d+\\.\\s/)) {\n const items: TiptapNode[] = [];\n while (i < lines.length && lines[i].match(/^\\d+\\.\\s/)) {\n const text = lines[i].replace(/^\\d+\\.\\s/, \"\");\n items.push({\n type: \"listItem\",\n content: [{ type: \"paragraph\", content: parseInline(text) }],\n });\n i++;\n }\n nodes.push({ type: \"orderedList\", content: items });\n continue;\n }\n\n if (line.trim() === \"\") {\n i++;\n continue;\n }\n\n const paraLines: string[] = [];\n while (\n i < lines.length &&\n lines[i].trim() !== \"\" &&\n !lines[i].match(/^#{1,4}\\s/) &&\n !lines[i].match(/^```/) &&\n !lines[i].match(/^\\$\\$/) &&\n !lines[i].match(/^---\\s*$/) &&\n !lines[i].match(/^[-*]\\s/) &&\n !lines[i].match(/^\\d+\\.\\s/) &&\n !lines[i].match(/^>\\s/) &&\n !lines[i].match(/^!\\[/)\n ) {\n paraLines.push(lines[i]);\n i++;\n }\n nodes.push({\n type: \"paragraph\",\n content: parseInline(paraLines.join(\"\\n\")),\n });\n }\n\n if (nodes.length === 0) {\n nodes.push({ type: \"paragraph\" });\n }\n\n return { type: \"doc\", content: nodes };\n}\n\nfunction parseInline(text: string): TiptapNode[] {\n if (!text) return [];\n if (text.length > 10000) return [{ type: \"text\", text }];\n\n const nodes: TiptapNode[] = [];\n const regex = /(\\*\\*([^*]+)\\*\\*|\\*([^*]+)\\*|`([^`]+)`|~~([^~]+)~~|\\[\\[([^\\]]+)\\]\\]|#([a-zA-Z][a-zA-Z0-9_/-]*)|\\[([^\\]]+)\\]\\(([^)]+)\\)|(?<!\\$)\\$([^\\$\\n]+)\\$(?!\\$))/g;\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = regex.exec(text)) !== null) {\n if (match.index > lastIndex) {\n nodes.push({ type: \"text\", text: text.slice(lastIndex, match.index) });\n }\n\n if (match[2]) {\n nodes.push({ type: \"text\", text: match[2], marks: [{ type: \"bold\" }] });\n } else if (match[3]) {\n nodes.push({ type: \"text\", text: match[3], marks: [{ type: \"italic\" }] });\n } else if (match[4]) {\n nodes.push({ type: \"text\", text: match[4], marks: [{ type: \"code\" }] });\n } else if (match[5]) {\n nodes.push({ type: \"text\", text: match[5], marks: [{ type: \"strike\" }] });\n } else if (match[6]) {\n nodes.push({ type: \"text\", text: `[[${match[6]}]]` });\n } else if (match[7]) {\n nodes.push({ type: \"text\", text: `#${match[7]}` });\n } else if (match[8] && match[9]) {\n nodes.push({ type: \"text\", text: match[8], marks: [{ type: \"link\", attrs: { href: match[9], target: \"_blank\" } }] });\n } else if (match[10]) {\n nodes.push({ type: \"inlineMath\", attrs: { formula: match[10] } });\n }\n\n lastIndex = match.index + match[0].length;\n }\n\n if (lastIndex < text.length) {\n nodes.push({ type: \"text\", text: text.slice(lastIndex) });\n }\n\n return nodes.length > 0 ? nodes : [{ type: \"text\", text: text || \" \" }];\n}\n","export const VERTEX_VERSION = \"0.1.0\";\n\nexport {\n createSupabaseClient,\n initSupabaseClient,\n getSupabaseClient,\n type SupabaseClient,\n} from \"./client\";\n\nexport type {\n NoteType,\n BlockType,\n LinkTargetType,\n Priority,\n TodoStatus,\n CalloutVariant,\n ChartType,\n Profile,\n UserPreferences,\n Note,\n Block,\n BlockMetadata,\n TodoMetadata,\n CodeMetadata,\n HeadingMetadata,\n ImageMetadata,\n FileMetadata,\n MermaidMetadata,\n ChartMetadata,\n CalloutMetadata,\n QueryMetadata,\n ScopeMetadata,\n Tag,\n TagEdge,\n BlockTag,\n NoteTag,\n Link,\n Snapshot,\n SrsCard,\n TagWithCounts,\n NoteWithTags,\n BlockWithTags,\n BacklinkResult,\n} from \"./types\";\n\nexport {\n signInWithOAuth,\n signInWithEmail,\n signUpWithEmail,\n signOut,\n getUser,\n getSession,\n getProfile,\n onAuthStateChange,\n type OAuthProvider,\n type User,\n type Session,\n} from \"./auth\";\n\nexport {\n createNote,\n getNote,\n updateNote,\n softDeleteNote,\n restoreNote,\n hardDeleteNote,\n emptyTrash,\n listNotes,\n getOrCreateDailyNote,\n type CreateNoteParams,\n type ListNotesParams,\n type FileCleanupFn,\n} from \"./notes\";\n\nexport {\n createBlock,\n getBlocksForNote,\n updateBlock,\n deleteBlock,\n upsertBlocks,\n saveNoteContent,\n type CreateBlockParams,\n} from \"./blocks\";\n\nexport {\n createTag,\n getOrCreateTag,\n getUserTags,\n updateTag,\n deleteTag,\n addTagEdge,\n removeTagEdge,\n getTagParents,\n getTagChildren,\n getTagDescendants,\n addBlockTag,\n removeBlockTag,\n getBlocksByTag,\n} from \"./tags\";\n\nexport {\n createLink,\n deleteLinksForBlock,\n getBacklinksForNote,\n syncLinksForNote,\n} from \"./links\";\n\nexport {\n createSnapshot,\n listSnapshots,\n getSnapshot,\n getLatestSnapshot,\n diffSnapshots,\n type DiffResult,\n} from \"./snapshots\";\n\nexport {\n fullTextSearch,\n searchByTag,\n searchByType,\n parseQuery,\n executeQuery,\n type SearchResult,\n type QueryFilter,\n} from \"./search\";\n\nexport {\n getGraphData,\n type GraphNode,\n type GraphEdge,\n type GraphData,\n} from \"./graph\";\n\nexport { NOTE_TEMPLATES, type NoteTemplate } from \"./templates\";\n\nexport {\n exportNoteAsJson,\n exportNoteAsMarkdown,\n} from \"./export\";\n\nexport { markdownToTiptap } from \"./md-to-tiptap\";\n\nexport {\n DEFAULT_STORAGE_CAP,\n getStorageInfo,\n getStorageUsed,\n getStorageCap,\n checkStorageCap,\n incrementStorageUsed,\n decrementStorageUsed,\n formatFileSize,\n} from \"./storage\";\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/capture.ts"],"sourcesContent":["import { Command, Args } from \"@oclif/core\";\nimport { listNotes, getBlocksForNote, saveNoteContent } from \"@vertex/core\";\nimport { getClient, getUserId } from \"../lib/client.js\";\n\nexport default class Capture extends Command {\n static override description = \"Quick capture text to Inbox\";\n\n static override args = {\n text: Args.string({ description: \"Text to capture\", required: true }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(Capture);\n const client = await getClient();\n const userId = await getUserId();\n const notes = await listNotes(client, { user_id: userId });\n const inbox = notes.find((n) => n.note_type === \"inbox\" && !n.deleted_at);\n\n if (!inbox) {\n this.error(\"Inbox note not found\");\n }\n\n const blocks = await getBlocksForNote(client, inbox.id);\n const existingContent = blocks.map((b) => {\n const meta = b.metadata as Record<string, unknown>;\n return (meta.tiptap ?? { type: \"paragraph\", content: [{ type: \"text\", text: b.content }] }) as Record<string, unknown>;\n });\n\n existingContent.push({\n type: \"paragraph\",\n content: [{ type: \"text\", text: args.text }],\n });\n\n await saveNoteContent(client, inbox.id, userId, { type: \"doc\", content: existingContent });\n this.log(`Captured to Inbox: \"${args.text}\"`);\n }\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,SAAS,YAAY;AAI9B,IAAqB,UAArB,MAAqB,iBAAgB,QAAQ;AAAA,EAC3C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,OAAO;AAAA,IACrB,MAAM,KAAK,OAAO,EAAE,aAAa,mBAAmB,UAAU,KAAK,CAAC;AAAA,EACtE;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,QAAO;AACzC,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,QAAQ,MAAM,UAAU,QAAQ,EAAE,SAAS,OAAO,CAAC;AACzD,UAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,cAAc,WAAW,CAAC,EAAE,UAAU;AAExE,QAAI,CAAC,OAAO;AACV,WAAK,MAAM,sBAAsB;AAAA,IACnC;AAEA,UAAM,SAAS,MAAM,iBAAiB,QAAQ,MAAM,EAAE;AACtD,UAAM,kBAAkB,OAAO,IAAI,CAAC,MAAM;AACxC,YAAM,OAAO,EAAE;AACf,aAAQ,KAAK,UAAU,EAAE,MAAM,aAAa,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,EAAE,QAAQ,CAAC,EAAE;AAAA,IAC3F,CAAC;AAED,oBAAgB,KAAK;AAAA,MACnB,MAAM;AAAA,MACN,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK,CAAC;AAAA,IAC7C,CAAC;AAED,UAAM,gBAAgB,QAAQ,MAAM,IAAI,QAAQ,EAAE,MAAM,OAAO,SAAS,gBAAgB,CAAC;AACzF,SAAK,IAAI,uBAAuB,KAAK,IAAI,GAAG;AAAA,EAC9C;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/daily.ts"],"sourcesContent":["import { Command, Flags } from \"@oclif/core\";\nimport { getOrCreateDailyNote, listNotes, exportNoteAsMarkdown } from \"@vertex/core\";\nimport { getClient, getUserId } from \"../lib/client.js\";\n\nexport default class Daily extends Command {\n static override description = \"View or create today's daily note\";\n\n static override flags = {\n last: Flags.boolean({ description: \"Open the most recent daily note (don't create new)\", default: false }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Daily);\n const client = await getClient();\n const userId = await getUserId();\n\n let noteId: string;\n let title: string;\n\n if (flags.last) {\n const notes = await listNotes(client, { user_id: userId, note_type: \"daily\" as \"daily\" });\n const dailies = notes.filter((n) => !n.deleted_at).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());\n if (dailies.length === 0) {\n this.log(\"No daily notes yet.\");\n return;\n }\n noteId = dailies[0].id;\n title = dailies[0].title;\n } else {\n const today = new Date().toISOString().split(\"T\")[0];\n const note = await getOrCreateDailyNote(client, userId, today);\n noteId = note.id;\n title = note.title;\n }\n\n const md = await exportNoteAsMarkdown(client, noteId);\n if (md.trim()) {\n this.log(md);\n } else {\n this.log(`# ${title}\\n\\n(empty)`);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,SAAS,aAAa;AAI/B,IAAqB,QAArB,MAAqB,eAAc,QAAQ;AAAA,EACzC,OAAgB,cAAc;AAAA,EAE9B,OAAgB,QAAQ;AAAA,IACtB,MAAM,MAAM,QAAQ,EAAE,aAAa,sDAAsD,SAAS,MAAM,CAAC;AAAA,EAC3G;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,MAAK;AACxC,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,SAAS,MAAM,UAAU;AAE/B,QAAI;AACJ,QAAI;AAEJ,QAAI,MAAM,MAAM;AACd,YAAM,QAAQ,MAAM,UAAU,QAAQ,EAAE,SAAS,QAAQ,WAAW,QAAmB,CAAC;AACxF,YAAM,UAAU,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC;AACrI,UAAI,QAAQ,WAAW,GAAG;AACxB,aAAK,IAAI,qBAAqB;AAC9B;AAAA,MACF;AACA,eAAS,QAAQ,CAAC,EAAE;AACpB,cAAQ,QAAQ,CAAC,EAAE;AAAA,IACrB,OAAO;AACL,YAAM,SAAQ,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AACnD,YAAM,OAAO,MAAM,qBAAqB,QAAQ,QAAQ,KAAK;AAC7D,eAAS,KAAK;AACd,cAAQ,KAAK;AAAA,IACf;AAEA,UAAM,KAAK,MAAM,qBAAqB,QAAQ,MAAM;AACpD,QAAI,GAAG,KAAK,GAAG;AACb,WAAK,IAAI,EAAE;AAAA,IACb,OAAO;AACL,WAAK,IAAI,KAAK,KAAK;AAAA;AAAA,QAAa;AAAA,IAClC;AAAA,EACF;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/delete.ts"],"sourcesContent":["import { Command, Args } from \"@oclif/core\";\nimport { listNotes, softDeleteNote } from \"@vertex/core\";\nimport { getClient, getUserId } from \"../lib/client.js\";\n\nexport default class Delete extends Command {\n static override description = \"Move a note to trash\";\n\n static override args = {\n title: Args.string({ description: \"Note title (partial match)\", required: true }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(Delete);\n const client = await getClient();\n const userId = await getUserId();\n const notes = await listNotes(client, { user_id: userId });\n const query = args.title.toLowerCase();\n const match = notes.find((n) => !n.deleted_at && n.title.toLowerCase().includes(query));\n\n if (!match) {\n this.error(`No note matching \"${args.title}\"`);\n }\n\n if (match.note_type === \"inbox\") {\n this.error(\"Cannot delete the Inbox note\");\n }\n\n await softDeleteNote(client, match.id);\n this.log(`Trashed: ${match.title}`);\n }\n}\n"],"mappings":";;;;;;;;;;;AAAA,SAAS,SAAS,YAAY;AAI9B,IAAqB,SAArB,MAAqB,gBAAe,QAAQ;AAAA,EAC1C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,OAAO;AAAA,IACrB,OAAO,KAAK,OAAO,EAAE,aAAa,8BAA8B,UAAU,KAAK,CAAC;AAAA,EAClF;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,OAAM;AACxC,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,QAAQ,MAAM,UAAU,QAAQ,EAAE,SAAS,OAAO,CAAC;AACzD,UAAM,QAAQ,KAAK,MAAM,YAAY;AACrC,UAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,MAAM,YAAY,EAAE,SAAS,KAAK,CAAC;AAEtF,QAAI,CAAC,OAAO;AACV,WAAK,MAAM,qBAAqB,KAAK,KAAK,GAAG;AAAA,IAC/C;AAEA,QAAI,MAAM,cAAc,SAAS;AAC/B,WAAK,MAAM,8BAA8B;AAAA,IAC3C;AAEA,UAAM,eAAe,QAAQ,MAAM,EAAE;AACrC,SAAK,IAAI,YAAY,MAAM,KAAK,EAAE;AAAA,EACpC;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/edit.ts"],"sourcesContent":["import { Command, Args } from \"@oclif/core\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { writeFileSync, readFileSync } from \"node:fs\";\nimport { execSync } from \"node:child_process\";\nimport { createInterface } from \"node:readline\";\nimport { listNotes, exportNoteAsMarkdown, saveNoteContent } from \"@vertex/core\";\nimport { getClient, getUserId } from \"../lib/client.js\";\nimport { markdownToTiptap } from \"@vertex/core\";\n\nconst SYNTAX_GUIDE = `\n Markdown Syntax Guide\n ─────────────────────\n\n Headings: # H1 ## H2 ### H3\n Formatting: **bold** *italic* \\`code\\` ~~strike~~\n Links: [[Wiki Link]] #tagname\n\n Lists: - bullet 1. numbered\n Tasks: - [x] done - [ ] open\n Other: > blockquote --- divider\n\n Code block: \\`\\`\\`python Math block: $$\n print(\"hi\") E = mc^2\n \\`\\`\\` $$\n\n Web app only: mermaid, callouts, query blocks, file uploads\n`;\n\nexport default class Edit extends Command {\n static override description = \"Edit a note in your $EDITOR\";\n\n static override args = {\n title: Args.string({ description: \"Note title (partial match)\", required: true }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(Edit);\n const client = await getClient();\n const userId = await getUserId();\n const notes = await listNotes(client, { user_id: userId });\n const query = args.title.toLowerCase();\n const match = notes.find((n) => !n.deleted_at && n.title.toLowerCase().includes(query));\n\n if (!match) {\n this.error(`No note matching \"${args.title}\"`);\n }\n\n const editor = process.env.EDITOR || process.env.VISUAL || \"vim\";\n\n this.log(`\\n Editing: ${match.title}`);\n this.log(` Editor: ${editor}`);\n this.log(SYNTAX_GUIDE);\n\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n await new Promise<void>((resolve) => {\n rl.question(\" Press Enter to open editor...\", () => { rl.close(); resolve(); });\n });\n\n const md = await exportNoteAsMarkdown(client, match.id);\n const tmpFile = join(tmpdir(), `vertex-${match.id}.md`);\n writeFileSync(tmpFile, md, \"utf-8\");\n\n try {\n execSync(`${editor} \"${tmpFile}\"`, { stdio: \"inherit\" });\n } catch {\n this.error(\"Editor exited with error\");\n }\n\n const edited = readFileSync(tmpFile, \"utf-8\");\n if (edited === md) {\n this.log(\"No changes.\");\n return;\n }\n\n const tiptapJson = markdownToTiptap(edited);\n await saveNoteContent(client, match.id, userId, tiptapJson);\n this.log(`Saved: ${match.title}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAAA,SAAS,SAAS,YAAY;AAC9B,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,eAAe,oBAAoB;AAC5C,SAAS,gBAAgB;AACzB,SAAS,uBAAuB;AAKhC,IAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBrB,IAAqB,OAArB,MAAqB,cAAa,QAAQ;AAAA,EACxC,OAAgB,cAAc;AAAA,EAE9B,OAAgB,OAAO;AAAA,IACrB,OAAO,KAAK,OAAO,EAAE,aAAa,8BAA8B,UAAU,KAAK,CAAC;AAAA,EAClF;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAI;AACtC,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,QAAQ,MAAM,UAAU,QAAQ,EAAE,SAAS,OAAO,CAAC;AACzD,UAAM,QAAQ,KAAK,MAAM,YAAY;AACrC,UAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,MAAM,YAAY,EAAE,SAAS,KAAK,CAAC;AAEtF,QAAI,CAAC,OAAO;AACV,WAAK,MAAM,qBAAqB,KAAK,KAAK,GAAG;AAAA,IAC/C;AAEA,UAAM,SAAS,QAAQ,IAAI,UAAU,QAAQ,IAAI,UAAU;AAE3D,SAAK,IAAI;AAAA,aAAgB,MAAM,KAAK,EAAE;AACtC,SAAK,IAAI,cAAc,MAAM,EAAE;AAC/B,SAAK,IAAI,YAAY;AAErB,UAAM,KAAK,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,UAAM,IAAI,QAAc,CAAC,YAAY;AACnC,SAAG,SAAS,mCAAmC,MAAM;AAAE,WAAG,MAAM;AAAG,gBAAQ;AAAA,MAAG,CAAC;AAAA,IACjF,CAAC;AAED,UAAM,KAAK,MAAM,qBAAqB,QAAQ,MAAM,EAAE;AACtD,UAAM,UAAU,KAAK,OAAO,GAAG,UAAU,MAAM,EAAE,KAAK;AACtD,kBAAc,SAAS,IAAI,OAAO;AAElC,QAAI;AACF,eAAS,GAAG,MAAM,KAAK,OAAO,KAAK,EAAE,OAAO,UAAU,CAAC;AAAA,IACzD,QAAQ;AACN,WAAK,MAAM,0BAA0B;AAAA,IACvC;AAEA,UAAM,SAAS,aAAa,SAAS,OAAO;AAC5C,QAAI,WAAW,IAAI;AACjB,WAAK,IAAI,aAAa;AACtB;AAAA,IACF;AAEA,UAAM,aAAa,iBAAiB,MAAM;AAC1C,UAAM,gBAAgB,QAAQ,MAAM,IAAI,QAAQ,UAAU;AAC1D,SAAK,IAAI,UAAU,MAAM,KAAK,EAAE;AAAA,EAClC;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/export.ts"],"sourcesContent":["import { Command, Args, Flags } from \"@oclif/core\";\nimport { writeFileSync } from \"node:fs\";\nimport { listNotes, exportNoteAsMarkdown, exportNoteAsJson } from \"@vertex/core\";\nimport { getClient, getUserId } from \"../lib/client.js\";\n\nexport default class Export extends Command {\n static override description = \"Export a note as markdown or JSON\";\n\n static override args = {\n title: Args.string({ description: \"Note title (partial match)\", required: true }),\n };\n\n static override flags = {\n json: Flags.boolean({ description: \"Export as JSON instead of markdown\", default: false }),\n out: Flags.string({ char: \"o\", description: \"Output file path (default: stdout)\" }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Export);\n const client = await getClient();\n const userId = await getUserId();\n const notes = await listNotes(client, { user_id: userId });\n const query = args.title.toLowerCase();\n const match = notes.find((n) => !n.deleted_at && n.title.toLowerCase().includes(query));\n\n if (!match) {\n this.error(`No note matching \"${args.title}\"`);\n }\n\n const content = flags.json\n ? await exportNoteAsJson(client, match.id)\n : await exportNoteAsMarkdown(client, match.id);\n\n if (flags.out) {\n writeFileSync(flags.out, content, \"utf-8\");\n this.log(`Exported to ${flags.out}`);\n } else {\n this.log(content);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,SAAS,MAAM,aAAa;AACrC,SAAS,qBAAqB;AAI9B,IAAqB,SAArB,MAAqB,gBAAe,QAAQ;AAAA,EAC1C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,OAAO;AAAA,IACrB,OAAO,KAAK,OAAO,EAAE,aAAa,8BAA8B,UAAU,KAAK,CAAC;AAAA,EAClF;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACtB,MAAM,MAAM,QAAQ,EAAE,aAAa,sCAAsC,SAAS,MAAM,CAAC;AAAA,IACzF,KAAK,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,qCAAqC,CAAC;AAAA,EACpF;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,MAAM,OAAM;AAC/C,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,QAAQ,MAAM,UAAU,QAAQ,EAAE,SAAS,OAAO,CAAC;AACzD,UAAM,QAAQ,KAAK,MAAM,YAAY;AACrC,UAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,MAAM,YAAY,EAAE,SAAS,KAAK,CAAC;AAEtF,QAAI,CAAC,OAAO;AACV,WAAK,MAAM,qBAAqB,KAAK,KAAK,GAAG;AAAA,IAC/C;AAEA,UAAM,UAAU,MAAM,OAClB,MAAM,iBAAiB,QAAQ,MAAM,EAAE,IACvC,MAAM,qBAAqB,QAAQ,MAAM,EAAE;AAE/C,QAAI,MAAM,KAAK;AACb,oBAAc,MAAM,KAAK,SAAS,OAAO;AACzC,WAAK,IAAI,eAAe,MAAM,GAAG,EAAE;AAAA,IACrC,OAAO;AACL,WAAK,IAAI,OAAO;AAAA,IAClB;AAAA,EACF;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/hello.ts"],"sourcesContent":["import { Command } from \"@oclif/core\";\nimport { VERTEX_VERSION } from \"@vertex/core\";\n\nexport default class Hello extends Command {\n static override description = \"Verify Vertex CLI is working\";\n\n async run(): Promise<void> {\n this.log(`Vertex CLI ready (v${VERTEX_VERSION})`);\n }\n}\n"],"mappings":";;;;;AAAA,SAAS,eAAe;AAGxB,IAAqB,QAArB,cAAmC,QAAQ;AAAA,EACzC,OAAgB,cAAc;AAAA,EAE9B,MAAM,MAAqB;AACzB,SAAK,IAAI,sBAAsB,cAAc,GAAG;AAAA,EAClD;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/help.ts"],"sourcesContent":["import { Command } from \"@oclif/core\";\nimport { VERTEX_VERSION } from \"@vertex/core\";\n\nconst DIM = \"\\x1b[90m\";\nconst BOLD = \"\\x1b[1m\";\nconst CYAN = \"\\x1b[36m\";\nconst YELLOW = \"\\x1b[33m\";\nconst GREEN = \"\\x1b[32m\";\nconst PURPLE = \"\\x1b[35m\";\nconst R = \"\\x1b[0m\";\n\nfunction heading(text: string): string {\n return `\\n ${BOLD}${CYAN}${text}${R}`;\n}\n\nfunction row(cmd: string, desc: string): string {\n return ` ${GREEN}${cmd.padEnd(32)}${R}${DIM}${desc}${R}`;\n}\n\nfunction sub(text: string): string {\n return ` ${DIM}${text}${R}`;\n}\n\nexport default class Help extends Command {\n static override description = \"Show all Vertex CLI commands\";\n\n async run(): Promise<void> {\n this.log(`\n ${BOLD}${PURPLE}▲ Vertex CLI${R} ${DIM}v${VERTEX_VERSION}${R}\n ${DIM}Your knowledge, structured — from the terminal.${R}\n${heading(\"AUTH\")}\n${row(\"vertex login\", \"Log in (GitHub, Google, or Email)\")}\n${row(\"vertex logout\", \"Log out and clear saved session\")}\n${row(\"vertex whoami\", \"Show logged-in user email\")}\n${heading(\"NOTES\")}\n${row(\"vertex notes\", \"List all notes\")}\n${row(\"vertex new [title]\", \"Create a new note\")}\n${row(\"vertex view <title>\", \"View note as markdown\")}\n${row(\"vertex edit <title>\", \"Edit note in $EDITOR\")}\n${row(\"vertex daily\", \"View or create today's daily note\")}\n${row(\"vertex daily --last\", \"View most recent daily note\")}\n${heading(\"INTERACTIVE MODE\")}\n${row(\"vertex today\", \"Latest daily note → interactive\")}\n${row(\"vertex interactive <title>\", \"Open any note → interactive\")}\n\n ${DIM}┌──────────┬────────────────────────────────────────────┐${R}\n ${DIM}│${R} ${YELLOW}↑ ↓${R} ${DIM}│${R} Move cursor between items ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}Enter${R} ${DIM}│${R} Toggle todo ${DIM}[ ] → [✓] → [ ]${R} ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}t${R} ${DIM}│${R} Add new todo ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}n${R} ${DIM}│${R} Add new text line ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}d${R} ${DIM}│${R} Delete item at cursor ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}e${R} ${DIM}│${R} Open in $EDITOR for full editing ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}s${R} ${DIM}│${R} Save changes ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}q${R} ${DIM}│${R} Quit ${DIM}(auto-saves if changed)${R} ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}Esc${R} ${DIM}│${R} Cancel input ${DIM}│${R}\n ${DIM}└──────────┴────────────────────────────────────────────┘${R}\n${heading(\"CAPTURE\")}\n${row(\"vertex capture \\\"text\\\"\", \"Quick capture to Inbox note\")}\n${heading(\"SEARCH & ORGANIZE\")}\n${row(\"vertex search <query>\", \"Search notes\")}\n${row(\"vertex tags\", \"List all tags\")}\n\n ${DIM}Query syntax: ${PURPLE}keyword${R}${DIM} · ${PURPLE}#tag${R}${DIM} · ${PURPLE}type:todo${R}${DIM} · ${PURPLE}status:open${R}${DIM} · ${PURPLE}status:done${R}\n${heading(\"IMPORT & EXPORT\")}\n${row(\"vertex import <file.md>\", \"Import markdown file as new note\")}\n${row(\"vertex import <file> -t \\\"Title\\\"\", \"Import with custom title\")}\n${row(\"vertex export <title>\", \"Export as markdown to stdout\")}\n${row(\"vertex export <title> --json\", \"Export as JSON\")}\n${row(\"vertex export <title> -o file\", \"Export to file\")}\n${heading(\"TRASH\")}\n${row(\"vertex delete <title>\", \"Soft delete → trash\")}\n${row(\"vertex restore <title>\", \"Restore from trash\")}\n${row(\"vertex trash\", \"List trashed notes\")}\n${row(\"vertex trash:empty\", \"Permanently delete all trash\")}\n${heading(\"INFO\")}\n${row(\"vertex status\", \"Storage usage, note count, version\")}\n${row(\"vertex hello\", \"Verify CLI is working\")}\n${row(\"vertex help\", \"Show this help\")}\n${row(\"vertex syntax\", \"Markdown syntax reference\")}\n${row(\"vertex howto\", \"Complete AI guide — everything to know\")}\n${heading(\"EDITOR SYNTAX\")}\n${sub(\"for use with: vertex edit <title>\")}\n\n ${DIM}┌────────────────────────┬────────────────────────────────┐${R}\n ${DIM}│${R} ${YELLOW}# ## ###${R} ${DIM}│${R} Headings ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}**bold** *italic*${R} ${DIM}│${R} Formatting ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}\\`code\\` ~~strike~~${R} ${DIM}│${R} Inline code & strikethrough ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}[[Link]] #tag${R} ${DIM}│${R} Wiki links & tags ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}- item${R} ${YELLOW}1. item${R} ${DIM}│${R} Bullet & numbered lists ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}- [x]${R} ${YELLOW}- [ ]${R} ${DIM}│${R} Done & open tasks ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}> quote${R} ${YELLOW}---${R} ${DIM}│${R} Blockquote & divider ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}\\`\\`\\`lang ... \\`\\`\\`${R} ${DIM}│${R} Code block ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}\\`\\`\\`mermaid ... \\`\\`\\`${R} ${DIM}│${R} Mermaid diagram ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}$$ ... $$${R} ${DIM}│${R} Math block (LaTeX) ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}> [!info] > text${R} ${DIM}│${R} Callout (info/warning/error/tip)${DIM}│${R}\n ${DIM}│${R} ${YELLOW}> [!query] > query${R} ${DIM}│${R} Live query block ${DIM}│${R}\n ${DIM}│${R} ${YELLOW}![alt](url)${R} ${DIM}│${R} Image ${DIM}│${R}\n ${DIM}└────────────────────────┴────────────────────────────────┘${R}\n ${DIM}All block types work in CLI edit, export, and import${R}\n${heading(\"TIPS\")}\n ${DIM}•${R} Title args use partial matching ${DIM}(\"proj\" → \"Project Plan\")${R}\n ${DIM}•${R} Set ${YELLOW}EDITOR=nano${R} or ${YELLOW}EDITOR=\"code --wait\"${R} for preferred editor\n ${DIM}•${R} Session stored in ${DIM}~/.vertex/config.json${R}\n ${DIM}•${R} New users get 50 MB storage, upgradeable per account\n ${DIM}•${R} ${GREEN}vertex today${R} is the fastest way to manage daily todos\n${heading(\"EXAMPLES\")}\n ${DIM}$${R} vertex today\n ${DIM}$${R} vertex capture \"buy groceries\"\n ${DIM}$${R} vertex search \"#work type:todo status:open\"\n ${DIM}$${R} vertex export \"Meeting Notes\" -o meeting.md\n ${DIM}$${R} EDITOR=nano vertex edit \"Ideas\"\n`);\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/howto.ts"],"sourcesContent":["import { Command } from \"@oclif/core\";\n\nconst D = \"\\x1b[90m\";\nconst B = \"\\x1b[1m\";\nconst C = \"\\x1b[36m\";\nconst Y = \"\\x1b[33m\";\nconst G = \"\\x1b[32m\";\nconst P = \"\\x1b[35m\";\nconst R = \"\\x1b[0m\";\n\nexport default class Howto extends Command {\n static override description = \"Complete guide for AI agents to create and manage Vertex notes\";\n\n async run(): Promise<void> {\n this.log(`\n${B}${P} Vertex — Complete AI Guide${R}\n${D} Everything an AI agent needs to create, edit, and manage notes.${R}\n${D} Read this once, then you can do anything in Vertex.${R}\n${D} ══════════════════════════════════════════════════════════════${R}\n\n${C}${B} 1. WHAT IS VERTEX?${R}\n${D} A knowledge workspace. Notes are stored in the cloud (Supabase).${R}\n${D} You write markdown in the terminal → it renders as rich content${R}\n${D} (diagrams, math, code, callouts) in the web app.${R}\n${D} Notes can link to each other via [[wiki links]] and #tags.${R}\n\n${C}${B} 2. HOW TO CREATE A NOTE${R}\n\n${D} Option A: Create and edit in one step${R}\n ${G}vertex new \"My Note Title\"${R}\n ${G}vertex edit \"My Note\"${R} ${D}← opens in $EDITOR (vim/nano/code)${R}\n\n${D} Option B: Write a .md file, then import${R}\n ${G}cat > note.md << 'EOF'${R}\n ${Y}# My Note Title${R}\n ${Y}Content here...${R}\n ${G}EOF${R}\n ${G}vertex import note.md -t \"My Note Title\"${R}\n\n${D} Option C: Quick one-liner to inbox${R}\n ${G}vertex capture \"Remember to review PR #42\"${R}\n\n${C}${B} 3. HOW TO EDIT AN EXISTING NOTE${R}\n\n ${G}vertex edit \"Note Title\"${R} ${D}← partial match works: \"Note\" matches \"Note Title\"${R}\n${D} This exports the note as markdown, opens your $EDITOR,${R}\n${D} and when you save & quit, it parses the markdown back${R}\n${D} and updates the note in the database.${R}\n\n${D} To use a specific editor:${R}\n ${G}EDITOR=nano vertex edit \"My Note\"${R}\n ${G}EDITOR=\"code --wait\" vertex edit \"My Note\"${R}\n ${G}EDITOR=vim vertex edit \"My Note\"${R}\n\n${C}${B} 4. HOW TO VIEW A NOTE (read-only)${R}\n\n ${G}vertex view \"Note Title\"${R} ${D}← prints markdown to stdout${R}\n ${G}vertex view \"Note\" | less${R} ${D}← paginated view${R}\n ${G}vertex export \"Note\" -o note.md${R} ${D}← save to file${R}\n\n${C}${B} 5. HOW TO LIST AND FIND NOTES${R}\n\n ${G}vertex notes${R} ${D}← list all notes${R}\n ${G}vertex search \"keyword\"${R} ${D}← full-text search${R}\n ${G}vertex search \"#tagname\"${R} ${D}← search by tag${R}\n ${G}vertex search \"type:todo status:open\"${R} ${D}← find open todos${R}\n ${G}vertex tags${R} ${D}← list all tags${R}\n ${G}vertex daily --last${R} ${D}← view latest daily note${R}\n\n${D} ══════════════════════════════════════════════════════════════${R}\n\n${C}${B} 6. MARKDOWN SYNTAX — ALL BLOCK TYPES${R}\n\n${D} ┌─ IMPORTANT ────────────────────────────────────────────────${R}\n${D} │ Every block must be separated by a BLANK LINE.${R}\n${D} │ The first # H1 heading becomes the note title.${R}\n${D} │ Tags must start with a letter (a-z): #valid not #123${R}\n${D} └──────────────────────────────────────────────────────────${R}\n\n${C} HEADINGS${R}\n${Y} # Heading 1${R}\n${Y} ## Heading 2${R}\n${Y} ### Heading 3${R}\n\n${C} TEXT FORMATTING${R}\n${Y} **bold text**${R}\n${Y} *italic text*${R}\n${Y} \\`inline code\\`${R}\n${Y} ~~strikethrough~~${R}\n\n${C} BULLET LIST${R}\n${Y} - Item one${R}\n${Y} - Item two${R}\n${Y} - Item three${R}\n\n${C} NUMBERED LIST${R}\n${Y} 1. First${R}\n${Y} 2. Second${R}\n${Y} 3. Third${R}\n\n${C} TODO TASKS${R}\n${Y} - [ ] Open task${R}\n${Y} - [x] Completed task${R}\n\n${C} BLOCKQUOTE${R}\n${Y} > Quoted text here${R}\n\n${C} DIVIDER${R}\n${Y} ---${R}\n\n${C} CODE BLOCK${R}\n${Y} \\`\\`\\`python${R}\n${Y} def hello():${R}\n${Y} print(\"Hello!\")${R}\n${Y} \\`\\`\\`${R}\n${D} Languages: python, javascript, typescript, rust, go, java,${R}\n${D} c, cpp, sql, html, css, json, yaml, bash, ruby, swift, etc.${R}\n\n${C} MERMAID DIAGRAM${R}\n${Y} \\`\\`\\`mermaid${R}\n${Y} graph TD;${R}\n${Y} A --> B --> C;${R}\n${Y} \\`\\`\\`${R}\n${D} Types: graph/flowchart, sequenceDiagram, classDiagram,${R}\n${D} erDiagram, stateDiagram, gantt, pie, gitGraph, mindmap${R}\n\n${C} INLINE MATH${R}\n${Y} The value $E = mc^2$ is inline.${R}\n${Y} Solve $\\\\frac{-b \\\\pm \\\\sqrt{b^2-4ac}}{2a}$ for $x$.${R}\n${D} Use single $ for inline math within text.${R}\n\n${C} BLOCK MATH (LaTeX via KaTeX)${R}\n${Y} $$${R}\n${Y} E = mc^2${R}\n${Y} $$${R}\n${D} Use $$ on separate lines for standalone equations.${R}\n${D} LaTeX: \\\\frac{a}{b} \\\\sqrt{x} \\\\sum_{i=1}^{n} \\\\int_0^1${R}\n${D} \\\\alpha \\\\beta \\\\pi \\\\infty \\\\text{label} x^{2} x_{i}${R}\n\n${C} CALLOUT${R}\n${Y} > [!info]${R}\n${Y} > Informational note${R}\n${D} Variants: info, warning, error, tip${R}\n${D} Multi-line: each line starts with > ${R}\n\n${C} QUERY BLOCK${R}\n${Y} > [!query]${R}\n${Y} > type:todo status:open #work${R}\n\n${C} INLINE LINK${R}\n${Y} [Link Text](https://example.com)${R}\n${D} Opens in new tab. Standard markdown link syntax.${R}\n\n${C} EMBED (link preview)${R}\n${Y} > [!embed]${R}\n${Y} > https://youtube.com/watch?v=ID${R}\n${D} YouTube → video player. Other URLs → preview card.${R}\n\n${C} IMAGE${R}\n${Y} ![description](https://url.com/image.png)${R}\n\n${C} FILE ATTACHMENT${R}\n${Y} > [!file]${R}\n${Y} > [filename.pdf](https://url.com/file.pdf)${R}\n${Y} > application/pdf 149780${R}\n\n${D} ══════════════════════════════════════════════════════════════${R}\n\n${C}${B} 7. WIKI LINKS — HOW TO CONNECT NOTES${R}\n\n${D} Wiki links create connections between notes.${R}\n${D} They render as clickable purple links in the web app.${R}\n${D} The linked note shows a \"backlink\" at the bottom.${R}\n\n${Y} Check out [[Project Roadmap]] for details.${R}\n${Y} This connects to [[AI Research Notes]] and [[Meeting Notes]].${R}\n\n${D} Rules:${R}\n${D} • Use the exact note title inside [[ ]]${R}\n${D} • Case-insensitive: [[my note]] matches \"My Note\"${R}\n${D} • If the note doesn't exist yet, the link is still created${R}\n${D} • Multiple links in one paragraph is fine${R}\n${D} • Wiki links work in any text: paragraphs, todos, callouts${R}\n\n${D} Example: Create a network of linked notes${R}\n ${G}vertex new \"Hub Note\"${R}\n ${G}vertex edit \"Hub Note\"${R}\n${D} Then write:${R}\n${Y} # Hub Note${R}\n${Y} ${R}\n${Y} This connects to:${R}\n${Y} - [[Topic A]] — first topic${R}\n${Y} - [[Topic B]] — second topic${R}\n${Y} - [[Topic C]] — third topic${R}\n\n${C}${B} 8. TAGS — HOW THEY WORK${R}\n\n${D} Tags categorize content. They appear as purple pills in the web app.${R}\n${D} Tags are auto-created when you use them — no need to create first.${R}\n\n${C} Basic tags:${R}\n${Y} This paragraph has #work and #important tags.${R}\n${Y} - [x] Finish report #work #deadline${R}\n\n${C} Rules:${R}\n${D} • Must start with a letter: #valid, #tag123${R}\n${D} • Can contain letters, numbers, hyphens, underscores: #my-tag, #my_tag${R}\n${D} • NO spaces: #my tag is wrong → use #my-tag${R}\n${D} • Tags are case-insensitive: #Work = #work${R}\n${D} • Tags work everywhere: paragraphs, todos, headings, callouts${R}\n\n${C}${B} 9. TAG HIERARCHY — PARENT/CHILD RELATIONSHIPS${R}\n\n${D} Tags can have parent-child relationships using / separator.${R}\n${D} This creates a DAG (directed acyclic graph) of tags.${R}\n\n${Y} This is about #work/frontend${R} ${D}← creates: work → frontend${R}\n${Y} Also covers #work/backend${R} ${D}← creates: work → backend${R}\n${Y} Deep nesting: #cs/algo/sorting${R} ${D}← creates: cs → algo → sorting${R}\n\n${D} What happens:${R}\n${D} • Only the LEAF tag is applied to the block: \"frontend\" not \"work\"${R}\n${D} • Parent tags are auto-created if they don't exist${R}\n${D} • Parent→child edges are created in the tag hierarchy${R}\n${D} • Searching #work finds blocks tagged with #work AND all children${R}\n${D} (frontend, backend, etc.)${R}\n\n${D} You can also set relationships via command palette (Cmd+K in web):${R}\n${D} \"Tag Extend\" → pick parent and child tags${R}\n\n${C}${B} 10. SEARCH QUERY SYNTAX${R}\n\n ${G}vertex search \"keyword\"${R} ${D}← full-text search${R}\n ${G}vertex search \"#work\"${R} ${D}← all blocks tagged #work (+ children)${R}\n ${G}vertex search \"#work/frontend\"${R} ${D}← searches the leaf tag \"frontend\"${R}\n ${G}vertex search \"type:todo\"${R} ${D}← all todo blocks${R}\n ${G}vertex search \"type:code\"${R} ${D}← all code blocks${R}\n ${G}vertex search \"type:heading\"${R} ${D}← all headings${R}\n ${G}vertex search \"status:open\"${R} ${D}← unchecked todos${R}\n ${G}vertex search \"status:done\"${R} ${D}← checked todos${R}\n ${G}vertex search \"type:todo status:open #work\"${R} ${D}← combine filters${R}\n ${G}vertex search \"type:todo #work keyword\"${R} ${D}← all three${R}\n\n${C}${B} 11. DAILY NOTES${R}\n\n ${G}vertex daily${R} ${D}← view/create today's daily note${R}\n ${G}vertex daily --last${R} ${D}← view most recent daily (no create)${R}\n ${G}vertex today${R} ${D}← open latest daily in interactive TUI${R}\n\n${D} Daily notes are auto-titled with the date: \"April 14, 2026\"${R}\n${D} One daily note per day — calling vertex daily twice won't duplicate.${R}\n\n${C}${B} 12. INTERACTIVE MODE${R}\n\n ${G}vertex interactive \"Note Title\"${R} ${D}← open any note${R}\n ${G}vertex today${R} ${D}← shortcut for latest daily${R}\n\n${D} Controls:${R}\n${D} ↑ ↓ Move cursor between items${R}\n${D} Enter Toggle todo done/undone${R}\n${D} t Add new todo${R}\n${D} n Add new text line${R}\n${D} d Delete item at cursor${R}\n${D} e Open in $EDITOR for full editing${R}\n${D} s Save changes${R}\n${D} q Save and quit${R}\n\n${C}${B} 13. TRASH & DELETE${R}\n\n ${G}vertex delete \"Note\"${R} ${D}← soft delete (recoverable)${R}\n ${G}vertex trash${R} ${D}← list trashed notes${R}\n ${G}vertex restore \"Note\"${R} ${D}← restore from trash${R}\n ${G}vertex trash:empty${R} ${D}← permanent delete all (irreversible)${R}\n\n${D} Soft delete: note goes to trash, can be restored${R}\n${D} Hard delete (trash:empty): note + files + tags permanently removed${R}\n\n${C}${B} 14. ALL COMMANDS REFERENCE${R}\n\n ${G}vertex login${R} ${D}← authenticate (GitHub/Google/Email)${R}\n ${G}vertex logout${R} ${D}← clear session${R}\n ${G}vertex whoami${R} ${D}← show logged-in user${R}\n ${G}vertex notes${R} ${D}← list all notes${R}\n ${G}vertex new [title]${R} ${D}← create note${R}\n ${G}vertex view <title>${R} ${D}← view as markdown${R}\n ${G}vertex edit <title>${R} ${D}← edit in $EDITOR${R}\n ${G}vertex daily${R} ${D}← today's daily note${R}\n ${G}vertex daily --last${R} ${D}← latest daily note${R}\n ${G}vertex today${R} ${D}← latest daily → interactive${R}\n ${G}vertex interactive <title>${R} ${D}← interactive TUI mode${R}\n ${G}vertex capture \"text\"${R} ${D}← quick capture to inbox${R}\n ${G}vertex search <query>${R} ${D}← search notes${R}\n ${G}vertex tags${R} ${D}← list tags${R}\n ${G}vertex import <file.md>${R} ${D}← import markdown as note${R}\n ${G}vertex import <file> -t \"T\"${R} ${D}← import with title${R}\n ${G}vertex export <title>${R} ${D}← export as markdown${R}\n ${G}vertex export <title> -o file${R} ${D}← export to file${R}\n ${G}vertex export <title> --json${R} ${D}← export as JSON${R}\n ${G}vertex delete <title>${R} ${D}← soft delete${R}\n ${G}vertex restore <title>${R} ${D}← restore from trash${R}\n ${G}vertex trash${R} ${D}← list trash${R}\n ${G}vertex trash:empty${R} ${D}← empty trash permanently${R}\n ${G}vertex status${R} ${D}← storage, note count, version${R}\n ${G}vertex syntax${R} ${D}← markdown syntax reference${R}\n ${G}vertex howto${R} ${D}← this guide${R}\n ${G}vertex help${R} ${D}← command overview${R}\n\n${C}${B} 15. FULL EXAMPLE — AI CREATING A COMPLETE NOTE${R}\n${D} ──────────────────────────────────────────────────────────────${R}\n\n ${G}cat > /tmp/my-note.md << 'VERTEX'${R}\n ${Y}# Distributed Systems Study Guide${R}\n ${Y}${R}\n ${Y}Notes from studying distributed systems. #learning #cs${R}\n ${Y}${R}\n ${Y}## CAP Theorem${R}\n ${Y}${R}\n ${Y}A distributed system can only guarantee 2 of 3:${R}\n ${Y}${R}\n ${Y}- **Consistency** — every read gets the latest write${R}\n ${Y}- **Availability** — every request gets a response${R}\n ${Y}- **Partition tolerance** — system works despite network failures${R}\n ${Y}${R}\n ${Y}> [!warning]${R}\n ${Y}> In practice, P is non-negotiable. You choose between CP and AP.${R}\n ${Y}${R}\n ${Y}## Consensus Algorithm${R}\n ${Y}${R}\n ${Y}\\`\\`\\`mermaid${R}\n ${Y}sequenceDiagram${R}\n ${Y} Leader->>Follower1: AppendEntries${R}\n ${Y} Leader->>Follower2: AppendEntries${R}\n ${Y} Follower1-->>Leader: ACK${R}\n ${Y} Follower2-->>Leader: ACK${R}\n ${Y} Leader->>Leader: Commit (majority ACK)${R}\n ${Y}\\`\\`\\`${R}\n ${Y}${R}\n ${Y}## Consistency Models${R}\n ${Y}${R}\n ${Y}$$${R}\n ${Y}\\\\text{Linearizability} \\\\subset \\\\text{Sequential} \\\\subset \\\\text{Causal} \\\\subset \\\\text{Eventual}${R}\n ${Y}$$${R}\n ${Y}${R}\n ${Y}## Implementation${R}\n ${Y}${R}\n ${Y}\\`\\`\\`go${R}\n ${Y}type RaftNode struct {${R}\n ${Y} state State${R}\n ${Y} term int${R}\n ${Y} votedFor string${R}\n ${Y} log []Entry${R}\n ${Y}}${R}\n ${Y}\\`\\`\\`${R}\n ${Y}${R}\n ${Y}## Reading List${R}\n ${Y}${R}\n ${Y}- [x] Designing Data-Intensive Applications #learning/books${R}\n ${Y}- [ ] Raft paper #learning/papers${R}\n ${Y}- [ ] Paxos Made Simple #learning/papers${R}\n ${Y}${R}\n ${Y}> [!tip]${R}\n ${Y}> Start with Raft — it's simpler than Paxos and used in etcd.${R}\n ${Y}${R}\n ${Y}---${R}\n ${Y}${R}\n ${Y}Related: [[Project Roadmap]] · [[AI Research Notes]]${R}\n ${G}VERTEX${R}\n\n ${G}vertex import /tmp/my-note.md -t \"Distributed Systems Study Guide\"${R}\n\n${D} ──────────────────────────────────────────────────────────────${R}\n${D} This creates a note with: heading, bullets, callouts, mermaid,${R}\n${D} math, code, todos with scoped tags, wiki links, and a divider.${R}\n${D} Open the web app to see it rendered with rich blocks.${R}\n`);\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/import.ts"],"sourcesContent":["import { Command, Args, Flags } from \"@oclif/core\";\nimport { readFileSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport { createNote, saveNoteContent } from \"@vertex/core\";\nimport { getClient, getUserId } from \"../lib/client.js\";\nimport { markdownToTiptap } from \"@vertex/core\";\n\nexport default class Import extends Command {\n static override description = \"Import a markdown file as a note\";\n\n static override args = {\n file: Args.string({ description: \"Path to .md file\", required: true }),\n };\n\n static override flags = {\n title: Flags.string({ char: \"t\", description: \"Note title (default: filename)\" }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Import);\n const client = await getClient();\n const userId = await getUserId();\n\n const md = readFileSync(args.file, \"utf-8\");\n const title = flags.title ?? basename(args.file, \".md\");\n const tiptapJson = markdownToTiptap(md);\n\n const note = await createNote(client, { user_id: userId, title });\n await saveNoteContent(client, note.id, userId, tiptapJson);\n\n this.log(`Imported: ${title} (${note.id})`);\n }\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,SAAS,MAAM,aAAa;AACrC,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB;AAKzB,IAAqB,SAArB,MAAqB,gBAAe,QAAQ;AAAA,EAC1C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,OAAO;AAAA,IACrB,MAAM,KAAK,OAAO,EAAE,aAAa,oBAAoB,UAAU,KAAK,CAAC;AAAA,EACvE;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACtB,OAAO,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,iCAAiC,CAAC;AAAA,EAClF;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,MAAM,OAAM;AAC/C,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,SAAS,MAAM,UAAU;AAE/B,UAAM,KAAK,aAAa,KAAK,MAAM,OAAO;AAC1C,UAAM,QAAQ,MAAM,SAAS,SAAS,KAAK,MAAM,KAAK;AACtD,UAAM,aAAa,iBAAiB,EAAE;AAEtC,UAAM,OAAO,MAAM,WAAW,QAAQ,EAAE,SAAS,QAAQ,MAAM,CAAC;AAChE,UAAM,gBAAgB,QAAQ,KAAK,IAAI,QAAQ,UAAU;AAEzD,SAAK,IAAI,aAAa,KAAK,KAAK,KAAK,EAAE,GAAG;AAAA,EAC5C;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/interactive.ts"],"sourcesContent":["import { Command, Args } from \"@oclif/core\";\nimport { listNotes, getBlocksForNote, saveNoteContent, exportNoteAsMarkdown, type Block } from \"@vertex/core\";\nimport { getClient, getUserId } from \"../lib/client.js\";\nimport { markdownToTiptap } from \"@vertex/core\";\n\ninterface TuiItem {\n kind: \"text\" | \"todo\" | \"heading\" | \"code\" | \"mermaid\" | \"math\" | \"callout\" | \"divider\" | \"bullet\" | \"quote\" | \"file\" | \"image\";\n text: string;\n checked: boolean;\n level?: number;\n language?: string;\n variant?: string;\n raw?: Record<string, unknown>;\n}\n\nconst DIM = \"\\x1b[90m\";\nconst BOLD = \"\\x1b[1m\";\nconst GREEN = \"\\x1b[32m\";\nconst CYAN = \"\\x1b[36m\";\nconst YELLOW = \"\\x1b[33m\";\nconst PURPLE = \"\\x1b[35m\";\nconst R = \"\\x1b[0m\";\nconst STRIKE = \"\\x1b[9m\";\n\nfunction extractText(node: Record<string, unknown>): string {\n if (typeof node.text === \"string\") return node.text;\n const content = node.content as Array<Record<string, unknown>> | undefined;\n if (!content) return \"\";\n return content.map(extractText).join(\"\");\n}\n\nfunction blocksToItems(blocks: Block[]): TuiItem[] {\n const items: TuiItem[] = [];\n for (const b of blocks) {\n const meta = b.metadata as Record<string, unknown>;\n const tiptap = meta.tiptap as Record<string, unknown> | undefined;\n if (!tiptap) {\n if (b.content.trim()) items.push({ kind: \"text\", text: b.content, checked: false });\n continue;\n }\n\n const type = tiptap.type as string;\n const attrs = (tiptap.attrs ?? {}) as Record<string, unknown>;\n\n switch (type) {\n case \"heading\":\n items.push({ kind: \"heading\", text: extractText(tiptap), checked: false, level: (attrs.level as number) ?? 1 });\n break;\n case \"taskList\":\n for (const child of (tiptap.content ?? []) as Array<Record<string, unknown>>) {\n const ca = (child.attrs ?? {}) as Record<string, unknown>;\n items.push({ kind: \"todo\", text: extractText(child), checked: ca.checked === true });\n }\n break;\n case \"bulletList\":\n for (const child of (tiptap.content ?? []) as Array<Record<string, unknown>>) {\n items.push({ kind: \"bullet\", text: extractText(child), checked: false });\n }\n break;\n case \"orderedList\":\n (tiptap.content as Array<Record<string, unknown>> ?? []).forEach((child, idx) => {\n items.push({ kind: \"text\", text: `${idx + 1}. ${extractText(child)}`, checked: false });\n });\n break;\n case \"codeBlock\":\n items.push({ kind: \"code\", text: extractText(tiptap), checked: false, language: (attrs.language as string) ?? \"\" });\n break;\n case \"mermaidBlock\":\n items.push({ kind: \"mermaid\", text: extractText(tiptap), checked: false });\n break;\n case \"mathBlock\":\n items.push({ kind: \"math\", text: extractText(tiptap), checked: false });\n break;\n case \"calloutBlock\":\n items.push({ kind: \"callout\", text: extractText(tiptap), checked: false, variant: (attrs.variant as string) ?? \"info\" });\n break;\n case \"blockquote\":\n items.push({ kind: \"quote\", text: extractText(tiptap), checked: false });\n break;\n case \"horizontalRule\":\n items.push({ kind: \"divider\", text: \"\", checked: false });\n break;\n case \"image\":\n items.push({ kind: \"image\", text: (attrs.alt as string) || (attrs.src as string) || \"image\", checked: false });\n break;\n case \"fileBlock\":\n items.push({ kind: \"file\", text: (attrs.filename as string) || \"file\", checked: false });\n break;\n default: {\n const text = extractText(tiptap);\n if (text.trim()) items.push({ kind: \"text\", text, checked: false });\n }\n }\n }\n return items;\n}\n\nfunction renderItem(item: TuiItem, selected: boolean): string {\n const ptr = selected ? `${CYAN} ▸ ${R}` : \" \";\n\n switch (item.kind) {\n case \"heading\": {\n const hashes = \"#\".repeat(item.level ?? 1);\n return `${ptr}${BOLD}${hashes} ${item.text}${R}`;\n }\n case \"todo\": {\n const box = item.checked ? `${GREEN}[✓]${R}` : `${DIM}[ ]${R}`;\n const text = item.checked ? `${DIM}${STRIKE}${item.text}${R}` : item.text;\n return `${ptr}${box} ${text}`;\n }\n case \"bullet\":\n return `${ptr}${DIM}•${R} ${item.text}`;\n case \"code\":\n return `${ptr}${DIM}┌ code${item.language ? ` (${item.language})` : \"\"}${R}\\n${item.text.split(\"\\n\").map((l) => ` ${DIM}│${R} ${l}`).join(\"\\n\")}\\n ${DIM}└──${R}`;\n case \"mermaid\":\n return `${ptr}${PURPLE}┌ mermaid${R}\\n${item.text.split(\"\\n\").map((l) => ` ${PURPLE}│${R} ${DIM}${l}${R}`).join(\"\\n\")}\\n ${PURPLE}└──${R}`;\n case \"math\":\n return `${ptr}${YELLOW}┌ math${R}\\n${item.text.split(\"\\n\").map((l) => ` ${YELLOW}│${R} ${l}`).join(\"\\n\")}\\n ${YELLOW}└──${R}`;\n case \"callout\":\n return `${ptr}${CYAN}[${(item.variant ?? \"info\").toUpperCase()}]${R} ${item.text}`;\n case \"quote\":\n return `${ptr}${DIM}▎${R} ${DIM}${item.text}${R}`;\n case \"divider\":\n return ` ${DIM}────────────────────────────${R}`;\n case \"image\":\n return `${ptr}${DIM}[image: ${item.text}]${R}`;\n case \"file\":\n return `${ptr}${DIM}[file: ${item.text}]${R}`;\n default:\n return `${ptr}${item.text}`;\n }\n}\n\nfunction render(items: TuiItem[], cursor: number, mode: string, inputBuffer: string, noteTitle: string): void {\n process.stdout.write(\"\\x1bc\");\n process.stdout.write(`${BOLD} ${noteTitle}${R}\\n`);\n process.stdout.write(`${DIM} ─────────────────────────────────────${R}\\n\\n`);\n\n for (let i = 0; i < items.length; i++) {\n process.stdout.write(renderItem(items[i], i === cursor) + \"\\n\");\n }\n\n if (items.length === 0) {\n process.stdout.write(` ${DIM}(empty)${R}\\n`);\n }\n\n process.stdout.write(`\\n${DIM} ─────────────────────────────────────${R}\\n`);\n\n if (mode === \"input-todo\") {\n process.stdout.write(` ${YELLOW}New todo:${R} ${inputBuffer}\\x1b[7m \\x1b[0m\\n`);\n } else if (mode === \"input-text\") {\n process.stdout.write(` ${YELLOW}New text:${R} ${inputBuffer}\\x1b[7m \\x1b[0m\\n`);\n } else {\n process.stdout.write(` ${DIM}↑↓ move Enter toggle t todo n text d delete e edit in $EDITOR s save q quit${R}\\n`);\n }\n}\n\nexport default class Interactive extends Command {\n static override description = \"Interactive note editor with todo toggling\";\n\n static override args = {\n title: Args.string({ description: \"Note title (partial match)\", required: true }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(Interactive);\n const client = await getClient();\n const userId = await getUserId();\n const notes = await listNotes(client, { user_id: userId });\n const query = args.title.toLowerCase();\n const match = notes.find((n) => !n.deleted_at && n.title.toLowerCase().includes(query));\n\n if (!match) {\n this.error(`No note matching \"${args.title}\"`);\n }\n\n const blocks = await getBlocksForNote(client, match.id);\n let items = blocksToItems(blocks);\n let cursor = 0;\n let dirty = false;\n let mode = \"normal\";\n let inputBuffer = \"\";\n\n process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.setEncoding(\"utf8\");\n\n render(items, cursor, mode, inputBuffer, match.title);\n\n const cleanup = () => {\n process.stdin.setRawMode(false);\n process.stdout.write(\"\\x1bc\");\n };\n\n const save = async () => {\n const md = items.map((item) => {\n switch (item.kind) {\n case \"heading\": return `${\"#\".repeat(item.level ?? 1)} ${item.text}`;\n case \"todo\": return `- [${item.checked ? \"x\" : \" \"}] ${item.text}`;\n case \"bullet\": return `- ${item.text}`;\n case \"code\": return `\\`\\`\\`${item.language ?? \"\"}\\n${item.text}\\n\\`\\`\\``;\n case \"mermaid\": return `\\`\\`\\`mermaid\\n${item.text}\\n\\`\\`\\``;\n case \"math\": return `$$\\n${item.text}\\n$$`;\n case \"callout\": return `> [!${item.variant ?? \"info\"}]\\n> ${item.text}`;\n case \"quote\": return `> ${item.text}`;\n case \"divider\": return \"---\";\n case \"image\": return `![](${item.text})`;\n case \"file\": return `> [!file]\\n> ${item.text}`;\n default: return item.text;\n }\n }).join(\"\\n\\n\");\n\n const tiptap = markdownToTiptap(md);\n await saveNoteContent(client, match.id, userId, tiptap);\n dirty = false;\n };\n\n const openEditor = async () => {\n cleanup();\n const { tmpdir } = await import(\"node:os\");\n const { join } = await import(\"node:path\");\n const { writeFileSync, readFileSync } = await import(\"node:fs\");\n const { execSync } = await import(\"node:child_process\");\n\n const md = await exportNoteAsMarkdown(client, match.id);\n const tmpFile = join(tmpdir(), `vertex-${match.id}.md`);\n writeFileSync(tmpFile, md, \"utf-8\");\n\n const editor = process.env.EDITOR || process.env.VISUAL || \"vim\";\n try { execSync(`${editor} \"${tmpFile}\"`, { stdio: \"inherit\" }); } catch { /* */ }\n\n const edited = readFileSync(tmpFile, \"utf-8\");\n if (edited !== md) {\n const tiptap = markdownToTiptap(edited);\n await saveNoteContent(client, match.id, userId, tiptap);\n }\n\n const newBlocks = await getBlocksForNote(client, match.id);\n items = blocksToItems(newBlocks);\n cursor = Math.min(cursor, Math.max(0, items.length - 1));\n dirty = false;\n\n process.stdin.setRawMode(true);\n process.stdin.resume();\n render(items, cursor, mode, inputBuffer, match.title);\n };\n\n process.stdin.on(\"data\", async (key: string) => {\n if (mode === \"input-todo\" || mode === \"input-text\") {\n if (key === \"\\r\" || key === \"\\n\") {\n if (inputBuffer.trim()) {\n const newItem: TuiItem = mode === \"input-todo\"\n ? { kind: \"todo\", text: inputBuffer.trim(), checked: false }\n : { kind: \"text\", text: inputBuffer.trim(), checked: false };\n items.splice(cursor + 1, 0, newItem);\n cursor = Math.min(cursor + 1, items.length - 1);\n dirty = true;\n }\n mode = \"normal\";\n inputBuffer = \"\";\n } else if (key === \"\\x1b\") {\n mode = \"normal\";\n inputBuffer = \"\";\n } else if (key === \"\\x7f\") {\n inputBuffer = inputBuffer.slice(0, -1);\n } else if (key >= \" \") {\n inputBuffer += key;\n }\n render(items, cursor, mode, inputBuffer, match.title);\n return;\n }\n\n if (key === \"\\x1b[A\") {\n cursor = Math.max(0, cursor - 1);\n } else if (key === \"\\x1b[B\") {\n cursor = Math.min(items.length - 1, cursor + 1);\n } else if (key === \"\\r\" || key === \"\\n\") {\n if (items[cursor]?.kind === \"todo\") {\n items[cursor].checked = !items[cursor].checked;\n dirty = true;\n }\n } else if (key === \"t\") {\n mode = \"input-todo\";\n inputBuffer = \"\";\n } else if (key === \"n\") {\n mode = \"input-text\";\n inputBuffer = \"\";\n } else if (key === \"d\") {\n if (items.length > 0) {\n items.splice(cursor, 1);\n cursor = Math.min(cursor, items.length - 1);\n dirty = true;\n }\n } else if (key === \"e\") {\n if (dirty) await save();\n await openEditor();\n return;\n } else if (key === \"s\") {\n await save();\n render(items, cursor, mode, inputBuffer, match.title);\n process.stdout.write(` ${GREEN}Saved!${R}\\n`);\n return;\n } else if (key === \"q\" || key === \"\\x03\") {\n if (dirty) await save();\n cleanup();\n this.log(dirty ? `Saved: ${match.title}` : \"No changes.\");\n process.exit(0);\n }\n\n render(items, cursor, mode, inputBuffer, match.title);\n });\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/login.ts"],"sourcesContent":["import { Command } from \"@oclif/core\";\nimport { createServer } from \"node:http\";\nimport { createInterface } from \"node:readline\";\nimport { createSupabaseClient } from \"@vertex/core\";\nimport { loadConfig, saveConfig } from \"../lib/config.js\";\n\nexport default class Login extends Command {\n static override description = \"Log in to Vertex\";\n\n async run(): Promise<void> {\n const config = loadConfig();\n\n this.log(\"\\n How would you like to log in?\\n\");\n this.log(\" 1) GitHub\");\n this.log(\" 2) Google\");\n this.log(\" 3) Email & Password\\n\");\n\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const choice = await new Promise<string>((resolve) => {\n rl.question(\" Choice (1/2/3): \", (ans) => { rl.close(); resolve(ans.trim()); });\n });\n\n if (choice === \"3\") {\n await this.emailLogin(config);\n return;\n }\n\n const provider = choice === \"2\" ? \"google\" : \"github\";\n await this.oauthLogin(config, provider);\n }\n\n private async emailLogin(config: ReturnType<typeof loadConfig>): Promise<void> {\n const rl1 = createInterface({ input: process.stdin, output: process.stdout });\n const email = await new Promise<string>((resolve) => {\n rl1.question(\" Email: \", (ans) => { rl1.close(); resolve(ans.trim()); });\n });\n\n const rl2 = createInterface({ input: process.stdin, output: process.stdout });\n const password = await new Promise<string>((resolve) => {\n rl2.question(\" Password: \", (ans) => { rl2.close(); resolve(ans.trim()); });\n });\n\n const rl3 = createInterface({ input: process.stdin, output: process.stdout });\n const isSignup = await new Promise<string>((resolve) => {\n rl3.question(\" Sign in or sign up? (in/up): \", (ans) => { rl3.close(); resolve(ans.trim().toLowerCase()); });\n });\n\n const client = createSupabaseClient(config.supabaseUrl, config.supabaseAnonKey);\n\n if (isSignup === \"up\") {\n const { error } = await client.auth.signUp({ email, password });\n if (error) {\n this.error(`Sign up failed: ${error.message}`);\n }\n this.log(\" Check your email to confirm your account, then run: vertex login\");\n process.exit(0);\n }\n\n const { data, error } = await client.auth.signInWithPassword({ email, password });\n if (error) {\n this.error(`Login failed: ${error.message}`);\n }\n\n if (data.session) {\n saveConfig({\n accessToken: data.session.access_token,\n refreshToken: data.session.refresh_token,\n userId: data.session.user.id,\n email: data.session.user.email,\n });\n this.log(` Logged in as ${data.session.user.email}`);\n }\n process.exit(0);\n }\n\n private async oauthLogin(config: ReturnType<typeof loadConfig>, provider: \"github\" | \"google\"): Promise<void> {\n const port = 54321;\n const redirectUrl = `http://localhost:${port}/callback`;\n\n this.log(` Opening browser for ${provider} login...`);\n\n const tokenPromise = new Promise<{ access_token: string; refresh_token: string }>((resolve, reject) => {\n const server = createServer((req, res) => {\n const url = new URL(req.url ?? \"/\", `http://localhost:${port}`);\n\n if (url.pathname === \"/callback\") {\n const accessToken = url.searchParams.get(\"access_token\");\n const refreshToken = url.searchParams.get(\"refresh_token\");\n\n if (accessToken && refreshToken) {\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(\"<h2 style='font-family:sans-serif;text-align:center;margin-top:40vh'>Logged in! You can close this tab.</h2>\");\n server.close();\n resolve({ access_token: accessToken, refresh_token: refreshToken });\n return;\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(`\n <html><body>\n <script>\n const hash = window.location.hash.substring(1);\n const params = new URLSearchParams(hash);\n const at = params.get(\"access_token\");\n const rt = params.get(\"refresh_token\");\n if (at && rt) {\n window.location.href = \"/callback?access_token=\" + encodeURIComponent(at) + \"&refresh_token=\" + encodeURIComponent(rt);\n } else {\n document.body.innerHTML = \"<h2 style='font-family:sans-serif;text-align:center;margin-top:40vh'>Login failed. Try again.</h2>\";\n }\n </script>\n <h2 style=\"font-family:sans-serif;text-align:center;margin-top:40vh\">Completing login...</h2>\n </body></html>\n `);\n return;\n }\n\n res.writeHead(404);\n res.end(\"Not found\");\n });\n\n server.listen(port, () => {\n const client = createSupabaseClient(config.supabaseUrl, config.supabaseAnonKey);\n client.auth.signInWithOAuth({\n provider,\n options: { redirectTo: redirectUrl, skipBrowserRedirect: false },\n }).then(({ data }) => {\n if (data.url) {\n console.log(`\\n If browser doesn't open, visit:\\n ${data.url}\\n`);\n import(\"node:child_process\").then(({ exec }) => {\n const cmd = process.platform === \"darwin\" ? \"open\"\n : process.platform === \"win32\" ? 'start \"\"'\n : \"xdg-open\";\n exec(`${cmd} \"${data.url}\"`);\n });\n }\n });\n });\n\n setTimeout(() => {\n server.close();\n reject(new Error(\"Login timed out after 120 seconds\"));\n }, 120_000);\n });\n\n try {\n const tokens = await tokenPromise;\n\n const client = createSupabaseClient(config.supabaseUrl, config.supabaseAnonKey);\n const { data } = await client.auth.setSession({\n access_token: tokens.access_token,\n refresh_token: tokens.refresh_token,\n });\n\n saveConfig({\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n userId: data.session?.user.id,\n email: data.session?.user.email,\n });\n\n this.log(` Logged in as ${data.session?.user.email ?? \"unknown\"}`);\n process.exit(0);\n } catch (err) {\n this.error(`Login failed: ${err instanceof Error ? err.message : err}`);\n }\n }\n}\n"],"mappings":"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","names":["error"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/logout.ts"],"sourcesContent":["import { Command } from \"@oclif/core\";\nimport { clearConfig } from \"../lib/config.js\";\n\nexport default class Logout extends Command {\n static override description = \"Log out of Vertex\";\n\n async run(): Promise<void> {\n clearConfig();\n this.log(\"Logged out.\");\n }\n}\n"],"mappings":";;;;;AAAA,SAAS,eAAe;AAGxB,IAAqB,SAArB,cAAoC,QAAQ;AAAA,EAC1C,OAAgB,cAAc;AAAA,EAE9B,MAAM,MAAqB;AACzB,gBAAY;AACZ,SAAK,IAAI,aAAa;AAAA,EACxB;AACF;","names":[]}