@bendyline/docblocks 1.1.2 → 2.0.0

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 (270) hide show
  1. package/README.md +76 -11
  2. package/dist/chunk-2D7Y4IR3.js +1293 -0
  3. package/dist/chunk-2D7Y4IR3.js.map +1 -0
  4. package/dist/chunk-5MYAICRE.js +957 -0
  5. package/dist/chunk-5MYAICRE.js.map +1 -0
  6. package/dist/chunk-75UUF6C4.js +802 -0
  7. package/dist/chunk-75UUF6C4.js.map +1 -0
  8. package/dist/chunk-AEHCVWU5.js +25 -0
  9. package/dist/chunk-AEHCVWU5.js.map +1 -0
  10. package/dist/chunk-AYZ4HN5M.js +20 -0
  11. package/dist/chunk-AYZ4HN5M.js.map +1 -0
  12. package/dist/chunk-EGNDADXB.js +111 -0
  13. package/dist/chunk-EGNDADXB.js.map +1 -0
  14. package/dist/chunk-EZKJZUNJ.js +13 -0
  15. package/dist/chunk-EZKJZUNJ.js.map +1 -0
  16. package/dist/chunk-FNW556FN.js +75 -0
  17. package/dist/chunk-FNW556FN.js.map +1 -0
  18. package/dist/chunk-GCPBEMMH.js +563 -0
  19. package/dist/chunk-GCPBEMMH.js.map +1 -0
  20. package/dist/chunk-J32GU3F3.js +1664 -0
  21. package/dist/chunk-J32GU3F3.js.map +1 -0
  22. package/dist/chunk-PGR7LK6D.js +1062 -0
  23. package/dist/chunk-PGR7LK6D.js.map +1 -0
  24. package/dist/chunk-RQJRQF46.js +787 -0
  25. package/dist/chunk-RQJRQF46.js.map +1 -0
  26. package/dist/{chunk-ME76RUMR.js → chunk-RVQHY3XU.js} +15 -1
  27. package/dist/chunk-RVQHY3XU.js.map +1 -0
  28. package/dist/chunk-SI2LU2RP.js +224 -0
  29. package/dist/chunk-SI2LU2RP.js.map +1 -0
  30. package/dist/chunk-W5UUUII5.js +142 -0
  31. package/dist/chunk-W5UUUII5.js.map +1 -0
  32. package/dist/document/document-session.d.ts +127 -0
  33. package/dist/document/document-session.d.ts.map +1 -0
  34. package/dist/document/document-session.js +749 -0
  35. package/dist/document/document-session.js.map +1 -0
  36. package/dist/document/filesystem-target.d.ts +17 -0
  37. package/dist/document/filesystem-target.d.ts.map +1 -0
  38. package/dist/document/filesystem-target.js +70 -0
  39. package/dist/document/filesystem-target.js.map +1 -0
  40. package/dist/document/index.d.ts +6 -0
  41. package/dist/document/index.d.ts.map +1 -0
  42. package/dist/document/index.js +4 -0
  43. package/dist/document/index.js.map +1 -0
  44. package/dist/document/recovery-journal.d.ts +125 -0
  45. package/dist/document/recovery-journal.d.ts.map +1 -0
  46. package/dist/document/recovery-journal.js +385 -0
  47. package/dist/document/recovery-journal.js.map +1 -0
  48. package/dist/document/types.d.ts +89 -0
  49. package/dist/document/types.d.ts.map +1 -0
  50. package/dist/document/types.js +9 -0
  51. package/dist/document/types.js.map +1 -0
  52. package/dist/filesystem/commit-lock.d.ts +3 -0
  53. package/dist/filesystem/commit-lock.d.ts.map +1 -0
  54. package/dist/filesystem/commit-lock.js +20 -0
  55. package/dist/filesystem/commit-lock.js.map +1 -0
  56. package/dist/filesystem/dbk-workspace.d.ts +34 -0
  57. package/dist/filesystem/dbk-workspace.d.ts.map +1 -0
  58. package/dist/filesystem/dbk-workspace.js +85 -0
  59. package/dist/filesystem/dbk-workspace.js.map +1 -0
  60. package/dist/filesystem/electron-provider-v2.d.ts +36 -0
  61. package/dist/filesystem/electron-provider-v2.d.ts.map +1 -0
  62. package/dist/filesystem/electron-provider-v2.js +503 -0
  63. package/dist/filesystem/electron-provider-v2.js.map +1 -0
  64. package/dist/filesystem/electron-provider.d.ts +6 -3
  65. package/dist/filesystem/electron-provider.d.ts.map +1 -1
  66. package/dist/filesystem/electron-provider.js +18 -13
  67. package/dist/filesystem/electron-provider.js.map +1 -1
  68. package/dist/filesystem/electron.d.ts +4 -0
  69. package/dist/filesystem/electron.d.ts.map +1 -0
  70. package/dist/filesystem/electron.js +4 -0
  71. package/dist/filesystem/electron.js.map +1 -0
  72. package/dist/filesystem/filesystem-content-container.d.ts +1 -1
  73. package/dist/filesystem/filesystem-content-container.d.ts.map +1 -1
  74. package/dist/filesystem/filesystem-content-container.js +50 -13
  75. package/dist/filesystem/filesystem-content-container.js.map +1 -1
  76. package/dist/filesystem/fs-error.d.ts +46 -0
  77. package/dist/filesystem/fs-error.d.ts.map +1 -0
  78. package/dist/filesystem/fs-error.js +170 -0
  79. package/dist/filesystem/fs-error.js.map +1 -0
  80. package/dist/filesystem/index.d.ts +15 -1
  81. package/dist/filesystem/index.d.ts.map +1 -1
  82. package/dist/filesystem/index.js +13 -0
  83. package/dist/filesystem/index.js.map +1 -1
  84. package/dist/filesystem/indexeddb-content-container.d.ts +3 -1
  85. package/dist/filesystem/indexeddb-content-container.d.ts.map +1 -1
  86. package/dist/filesystem/indexeddb-content-container.js +18 -11
  87. package/dist/filesystem/indexeddb-content-container.js.map +1 -1
  88. package/dist/filesystem/indexeddb-provider-v2.d.ts +96 -0
  89. package/dist/filesystem/indexeddb-provider-v2.d.ts.map +1 -0
  90. package/dist/filesystem/indexeddb-provider-v2.js +1241 -0
  91. package/dist/filesystem/indexeddb-provider-v2.js.map +1 -0
  92. package/dist/filesystem/indexeddb-provider.d.ts +21 -14
  93. package/dist/filesystem/indexeddb-provider.d.ts.map +1 -1
  94. package/dist/filesystem/indexeddb-provider.js +111 -261
  95. package/dist/filesystem/indexeddb-provider.js.map +1 -1
  96. package/dist/filesystem/indexeddb-store.d.ts +34 -0
  97. package/dist/filesystem/indexeddb-store.d.ts.map +1 -0
  98. package/dist/filesystem/indexeddb-store.js +165 -0
  99. package/dist/filesystem/indexeddb-store.js.map +1 -0
  100. package/dist/filesystem/indexeddb.d.ts +5 -0
  101. package/dist/filesystem/indexeddb.d.ts.map +1 -0
  102. package/dist/filesystem/indexeddb.js +5 -0
  103. package/dist/filesystem/indexeddb.js.map +1 -0
  104. package/dist/filesystem/legacy-v2-adapter.d.ts +62 -0
  105. package/dist/filesystem/legacy-v2-adapter.d.ts.map +1 -0
  106. package/dist/filesystem/legacy-v2-adapter.js +499 -0
  107. package/dist/filesystem/legacy-v2-adapter.js.map +1 -0
  108. package/dist/filesystem/memory-provider-v2.d.ts +92 -0
  109. package/dist/filesystem/memory-provider-v2.d.ts.map +1 -0
  110. package/dist/filesystem/memory-provider-v2.js +615 -0
  111. package/dist/filesystem/memory-provider-v2.js.map +1 -0
  112. package/dist/filesystem/memory-provider.d.ts +54 -0
  113. package/dist/filesystem/memory-provider.d.ts.map +1 -0
  114. package/dist/filesystem/memory-provider.js +132 -0
  115. package/dist/filesystem/memory-provider.js.map +1 -0
  116. package/dist/filesystem/memory.d.ts +4 -0
  117. package/dist/filesystem/memory.d.ts.map +1 -0
  118. package/dist/filesystem/memory.js +4 -0
  119. package/dist/filesystem/memory.js.map +1 -0
  120. package/dist/filesystem/move-entry.d.ts +9 -0
  121. package/dist/filesystem/move-entry.d.ts.map +1 -0
  122. package/dist/filesystem/move-entry.js +103 -0
  123. package/dist/filesystem/move-entry.js.map +1 -0
  124. package/dist/filesystem/move-error.d.ts +53 -0
  125. package/dist/filesystem/move-error.d.ts.map +1 -0
  126. package/dist/filesystem/move-error.js +99 -0
  127. package/dist/filesystem/move-error.js.map +1 -0
  128. package/dist/filesystem/native-provider-v2.d.ts +75 -0
  129. package/dist/filesystem/native-provider-v2.d.ts.map +1 -0
  130. package/dist/filesystem/native-provider-v2.js +849 -0
  131. package/dist/filesystem/native-provider-v2.js.map +1 -0
  132. package/dist/filesystem/native-provider.d.ts +9 -1
  133. package/dist/filesystem/native-provider.d.ts.map +1 -1
  134. package/dist/filesystem/native-provider.js +172 -37
  135. package/dist/filesystem/native-provider.js.map +1 -1
  136. package/dist/filesystem/native.d.ts +4 -0
  137. package/dist/filesystem/native.d.ts.map +1 -0
  138. package/dist/filesystem/native.js +4 -0
  139. package/dist/filesystem/native.js.map +1 -0
  140. package/dist/filesystem/types.d.ts +37 -4
  141. package/dist/filesystem/types.d.ts.map +1 -1
  142. package/dist/filesystem/types.js +11 -3
  143. package/dist/filesystem/types.js.map +1 -1
  144. package/dist/filesystem/v2.d.ts +172 -0
  145. package/dist/filesystem/v2.d.ts.map +1 -0
  146. package/dist/filesystem/v2.js +16 -0
  147. package/dist/filesystem/v2.js.map +1 -0
  148. package/dist/filesystem/workspace-path.d.ts +21 -0
  149. package/dist/filesystem/workspace-path.d.ts.map +1 -0
  150. package/dist/filesystem/workspace-path.js +80 -0
  151. package/dist/filesystem/workspace-path.js.map +1 -0
  152. package/dist/host/filesystem-v2.d.ts +45 -0
  153. package/dist/host/filesystem-v2.d.ts.map +1 -0
  154. package/dist/host/filesystem-v2.js +13 -0
  155. package/dist/host/filesystem-v2.js.map +1 -0
  156. package/dist/host/git.d.ts +200 -0
  157. package/dist/host/git.d.ts.map +1 -0
  158. package/dist/host/git.js +15 -0
  159. package/dist/host/git.js.map +1 -0
  160. package/dist/host/index.d.ts +4 -1
  161. package/dist/host/index.d.ts.map +1 -1
  162. package/dist/host/index.js +2 -0
  163. package/dist/host/index.js.map +1 -1
  164. package/dist/host/types.d.ts +114 -31
  165. package/dist/host/types.d.ts.map +1 -1
  166. package/dist/host/wire-policy.d.ts +22 -0
  167. package/dist/host/wire-policy.d.ts.map +1 -0
  168. package/dist/host/wire-policy.js +92 -0
  169. package/dist/host/wire-policy.js.map +1 -0
  170. package/dist/index.d.ts +2 -1
  171. package/dist/index.d.ts.map +1 -1
  172. package/dist/index.js +2 -1
  173. package/dist/index.js.map +1 -1
  174. package/dist/mcp/index.d.ts +4 -0
  175. package/dist/mcp/index.d.ts.map +1 -0
  176. package/dist/mcp/index.js +4 -0
  177. package/dist/mcp/index.js.map +1 -0
  178. package/dist/mcp/types.d.ts +466 -0
  179. package/dist/mcp/types.d.ts.map +1 -0
  180. package/dist/mcp/types.js +25 -0
  181. package/dist/mcp/types.js.map +1 -0
  182. package/dist/mcp/wire.d.ts +29 -0
  183. package/dist/mcp/wire.d.ts.map +1 -0
  184. package/dist/mcp/wire.js +1046 -0
  185. package/dist/mcp/wire.js.map +1 -0
  186. package/dist/mcp/zod.d.ts +5763 -0
  187. package/dist/mcp/zod.d.ts.map +1 -0
  188. package/dist/mcp/zod.js +908 -0
  189. package/dist/mcp/zod.js.map +1 -0
  190. package/dist/types-CX893hgH.d.ts +468 -0
  191. package/dist/types-CsX6EN2t.d.ts +301 -0
  192. package/dist/types-eOlt9J7n.d.ts +478 -0
  193. package/dist/vscode/index.d.ts +3 -0
  194. package/dist/vscode/index.d.ts.map +1 -0
  195. package/dist/vscode/index.js +3 -0
  196. package/dist/vscode/index.js.map +1 -0
  197. package/dist/vscode/messages.d.ts +204 -0
  198. package/dist/vscode/messages.d.ts.map +1 -0
  199. package/dist/vscode/messages.js +494 -0
  200. package/dist/vscode/messages.js.map +1 -0
  201. package/dist/workspace/index.d.ts +3 -2
  202. package/dist/workspace/index.d.ts.map +1 -1
  203. package/dist/workspace/index.js +2 -1
  204. package/dist/workspace/index.js.map +1 -1
  205. package/dist/workspace/reconcile-electron.d.ts +19 -0
  206. package/dist/workspace/reconcile-electron.d.ts.map +1 -0
  207. package/dist/workspace/reconcile-electron.js +42 -0
  208. package/dist/workspace/reconcile-electron.js.map +1 -0
  209. package/dist/workspace/types.d.ts +41 -1
  210. package/dist/workspace/types.d.ts.map +1 -1
  211. package/dist/workspace/types.js +0 -4
  212. package/dist/workspace/types.js.map +1 -1
  213. package/dist/workspace/workspace-manager.d.ts +17 -5
  214. package/dist/workspace/workspace-manager.d.ts.map +1 -1
  215. package/dist/workspace/workspace-manager.js +55 -11
  216. package/dist/workspace/workspace-manager.js.map +1 -1
  217. package/dist/workspace-path-CWVrcuPL.d.ts +21 -0
  218. package/package.json +43 -2
  219. package/src/document/document-session.ts +834 -0
  220. package/src/document/filesystem-target.ts +109 -0
  221. package/src/document/index.ts +41 -0
  222. package/src/document/recovery-journal.ts +536 -0
  223. package/src/document/types.ts +116 -0
  224. package/src/filesystem/commit-lock.ts +29 -0
  225. package/src/filesystem/dbk-workspace.ts +135 -0
  226. package/src/filesystem/electron-provider-v2.ts +630 -0
  227. package/src/filesystem/electron-provider.ts +25 -14
  228. package/src/filesystem/electron.ts +3 -0
  229. package/src/filesystem/filesystem-content-container.ts +53 -15
  230. package/src/filesystem/fs-error.ts +234 -0
  231. package/src/filesystem/index.ts +119 -0
  232. package/src/filesystem/indexeddb-content-container.ts +20 -12
  233. package/src/filesystem/indexeddb-provider-v2.ts +1740 -0
  234. package/src/filesystem/indexeddb-provider.ts +126 -300
  235. package/src/filesystem/indexeddb-store.ts +207 -0
  236. package/src/filesystem/indexeddb.ts +12 -0
  237. package/src/filesystem/legacy-v2-adapter.ts +779 -0
  238. package/src/filesystem/memory-provider-v2.ts +896 -0
  239. package/src/filesystem/memory-provider.ts +180 -0
  240. package/src/filesystem/memory.ts +15 -0
  241. package/src/filesystem/move-entry.ts +142 -0
  242. package/src/filesystem/move-error.ts +159 -0
  243. package/src/filesystem/native-provider-v2.ts +1165 -0
  244. package/src/filesystem/native-provider.ts +194 -41
  245. package/src/filesystem/native.ts +16 -0
  246. package/src/filesystem/types.ts +49 -4
  247. package/src/filesystem/v2.ts +231 -0
  248. package/src/filesystem/workspace-path.ts +92 -0
  249. package/src/host/filesystem-v2.ts +104 -0
  250. package/src/host/git.ts +246 -0
  251. package/src/host/index.ts +46 -0
  252. package/src/host/types.ts +155 -34
  253. package/src/host/wire-policy.ts +103 -0
  254. package/src/index.ts +2 -1
  255. package/src/mcp/index.ts +3 -0
  256. package/src/mcp/types.ts +594 -0
  257. package/src/mcp/wire.ts +1280 -0
  258. package/src/mcp/zod.ts +1000 -0
  259. package/src/vscode/index.ts +2 -0
  260. package/src/vscode/messages.ts +704 -0
  261. package/src/workspace/index.ts +8 -1
  262. package/src/workspace/reconcile-electron.ts +65 -0
  263. package/src/workspace/types.ts +39 -1
  264. package/src/workspace/workspace-manager.ts +71 -10
  265. package/dist/chunk-GUNM43XZ.js +0 -63
  266. package/dist/chunk-GUNM43XZ.js.map +0 -1
  267. package/dist/chunk-IM7LCQJ6.js +0 -850
  268. package/dist/chunk-IM7LCQJ6.js.map +0 -1
  269. package/dist/chunk-ME76RUMR.js.map +0 -1
  270. package/dist/index-pgBHBQ9G.d.ts +0 -213
package/src/host/index.ts CHANGED
@@ -7,17 +7,63 @@
7
7
  export type {
8
8
  DocBlocksHostAPI,
9
9
  DocBlocksHostFsAPI,
10
+ DocBlocksHostExternalAPI,
10
11
  DocBlocksHostWorkspacesAPI,
11
12
  DocBlocksHostShellAPI,
13
+ DocBlocksHostExportAPI,
12
14
  DocBlocksHostFfmpegAPI,
13
15
  DocBlocksHostUpdaterAPI,
16
+ DocBlocksHostLifecycleAPI,
14
17
  ElectronWorkspaceInfo,
18
+ ExternalBinaryCommitResult,
19
+ HostCloseReason,
15
20
  HostEnvironment,
21
+ HostExportTargetGrant,
22
+ HostPrepareCloseRequest,
23
+ HostPrepareCloseResult,
16
24
  MenuCommand,
17
25
  OpenRequest,
26
+ UpdateInstallResult,
18
27
  UpdaterStatus,
19
28
  } from './types.js';
20
29
 
30
+ export type {
31
+ DocBlocksHostGitAPI,
32
+ GitBranchInfo,
33
+ GitCapabilities,
34
+ GitCloneHandle,
35
+ GitCloneProgress,
36
+ GitError,
37
+ GitErrorCode,
38
+ GitFileAtRevision,
39
+ GitFileChange,
40
+ GitFileStatusCode,
41
+ GitLogEntry,
42
+ GitLogOptions,
43
+ GitRemoteInfo,
44
+ GitRepoDetection,
45
+ GitResult,
46
+ GitRevision,
47
+ GitStatus,
48
+ } from './git.js';
49
+
50
+ export {
51
+ ELECTRON_FILE_SYSTEM_V2_CAPABILITIES,
52
+ type DocBlocksHostFsV2API,
53
+ type HostFileSystemV2OpenRequest,
54
+ type HostFileSystemV2Result,
55
+ type HostFileSystemV2WatchMessage,
56
+ } from './filesystem-v2.js';
57
+
58
+ export {
59
+ HOST_WIRE_LIMITS,
60
+ isBoundedBytePayload,
61
+ isBoundedString,
62
+ isTrustedRendererUrl,
63
+ parseExternalHttpUrl,
64
+ parseOpenRequest,
65
+ } from './wire-policy.js';
66
+
21
67
  import type { DocBlocksHostAPI } from './types.js';
22
68
 
23
69
  /** True when running inside the Electron desktop shell. */
package/src/host/types.ts CHANGED
@@ -7,39 +7,50 @@
7
7
  * this shape; the React renderer calls it through `window.docBlocksHost`.
8
8
  */
9
9
 
10
- import type { FileSystemEntry, FileMeta } from '../filesystem/types.js';
10
+ import type { FileCommitResult, FileSystemEntry, FileMeta } from '../filesystem/types.js';
11
+ import type { DocBlocksHostFsV2API } from './filesystem-v2.js';
12
+ import type { DocBlocksHostGitAPI } from './git.js';
11
13
 
12
- /** Filesystem operations scoped to a registered absolute root path. */
14
+ /** Filesystem operations scoped to a main-owned registered workspace id. */
13
15
  export interface DocBlocksHostFsAPI {
14
- readFile(rootPath: string, path: string): Promise<string | null>;
15
- writeFile(rootPath: string, path: string, content: string): Promise<void>;
16
- delete(rootPath: string, path: string): Promise<void>;
17
- rename(rootPath: string, oldPath: string, newPath: string): Promise<void>;
18
- readDirectory(rootPath: string, path: string): Promise<FileSystemEntry[]>;
19
- exists(rootPath: string, path: string): Promise<boolean>;
20
- createDirectory(rootPath: string, path: string): Promise<void>;
21
- stat(rootPath: string, path: string): Promise<FileMeta | null>;
22
- readBinary(rootPath: string, path: string): Promise<ArrayBuffer | null>;
23
- writeBinary(rootPath: string, path: string, data: ArrayBuffer | Uint8Array): Promise<void>;
16
+ readFile(workspaceId: string, path: string): Promise<string | null>;
17
+ writeFile(workspaceId: string, path: string, content: string): Promise<void>;
18
+ commitFile(
19
+ workspaceId: string,
20
+ path: string,
21
+ content: string,
22
+ expectedContent: string | null,
23
+ ): Promise<FileCommitResult>;
24
+ delete(workspaceId: string, path: string): Promise<void>;
25
+ rename(workspaceId: string, oldPath: string, newPath: string): Promise<void>;
26
+ readDirectory(workspaceId: string, path: string): Promise<FileSystemEntry[]>;
27
+ exists(workspaceId: string, path: string): Promise<boolean>;
28
+ createDirectory(workspaceId: string, path: string): Promise<void>;
29
+ stat(workspaceId: string, path: string): Promise<FileMeta | null>;
30
+ readBinary(workspaceId: string, path: string): Promise<ArrayBuffer | null>;
31
+ writeBinary(workspaceId: string, path: string, data: ArrayBuffer | Uint8Array): Promise<void>;
24
32
  /**
25
33
  * Subscribe to change notifications for a watched root. Returns an
26
34
  * unsubscribe function. The main process uses chokidar under the hood.
27
35
  */
28
- watch(rootPath: string, onChange: (path: string) => void): () => void;
36
+ watch(workspaceId: string, onChange: (path: string) => void): () => void;
29
37
  }
30
38
 
31
39
  /** Descriptor returned for an Electron-managed workspace (backed by a folder). */
32
40
  export interface ElectronWorkspaceInfo {
33
41
  id: string;
34
42
  name: string;
43
+ /** Display/persistence metadata only. Privileged host calls accept `id`, never this path. */
35
44
  rootPath: string;
36
45
  }
37
46
 
38
47
  /** Workspace-management operations exposed to the renderer. */
39
48
  export interface DocBlocksHostWorkspacesAPI {
49
+ /** List only folders already persisted as trusted main-process roots. */
50
+ list(): Promise<ElectronWorkspaceInfo[]>;
40
51
  /**
41
- * Return the default workspace (creating ~/Documents/DocBlocks on first
42
- * call, or the user's configured default).
52
+ * Return the default workspace (creating DocBlocks inside the operating
53
+ * system's Documents folder on first call, or the user's configured default).
43
54
  */
44
55
  getDefault(): Promise<ElectronWorkspaceInfo>;
45
56
  /**
@@ -48,36 +59,58 @@ export interface DocBlocksHostWorkspacesAPI {
48
59
  */
49
60
  pickFolder(): Promise<ElectronWorkspaceInfo | null>;
50
61
  /**
51
- * Re-register a previously known workspace so its rootPath is trusted
52
- * for subsequent fs calls. Called on app startup for persisted
53
- * electron-native workspaces before any fs operation.
62
+ * Re-register a previously picker-approved workspace by main-owned id.
63
+ * Called on app startup before any filesystem operation.
54
64
  */
55
- register(info: ElectronWorkspaceInfo): Promise<void>;
65
+ register(workspaceId: string): Promise<void>;
56
66
  /** Remove a workspace from the trusted whitelist. */
57
67
  unregister(id: string): Promise<void>;
58
68
  }
59
69
 
60
70
  /** Shell operations — reveal in Finder/Explorer, open external URLs. */
61
71
  export interface DocBlocksHostShellAPI {
62
- /** Reveal a file (by absolute path) in the OS file manager. */
63
- revealInFolder(absolutePath: string): Promise<void>;
72
+ /** Reveal a registered workspace root or one root-relative entry. */
73
+ revealInFolder(workspaceId: string, workspacePath?: string): Promise<void>;
64
74
  /** Open a URL in the default browser. */
65
75
  openExternal(url: string): Promise<void>;
66
76
  }
67
77
 
78
+ /** Exact, main-owned export authority. The display path is never authority. */
79
+ export interface HostExportTargetGrant {
80
+ /** Null means this is a display-only suggestion and save must show a picker. */
81
+ grantId: string | null;
82
+ displayPath: string;
83
+ }
84
+
85
+ /** Native export target selection and binary file writing. */
86
+ export interface DocBlocksHostExportAPI {
87
+ /** Resolve an exact remembered grant or a display-only host suggestion. */
88
+ resolveTarget(documentId: string, filename: string): Promise<HostExportTargetGrant>;
89
+ /** Open the native Save dialog and remember the selected target. */
90
+ pickTarget(
91
+ documentId: string,
92
+ filename: string,
93
+ currentGrantId?: string | null,
94
+ ): Promise<HostExportTargetGrant | null>;
95
+ /** Write only to an exact target granted by the main process. */
96
+ save(
97
+ documentId: string,
98
+ filename: string,
99
+ grantId: string | null,
100
+ data: ArrayBuffer | Uint8Array,
101
+ ): Promise<HostExportTargetGrant | null>;
102
+ }
103
+
68
104
  /** System ffmpeg detection and invocation. */
69
105
  export interface DocBlocksHostFfmpegAPI {
70
106
  /** True if `ffmpeg` is available on PATH (or bundled). */
71
107
  available(): Promise<boolean>;
72
108
  /** Version string from `ffmpeg -version`, or null if unavailable. */
73
109
  version(): Promise<string | null>;
74
- /**
75
- * Render a markdown file at the given absolute path to MP4 using the
76
- * existing squisq-video CLI pipeline. Returns the absolute path to the
77
- * produced MP4 file, or throws on failure.
78
- */
110
+ /** Render a physically contained workspace-relative Markdown file to MP4. */
79
111
  renderVideo(
80
- markdownAbsolutePath: string,
112
+ workspaceId: string,
113
+ markdownPath: string,
81
114
  options: { fps?: number; quality?: 'draft' | 'normal' | 'high' },
82
115
  ): Promise<string>;
83
116
  }
@@ -92,13 +125,15 @@ export interface DocBlocksHostUpdaterAPI {
92
125
  * Quit the app and apply a downloaded update. Should only be called
93
126
  * after an `UpdaterStatus` of kind `'downloaded'` has been observed.
94
127
  */
95
- quitAndInstall(): Promise<void>;
128
+ quitAndInstall(): Promise<UpdateInstallResult>;
96
129
  /**
97
130
  * Subscribe to updater status events. Returns an unsubscribe function.
98
131
  */
99
132
  onStatus(listener: (status: UpdaterStatus) => void): () => void;
100
133
  }
101
134
 
135
+ export type UpdateInstallResult = 'installing' | 'cancelled' | 'not-ready';
136
+
102
137
  export type UpdaterStatus =
103
138
  | { kind: 'checking' }
104
139
  | { kind: 'available'; version: string; releaseNotes?: string; releaseUrl?: string }
@@ -113,18 +148,66 @@ export type MenuCommand =
113
148
  | 'file:openFolder'
114
149
  | 'file:revealWorkspace'
115
150
  | 'file:settings'
151
+ | 'git:commit'
152
+ | 'git:push'
153
+ | 'git:pull'
154
+ | 'git:fetch'
155
+ | 'git:newBranch'
156
+ | 'git:switchBranch'
157
+ | 'git:history'
158
+ | 'git:clone'
159
+ | 'git:openOnRemote'
160
+ | 'git:createPullRequest'
116
161
  | 'help:about'
117
162
  | 'help:checkForUpdates'
118
163
  | 'help:viewOnGitHub';
119
164
 
120
- /** Deep-link event resolved by the host into a trusted workspace file. */
121
- export interface OpenRequest {
122
- kind: 'workspace-file';
123
- workspaceId: string;
124
- /** Slash-prefixed path relative to the workspace root. */
125
- path: string;
165
+ /**
166
+ * OS open-file / deep-link event resolved by the host.
167
+ * - 'workspace-file': a file inside an already-registered workspace.
168
+ * - 'external-file': a loose markdown file outside any workspace — opened in a
169
+ * transient workspace and saved through an opaque resource grant.
170
+ * - 'external-bundle': a `.dbk`/zip bundle — unpacked into a transient
171
+ * workspace and re-zipped through an opaque resource grant on save.
172
+ */
173
+ export type OpenRequest =
174
+ | {
175
+ kind: 'workspace-file';
176
+ workspaceId: string;
177
+ /** Slash-prefixed path relative to the workspace root. */
178
+ path: string;
179
+ }
180
+ | { kind: 'external-file'; resourceId: string; name: string }
181
+ | { kind: 'external-bundle'; resourceId: string; name: string };
182
+
183
+ /**
184
+ * Read/write access to individual OS files the user has explicitly opened
185
+ * (via "Open With" / deep link), outside the workspace-root whitelist. The
186
+ * main process gates these with owner-scoped, exact-file capabilities.
187
+ */
188
+ export interface DocBlocksHostExternalAPI {
189
+ readText(resourceId: string): Promise<string | null>;
190
+ readBinary(resourceId: string): Promise<ArrayBuffer | null>;
191
+ writeText(resourceId: string, content: string): Promise<void>;
192
+ writeBinary(resourceId: string, data: ArrayBuffer | Uint8Array): Promise<void>;
193
+ commitText(
194
+ resourceId: string,
195
+ content: string,
196
+ expectedContent: string | null,
197
+ ): Promise<FileCommitResult>;
198
+ commitBinary(
199
+ resourceId: string,
200
+ data: ArrayBuffer | Uint8Array,
201
+ expectedVersion: string | null,
202
+ ): Promise<ExternalBinaryCommitResult>;
203
+ /** Revoke one external resource when its transient document is closed. */
204
+ revoke(resourceId: string): Promise<void>;
126
205
  }
127
206
 
207
+ export type ExternalBinaryCommitResult =
208
+ | { status: 'committed'; version: string }
209
+ | { status: 'conflict'; version: string | null; data: ArrayBuffer | null };
210
+
128
211
  /** Environment metadata provided by the host. */
129
212
  export interface HostEnvironment {
130
213
  platform: 'darwin' | 'win32' | 'linux';
@@ -132,14 +215,52 @@ export interface HostEnvironment {
132
215
  isDev: boolean;
133
216
  }
134
217
 
218
+ export type HostCloseReason =
219
+ | 'window-close'
220
+ | 'app-quit'
221
+ | 'update-install'
222
+ | 'reload'
223
+ | 'force-reload';
224
+
225
+ export interface HostPrepareCloseRequest {
226
+ requestId: string;
227
+ reason: HostCloseReason;
228
+ /** Absolute epoch-millisecond deadline chosen by the main process. */
229
+ deadline: number;
230
+ }
231
+
232
+ export type HostPrepareCloseResult =
233
+ | { status: 'ready'; persistedRevision: number }
234
+ | {
235
+ status: 'blocked';
236
+ code: 'save-failed' | 'external-conflict' | 'not-ready';
237
+ message: string;
238
+ };
239
+
240
+ /**
241
+ * Main-owned close handshake. Preload privately correlates replies; the
242
+ * renderer never chooses request or window identifiers.
243
+ */
244
+ export interface DocBlocksHostLifecycleAPI {
245
+ onPrepareClose(
246
+ listener: (request: HostPrepareCloseRequest) => Promise<HostPrepareCloseResult>,
247
+ ): () => void;
248
+ onCancelClose(listener: (requestId: string) => void): () => void;
249
+ }
250
+
135
251
  /** The full DocBlocks desktop host API. */
136
252
  export interface DocBlocksHostAPI {
137
253
  env: HostEnvironment;
138
254
  fs: DocBlocksHostFsAPI;
255
+ fsV2: DocBlocksHostFsV2API;
256
+ external: DocBlocksHostExternalAPI;
139
257
  workspaces: DocBlocksHostWorkspacesAPI;
140
258
  shell: DocBlocksHostShellAPI;
259
+ exports: DocBlocksHostExportAPI;
141
260
  ffmpeg: DocBlocksHostFfmpegAPI;
261
+ git: DocBlocksHostGitAPI;
142
262
  updater: DocBlocksHostUpdaterAPI;
263
+ lifecycle: DocBlocksHostLifecycleAPI;
143
264
  /**
144
265
  * Subscribe to menu commands dispatched by the native menu.
145
266
  * Returns an unsubscribe function.
@@ -0,0 +1,103 @@
1
+ import type { OpenRequest } from './types.js';
2
+
3
+ /** Quantitative limits shared by privileged host boundaries. */
4
+ export const HOST_WIRE_LIMITS = Object.freeze({
5
+ identifierCharacters: 256,
6
+ labelCharacters: 1_024,
7
+ pathCharacters: 4_096,
8
+ urlCharacters: 8_192,
9
+ messageCharacters: 2_000,
10
+ documentCharacters: 20 * 1024 * 1024,
11
+ binaryBytes: 100 * 1024 * 1024,
12
+ base64Characters: 140 * 1024 * 1024,
13
+ arrayEntries: 10_000,
14
+ });
15
+
16
+ function hasExactKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {
17
+ const actual = Object.keys(value);
18
+ return (
19
+ actual.length === keys.length &&
20
+ keys.every((key) => Object.prototype.hasOwnProperty.call(value, key))
21
+ );
22
+ }
23
+
24
+ export function isBoundedString(
25
+ value: unknown,
26
+ maximumCharacters: number,
27
+ minimumCharacters = 0,
28
+ ): value is string {
29
+ return (
30
+ typeof value === 'string' &&
31
+ value.length >= minimumCharacters &&
32
+ value.length <= maximumCharacters &&
33
+ !value.includes('\0')
34
+ );
35
+ }
36
+
37
+ export function isBoundedBytePayload(
38
+ value: unknown,
39
+ maximumBytes = HOST_WIRE_LIMITS.binaryBytes,
40
+ ): value is ArrayBuffer | Uint8Array {
41
+ return (
42
+ (value instanceof ArrayBuffer || value instanceof Uint8Array) &&
43
+ value.byteLength <= maximumBytes
44
+ );
45
+ }
46
+
47
+ /** Parse one exact, bounded main-to-renderer open request. */
48
+ export function parseOpenRequest(value: unknown): OpenRequest | null {
49
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) return null;
50
+ const record = value as Record<string, unknown>;
51
+
52
+ if (record.kind === 'workspace-file') {
53
+ if (!hasExactKeys(record, ['kind', 'workspaceId', 'path'])) return null;
54
+ if (!isBoundedString(record.workspaceId, HOST_WIRE_LIMITS.identifierCharacters, 1)) return null;
55
+ if (!isBoundedString(record.path, HOST_WIRE_LIMITS.pathCharacters, 1)) return null;
56
+ return { kind: 'workspace-file', workspaceId: record.workspaceId, path: record.path };
57
+ }
58
+
59
+ if (record.kind === 'external-file' || record.kind === 'external-bundle') {
60
+ if (!hasExactKeys(record, ['kind', 'resourceId', 'name'])) return null;
61
+ if (!isBoundedString(record.resourceId, HOST_WIRE_LIMITS.identifierCharacters, 1)) return null;
62
+ if (!isBoundedString(record.name, HOST_WIRE_LIMITS.labelCharacters, 1)) return null;
63
+ return { kind: record.kind, resourceId: record.resourceId, name: record.name };
64
+ }
65
+
66
+ return null;
67
+ }
68
+
69
+ /** Return one canonical HTTP(S) URL, or null when external navigation is unsafe. */
70
+ export function parseExternalHttpUrl(value: unknown): string | null {
71
+ if (!isBoundedString(value, HOST_WIRE_LIMITS.urlCharacters, 1)) return null;
72
+ try {
73
+ const url = new URL(value);
74
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') return null;
75
+ if (url.username || url.password) return null;
76
+ const canonical = url.href;
77
+ return canonical.length <= HOST_WIRE_LIMITS.urlCharacters ? canonical : null;
78
+ } catch {
79
+ return null;
80
+ }
81
+ }
82
+
83
+ /** True only for the packaged renderer origin or the exact configured dev origin. */
84
+ export function isTrustedRendererUrl(value: unknown, developmentOrigin?: string): boolean {
85
+ if (!isBoundedString(value, HOST_WIRE_LIMITS.urlCharacters, 1)) return false;
86
+ try {
87
+ const url = new URL(value);
88
+ if (
89
+ url.protocol === 'app:' &&
90
+ url.hostname === 'docblocks' &&
91
+ url.port === '' &&
92
+ url.username === '' &&
93
+ url.password === ''
94
+ ) {
95
+ return true;
96
+ }
97
+ if (!developmentOrigin) return false;
98
+ const trustedDevelopmentOrigin = new URL(developmentOrigin);
99
+ return url.origin === trustedDevelopmentOrigin.origin;
100
+ } catch {
101
+ return false;
102
+ }
103
+ }
package/src/index.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * @bendyline/docblocks — Core package
3
3
  *
4
- * Re-exports filesystem, workspace, and host modules for convenience.
4
+ * Re-exports filesystem, document, workspace, and host modules for convenience.
5
5
  */
6
6
 
7
7
  export * from './filesystem/index.js';
8
+ export * from './document/index.js';
8
9
  export * from './workspace/index.js';
9
10
  export * from './host/index.js';
@@ -0,0 +1,3 @@
1
+ /** Exact, bounded wire contracts shared by DocBlocks MCP implementations. */
2
+ export * from './types.js';
3
+ export * from './wire.js';