@knpkv/confluence-to-markdown 0.6.0 → 0.7.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 (357) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/LICENSE +21 -0
  3. package/README.md +22 -13
  4. package/dist/AdfPlaceholders.d.ts +42 -0
  5. package/dist/AdfPlaceholders.d.ts.map +1 -0
  6. package/dist/AdfPlaceholders.js +547 -0
  7. package/dist/AdfPlaceholders.js.map +1 -0
  8. package/dist/AdfSchemaValidator.d.ts +37 -0
  9. package/dist/AdfSchemaValidator.d.ts.map +1 -0
  10. package/dist/AdfSchemaValidator.js +37 -0
  11. package/dist/AdfSchemaValidator.js.map +1 -0
  12. package/dist/AdfWalker.d.ts +39 -0
  13. package/dist/AdfWalker.d.ts.map +1 -0
  14. package/dist/AdfWalker.js +527 -0
  15. package/dist/AdfWalker.js.map +1 -0
  16. package/dist/AtlaskitTransformers.d.ts +35 -0
  17. package/dist/AtlaskitTransformers.d.ts.map +1 -0
  18. package/dist/AtlaskitTransformers.js +48 -0
  19. package/dist/AtlaskitTransformers.js.map +1 -0
  20. package/dist/Brand.d.ts +6 -6
  21. package/dist/Brand.d.ts.map +1 -1
  22. package/dist/Brand.js +8 -6
  23. package/dist/Brand.js.map +1 -1
  24. package/dist/ConfluenceAuth.d.ts +4 -4
  25. package/dist/ConfluenceAuth.d.ts.map +1 -1
  26. package/dist/ConfluenceAuth.js +37 -39
  27. package/dist/ConfluenceAuth.js.map +1 -1
  28. package/dist/ConfluenceClient.d.ts +7 -17
  29. package/dist/ConfluenceClient.d.ts.map +1 -1
  30. package/dist/ConfluenceClient.js +81 -38
  31. package/dist/ConfluenceClient.js.map +1 -1
  32. package/dist/ConfluenceConfig.d.ts +3 -3
  33. package/dist/ConfluenceConfig.d.ts.map +1 -1
  34. package/dist/ConfluenceConfig.js +13 -11
  35. package/dist/ConfluenceConfig.js.map +1 -1
  36. package/dist/ConfluenceError.d.ts +68 -16
  37. package/dist/ConfluenceError.d.ts.map +1 -1
  38. package/dist/ConfluenceError.js +30 -1
  39. package/dist/ConfluenceError.js.map +1 -1
  40. package/dist/GitError.d.ts +5 -5
  41. package/dist/GitService.d.ts +11 -3
  42. package/dist/GitService.d.ts.map +1 -1
  43. package/dist/GitService.js +22 -27
  44. package/dist/GitService.js.map +1 -1
  45. package/dist/LocalFileSystem.d.ts +3 -3
  46. package/dist/LocalFileSystem.d.ts.map +1 -1
  47. package/dist/LocalFileSystem.js +6 -6
  48. package/dist/LocalFileSystem.js.map +1 -1
  49. package/dist/MarkdownConverter.d.ts +16 -65
  50. package/dist/MarkdownConverter.d.ts.map +1 -1
  51. package/dist/MarkdownConverter.js +64 -85
  52. package/dist/MarkdownConverter.js.map +1 -1
  53. package/dist/Schemas.d.ts +128 -141
  54. package/dist/Schemas.d.ts.map +1 -1
  55. package/dist/Schemas.js +21 -23
  56. package/dist/Schemas.js.map +1 -1
  57. package/dist/SyncEngine.d.ts +8 -5
  58. package/dist/SyncEngine.d.ts.map +1 -1
  59. package/dist/SyncEngine.js +189 -113
  60. package/dist/SyncEngine.js.map +1 -1
  61. package/dist/bin.js +23 -35
  62. package/dist/bin.js.map +1 -1
  63. package/dist/commands/auth.d.ts +2 -14
  64. package/dist/commands/auth.d.ts.map +1 -1
  65. package/dist/commands/auth.js +11 -16
  66. package/dist/commands/auth.js.map +1 -1
  67. package/dist/commands/clone.d.ts +4 -6
  68. package/dist/commands/clone.d.ts.map +1 -1
  69. package/dist/commands/clone.js +34 -32
  70. package/dist/commands/clone.js.map +1 -1
  71. package/dist/commands/delete.d.ts +2 -10
  72. package/dist/commands/delete.d.ts.map +1 -1
  73. package/dist/commands/delete.js +5 -4
  74. package/dist/commands/delete.js.map +1 -1
  75. package/dist/commands/errorHandler.d.ts +2 -1
  76. package/dist/commands/errorHandler.d.ts.map +1 -1
  77. package/dist/commands/errorHandler.js +22 -15
  78. package/dist/commands/errorHandler.js.map +1 -1
  79. package/dist/commands/fetch.d.ts +27 -0
  80. package/dist/commands/fetch.d.ts.map +1 -0
  81. package/dist/commands/fetch.js +48 -0
  82. package/dist/commands/fetch.js.map +1 -0
  83. package/dist/commands/git.d.ts +7 -10
  84. package/dist/commands/git.d.ts.map +1 -1
  85. package/dist/commands/git.js +6 -6
  86. package/dist/commands/git.js.map +1 -1
  87. package/dist/commands/index.d.ts +1 -0
  88. package/dist/commands/index.d.ts.map +1 -1
  89. package/dist/commands/index.js +1 -0
  90. package/dist/commands/index.js.map +1 -1
  91. package/dist/commands/layers.d.ts +10 -9
  92. package/dist/commands/layers.d.ts.map +1 -1
  93. package/dist/commands/layers.js +41 -30
  94. package/dist/commands/layers.js.map +1 -1
  95. package/dist/commands/new.d.ts +2 -6
  96. package/dist/commands/new.d.ts.map +1 -1
  97. package/dist/commands/new.js +5 -4
  98. package/dist/commands/new.js.map +1 -1
  99. package/dist/commands/pageInput.d.ts +19 -0
  100. package/dist/commands/pageInput.d.ts.map +1 -0
  101. package/dist/commands/pageInput.js +68 -0
  102. package/dist/commands/pageInput.js.map +1 -0
  103. package/dist/commands/root.d.ts +8 -0
  104. package/dist/commands/root.d.ts.map +1 -0
  105. package/dist/commands/root.js +29 -0
  106. package/dist/commands/root.js.map +1 -0
  107. package/dist/commands/sync.d.ts +6 -9
  108. package/dist/commands/sync.d.ts.map +1 -1
  109. package/dist/commands/sync.js +5 -6
  110. package/dist/commands/sync.js.map +1 -1
  111. package/dist/index.d.ts +3 -8
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +2 -13
  114. package/dist/index.js.map +1 -1
  115. package/dist/internal/NodeLayers.d.ts.map +1 -1
  116. package/dist/internal/NodeLayers.js +1 -2
  117. package/dist/internal/NodeLayers.js.map +1 -1
  118. package/dist/internal/adfMetadata.d.ts +30 -0
  119. package/dist/internal/adfMetadata.d.ts.map +1 -0
  120. package/dist/internal/adfMetadata.js +126 -0
  121. package/dist/internal/adfMetadata.js.map +1 -0
  122. package/dist/internal/cleanMarkdown.d.ts +5 -0
  123. package/dist/internal/cleanMarkdown.d.ts.map +1 -0
  124. package/dist/internal/cleanMarkdown.js +13 -0
  125. package/dist/internal/cleanMarkdown.js.map +1 -0
  126. package/dist/internal/frontmatter.d.ts.map +1 -1
  127. package/dist/internal/frontmatter.js +41 -8
  128. package/dist/internal/frontmatter.js.map +1 -1
  129. package/dist/internal/gitCommands.d.ts +9 -3
  130. package/dist/internal/gitCommands.d.ts.map +1 -1
  131. package/dist/internal/gitCommands.js +18 -9
  132. package/dist/internal/gitCommands.js.map +1 -1
  133. package/dist/internal/hashUtils.d.ts +1 -1
  134. package/dist/internal/hashUtils.d.ts.map +1 -1
  135. package/dist/internal/hashUtils.js +1 -1
  136. package/dist/internal/hashUtils.js.map +1 -1
  137. package/dist/internal/oauthServer.d.ts +10 -5
  138. package/dist/internal/oauthServer.d.ts.map +1 -1
  139. package/dist/internal/oauthServer.js +19 -40
  140. package/dist/internal/oauthServer.js.map +1 -1
  141. package/dist/internal/pathUtils.d.ts +1 -1
  142. package/dist/internal/pathUtils.d.ts.map +1 -1
  143. package/dist/internal/pathUtils.js +1 -1
  144. package/dist/internal/pathUtils.js.map +1 -1
  145. package/dist/internal/process.d.ts +15 -0
  146. package/dist/internal/process.d.ts.map +1 -0
  147. package/dist/internal/process.js +10 -0
  148. package/dist/internal/process.js.map +1 -0
  149. package/dist/internal/stdio.d.ts +6 -0
  150. package/dist/internal/stdio.d.ts.map +1 -0
  151. package/dist/internal/stdio.js +15 -0
  152. package/dist/internal/stdio.js.map +1 -0
  153. package/dist/internal/tokenStorage.d.ts +3 -13
  154. package/dist/internal/tokenStorage.d.ts.map +1 -1
  155. package/dist/internal/tokenStorage.js +26 -24
  156. package/dist/internal/tokenStorage.js.map +1 -1
  157. package/dist/internal/userCache.d.ts +1 -1
  158. package/dist/internal/userCache.d.ts.map +1 -1
  159. package/dist/internal/userCache.js +1 -1
  160. package/dist/internal/userCache.js.map +1 -1
  161. package/package.json +30 -30
  162. package/skills/confluence/SKILL.md +143 -0
  163. package/skills/confluence/agents/openai.yaml +4 -0
  164. package/src/AdfPlaceholders.ts +310 -13
  165. package/src/AdfSchemaValidator.ts +2 -4
  166. package/src/AdfWalker.ts +122 -42
  167. package/src/AtlaskitTransformers.ts +2 -4
  168. package/src/Brand.ts +11 -16
  169. package/src/ConfluenceAuth.ts +22 -30
  170. package/src/ConfluenceClient.ts +24 -20
  171. package/src/ConfluenceConfig.ts +14 -14
  172. package/src/GitService.ts +39 -49
  173. package/src/LocalFileSystem.ts +7 -9
  174. package/src/MarkdownConverter.ts +2 -4
  175. package/src/Schemas.ts +13 -12
  176. package/src/SyncEngine.ts +151 -53
  177. package/src/bin.ts +30 -56
  178. package/src/commands/auth.ts +21 -18
  179. package/src/commands/clone.ts +38 -37
  180. package/src/commands/delete.ts +5 -4
  181. package/src/commands/errorHandler.ts +25 -18
  182. package/src/commands/fetch.ts +90 -0
  183. package/src/commands/git.ts +6 -6
  184. package/src/commands/index.ts +1 -0
  185. package/src/commands/layers.ts +53 -33
  186. package/src/commands/new.ts +5 -4
  187. package/src/commands/pageInput.ts +103 -0
  188. package/src/commands/root.ts +59 -0
  189. package/src/commands/sync.ts +7 -6
  190. package/src/internal/NodeLayers.ts +1 -2
  191. package/src/internal/adfMetadata.ts +145 -0
  192. package/src/internal/cleanMarkdown.ts +15 -0
  193. package/src/internal/frontmatter.ts +45 -8
  194. package/src/internal/gitCommands.ts +23 -17
  195. package/src/internal/hashUtils.ts +2 -2
  196. package/src/internal/oauthServer.ts +84 -105
  197. package/src/internal/pathUtils.ts +1 -1
  198. package/src/internal/process.ts +15 -0
  199. package/src/internal/stdio.ts +22 -0
  200. package/src/internal/tokenStorage.ts +39 -29
  201. package/src/internal/userCache.ts +2 -2
  202. package/test/AdfPlaceholders.test.ts +213 -0
  203. package/test/AdfSchemaValidator.test.ts +6 -6
  204. package/test/AdfWalker.test.ts +167 -21
  205. package/test/AtlaskitTransformers.test.ts +4 -4
  206. package/test/Brand.test.ts +11 -11
  207. package/test/GitService.test.ts +6 -2
  208. package/test/MarkdownConverter.test.ts +12 -11
  209. package/test/RoundTrip.test.ts +258 -3
  210. package/test/Schemas.test.ts +40 -40
  211. package/test/adfMetadata.test.ts +110 -0
  212. package/test/cleanMarkdown.test.ts +36 -0
  213. package/test/commandHarness.test.ts +79 -0
  214. package/test/commandHarness.ts +147 -0
  215. package/test/fetch.test.ts +61 -0
  216. package/test/frontmatter.test.ts +41 -0
  217. package/test/integration.test.ts +569 -156
  218. package/test/layers.test.ts +12 -0
  219. package/test/oauthServer.test.ts +4 -5
  220. package/test/pageInput.test.ts +83 -0
  221. package/test/tokenStorage.test.ts +17 -17
  222. package/dist/SchemaConverterError.d.ts +0 -108
  223. package/dist/SchemaConverterError.d.ts.map +0 -1
  224. package/dist/SchemaConverterError.js +0 -84
  225. package/dist/SchemaConverterError.js.map +0 -1
  226. package/dist/ast/BlockNode.d.ts +0 -468
  227. package/dist/ast/BlockNode.d.ts.map +0 -1
  228. package/dist/ast/BlockNode.js +0 -319
  229. package/dist/ast/BlockNode.js.map +0 -1
  230. package/dist/ast/Document.d.ts +0 -244
  231. package/dist/ast/Document.d.ts.map +0 -1
  232. package/dist/ast/Document.js +0 -69
  233. package/dist/ast/Document.js.map +0 -1
  234. package/dist/ast/InlineNode.d.ts +0 -477
  235. package/dist/ast/InlineNode.d.ts.map +0 -1
  236. package/dist/ast/InlineNode.js +0 -263
  237. package/dist/ast/InlineNode.js.map +0 -1
  238. package/dist/ast/MacroNode.d.ts +0 -267
  239. package/dist/ast/MacroNode.d.ts.map +0 -1
  240. package/dist/ast/MacroNode.js +0 -164
  241. package/dist/ast/MacroNode.js.map +0 -1
  242. package/dist/ast/index.d.ts +0 -10
  243. package/dist/ast/index.d.ts.map +0 -1
  244. package/dist/ast/index.js +0 -14
  245. package/dist/ast/index.js.map +0 -1
  246. package/dist/parsers/ConfluenceParser.d.ts +0 -26
  247. package/dist/parsers/ConfluenceParser.d.ts.map +0 -1
  248. package/dist/parsers/ConfluenceParser.js +0 -792
  249. package/dist/parsers/ConfluenceParser.js.map +0 -1
  250. package/dist/parsers/MarkdownParser.d.ts +0 -26
  251. package/dist/parsers/MarkdownParser.d.ts.map +0 -1
  252. package/dist/parsers/MarkdownParser.js +0 -873
  253. package/dist/parsers/MarkdownParser.js.map +0 -1
  254. package/dist/parsers/index.d.ts +0 -8
  255. package/dist/parsers/index.d.ts.map +0 -1
  256. package/dist/parsers/index.js +0 -8
  257. package/dist/parsers/index.js.map +0 -1
  258. package/dist/parsers/preprocessing/ConfluencePreprocessing.d.ts +0 -23
  259. package/dist/parsers/preprocessing/ConfluencePreprocessing.d.ts.map +0 -1
  260. package/dist/parsers/preprocessing/ConfluencePreprocessing.js +0 -323
  261. package/dist/parsers/preprocessing/ConfluencePreprocessing.js.map +0 -1
  262. package/dist/parsers/preprocessing/index.d.ts +0 -7
  263. package/dist/parsers/preprocessing/index.d.ts.map +0 -1
  264. package/dist/parsers/preprocessing/index.js +0 -7
  265. package/dist/parsers/preprocessing/index.js.map +0 -1
  266. package/dist/schemas/ConfluenceSchema.d.ts +0 -21
  267. package/dist/schemas/ConfluenceSchema.d.ts.map +0 -1
  268. package/dist/schemas/ConfluenceSchema.js +0 -38
  269. package/dist/schemas/ConfluenceSchema.js.map +0 -1
  270. package/dist/schemas/ConversionSchema.d.ts +0 -35
  271. package/dist/schemas/ConversionSchema.d.ts.map +0 -1
  272. package/dist/schemas/ConversionSchema.js +0 -208
  273. package/dist/schemas/ConversionSchema.js.map +0 -1
  274. package/dist/schemas/MarkdownSchema.d.ts +0 -21
  275. package/dist/schemas/MarkdownSchema.d.ts.map +0 -1
  276. package/dist/schemas/MarkdownSchema.js +0 -38
  277. package/dist/schemas/MarkdownSchema.js.map +0 -1
  278. package/dist/schemas/hast/HastFromHtml.d.ts +0 -27
  279. package/dist/schemas/hast/HastFromHtml.d.ts.map +0 -1
  280. package/dist/schemas/hast/HastFromHtml.js +0 -107
  281. package/dist/schemas/hast/HastFromHtml.js.map +0 -1
  282. package/dist/schemas/hast/HastSchema.d.ts +0 -195
  283. package/dist/schemas/hast/HastSchema.d.ts.map +0 -1
  284. package/dist/schemas/hast/HastSchema.js +0 -183
  285. package/dist/schemas/hast/HastSchema.js.map +0 -1
  286. package/dist/schemas/hast/index.d.ts +0 -9
  287. package/dist/schemas/hast/index.d.ts.map +0 -1
  288. package/dist/schemas/hast/index.js +0 -3
  289. package/dist/schemas/hast/index.js.map +0 -1
  290. package/dist/schemas/index.d.ts +0 -14
  291. package/dist/schemas/index.d.ts.map +0 -1
  292. package/dist/schemas/index.js +0 -16
  293. package/dist/schemas/index.js.map +0 -1
  294. package/dist/schemas/mdast/MdastFromMarkdown.d.ts +0 -30
  295. package/dist/schemas/mdast/MdastFromMarkdown.d.ts.map +0 -1
  296. package/dist/schemas/mdast/MdastFromMarkdown.js +0 -79
  297. package/dist/schemas/mdast/MdastFromMarkdown.js.map +0 -1
  298. package/dist/schemas/mdast/MdastSchema.d.ts +0 -385
  299. package/dist/schemas/mdast/MdastSchema.d.ts.map +0 -1
  300. package/dist/schemas/mdast/MdastSchema.js +0 -266
  301. package/dist/schemas/mdast/MdastSchema.js.map +0 -1
  302. package/dist/schemas/mdast/index.d.ts +0 -10
  303. package/dist/schemas/mdast/index.d.ts.map +0 -1
  304. package/dist/schemas/mdast/index.js +0 -4
  305. package/dist/schemas/mdast/index.js.map +0 -1
  306. package/dist/schemas/mdast/mdastToString.d.ts +0 -13
  307. package/dist/schemas/mdast/mdastToString.d.ts.map +0 -1
  308. package/dist/schemas/mdast/mdastToString.js +0 -85
  309. package/dist/schemas/mdast/mdastToString.js.map +0 -1
  310. package/dist/schemas/nodes/block/BlockSchema.d.ts +0 -43
  311. package/dist/schemas/nodes/block/BlockSchema.d.ts.map +0 -1
  312. package/dist/schemas/nodes/block/BlockSchema.js +0 -634
  313. package/dist/schemas/nodes/block/BlockSchema.js.map +0 -1
  314. package/dist/schemas/nodes/block/index.d.ts +0 -7
  315. package/dist/schemas/nodes/block/index.d.ts.map +0 -1
  316. package/dist/schemas/nodes/block/index.js +0 -7
  317. package/dist/schemas/nodes/block/index.js.map +0 -1
  318. package/dist/schemas/nodes/index.d.ts +0 -9
  319. package/dist/schemas/nodes/index.d.ts.map +0 -1
  320. package/dist/schemas/nodes/index.js +0 -12
  321. package/dist/schemas/nodes/index.js.map +0 -1
  322. package/dist/schemas/nodes/inline/InlineSchema.d.ts +0 -48
  323. package/dist/schemas/nodes/inline/InlineSchema.d.ts.map +0 -1
  324. package/dist/schemas/nodes/inline/InlineSchema.js +0 -436
  325. package/dist/schemas/nodes/inline/InlineSchema.js.map +0 -1
  326. package/dist/schemas/nodes/inline/index.d.ts +0 -7
  327. package/dist/schemas/nodes/inline/index.d.ts.map +0 -1
  328. package/dist/schemas/nodes/inline/index.js +0 -7
  329. package/dist/schemas/nodes/inline/index.js.map +0 -1
  330. package/dist/schemas/nodes/macro/MacroSchema.d.ts +0 -27
  331. package/dist/schemas/nodes/macro/MacroSchema.d.ts.map +0 -1
  332. package/dist/schemas/nodes/macro/MacroSchema.js +0 -162
  333. package/dist/schemas/nodes/macro/MacroSchema.js.map +0 -1
  334. package/dist/schemas/nodes/macro/index.d.ts +0 -7
  335. package/dist/schemas/nodes/macro/index.d.ts.map +0 -1
  336. package/dist/schemas/nodes/macro/index.js +0 -7
  337. package/dist/schemas/nodes/macro/index.js.map +0 -1
  338. package/dist/schemas/preprocessing/ConfluencePreprocessor.d.ts +0 -53
  339. package/dist/schemas/preprocessing/ConfluencePreprocessor.d.ts.map +0 -1
  340. package/dist/schemas/preprocessing/ConfluencePreprocessor.js +0 -349
  341. package/dist/schemas/preprocessing/ConfluencePreprocessor.js.map +0 -1
  342. package/dist/schemas/preprocessing/index.d.ts +0 -8
  343. package/dist/schemas/preprocessing/index.d.ts.map +0 -1
  344. package/dist/schemas/preprocessing/index.js +0 -2
  345. package/dist/schemas/preprocessing/index.js.map +0 -1
  346. package/dist/serializers/ConfluenceSerializer.d.ts +0 -30
  347. package/dist/serializers/ConfluenceSerializer.d.ts.map +0 -1
  348. package/dist/serializers/ConfluenceSerializer.js +0 -551
  349. package/dist/serializers/ConfluenceSerializer.js.map +0 -1
  350. package/dist/serializers/MarkdownSerializer.d.ts +0 -34
  351. package/dist/serializers/MarkdownSerializer.d.ts.map +0 -1
  352. package/dist/serializers/MarkdownSerializer.js +0 -355
  353. package/dist/serializers/MarkdownSerializer.js.map +0 -1
  354. package/dist/serializers/index.d.ts +0 -8
  355. package/dist/serializers/index.d.ts.map +0 -1
  356. package/dist/serializers/index.js +0 -8
  357. package/dist/serializers/index.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"SyncEngine.d.ts","sourceRoot":"","sources":["../src/SyncEngine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SyncEngine.d.ts","sourceRoot":"","sources":["../src/SyncEngine.ts"],"names":[],"mappings":"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"}
@@ -3,19 +3,43 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- import * as Path from "@effect/platform/Path";
7
6
  import * as Context from "effect/Context";
8
7
  import * as Effect from "effect/Effect";
8
+ import * as FileSystem from "effect/FileSystem";
9
9
  import * as Layer from "effect/Layer";
10
+ import * as Path from "effect/Path";
11
+ import * as Result from "effect/Result";
12
+ import * as Schema from "effect/Schema";
10
13
  import { PageId } from "./Brand.js";
11
14
  import { ConfluenceClient } from "./ConfluenceClient.js";
12
15
  import { ConfluenceConfig } from "./ConfluenceConfig.js";
13
16
  import { FileSystemError, StructureError } from "./ConfluenceError.js";
14
17
  import { GitService } from "./GitService.js";
18
+ import { AdfMetadataSidecarSchema, collectAdfMetadataHrefs, externalizeAdfMetadata, hydrateAdfMetadata } from "./internal/adfMetadata.js";
19
+ import { parseMarkdown } from "./internal/frontmatter.js";
15
20
  import { computeHash, HashServiceLive } from "./internal/hashUtils.js";
16
21
  import { UserCache } from "./internal/userCache.js";
17
22
  import { LocalFileSystem } from "./LocalFileSystem.js";
18
23
  import { MarkdownConverter } from "./MarkdownConverter.js";
24
+ /**
25
+ * Pretty-print an ADF JSON wire string for the `.source.json` companion file.
26
+ * Falls back to the raw string if it can't be parsed as JSON.
27
+ */
28
+ const prettyAdf = (raw) => {
29
+ try {
30
+ return JSON.stringify(JSON.parse(raw), null, 2);
31
+ }
32
+ catch {
33
+ return raw;
34
+ }
35
+ };
36
+ /**
37
+ * Hash a markdown body in the form `readMarkdownFile` will later return it.
38
+ * `parseMarkdown` trims the body when reading, so the hash we store on
39
+ * frontmatter must hash the trimmed body too — otherwise every subsequent
40
+ * read sees a "changed" file and `push` keeps pushing a no-op update.
41
+ */
42
+ const hashBody = (markdown) => computeHash(markdown.trim()).pipe(Effect.provide(HashServiceLive));
19
43
  /**
20
44
  * Sync engine service for Confluence <-> Markdown operations.
21
45
  *
@@ -33,7 +57,7 @@ import { MarkdownConverter } from "./MarkdownConverter.js";
33
57
  *
34
58
  * @category Sync
35
59
  */
36
- export class SyncEngine extends Context.Tag("@knpkv/confluence-to-markdown/SyncEngine")() {
60
+ export class SyncEngine extends Context.Service()("@knpkv/confluence-to-markdown/SyncEngine") {
37
61
  }
38
62
  /**
39
63
  * Layer that provides SyncEngine.
@@ -46,9 +70,48 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
46
70
  const converter = yield* MarkdownConverter;
47
71
  const localFs = yield* LocalFileSystem;
48
72
  const pathService = yield* Path.Path;
73
+ const fs = yield* FileSystem.FileSystem;
49
74
  const git = yield* GitService;
50
75
  const userCache = yield* UserCache;
51
- const docsPath = pathService.join(process.cwd(), config.docsPath);
76
+ const cwd = pathService.resolve(".");
77
+ const docsPath = pathService.join(cwd, config.docsPath);
78
+ const adfMetadataPath = (filePath, pageId) => pageId
79
+ ? pathService.join(pathService.dirname(filePath), `${pageId}.adf.json`)
80
+ : filePath.replace(/\.md$/, ".adf.json");
81
+ const adfMetadataHref = (filePath, pageId) => `./${pathService.basename(adfMetadataPath(filePath, pageId))}`;
82
+ const prepareMarkdownForFile = (filePath, markdown, pageId) => externalizeAdfMetadata(markdown, adfMetadataHref(filePath, pageId));
83
+ const writePreparedMarkdownWithAdfMetadata = (filePath, frontMatter, prepared) => Effect.gen(function* () {
84
+ yield* localFs.writeMarkdownFile(filePath, frontMatter, prepared.markdown);
85
+ const sidecarPath = adfMetadataPath(filePath, frontMatter.pageId);
86
+ if (prepared.sidecar !== null) {
87
+ yield* localFs.writeFile(sidecarPath, JSON.stringify(prepared.sidecar, null, 2) + "\n");
88
+ }
89
+ else if (yield* localFs.exists(sidecarPath)) {
90
+ yield* localFs.deleteFile(sidecarPath);
91
+ }
92
+ });
93
+ const readAdfMetadataSidecar = (sidecarPath) => Effect.gen(function* () {
94
+ const exists = yield* localFs.exists(sidecarPath);
95
+ if (!exists)
96
+ return null;
97
+ const raw = yield* fs.readFileString(sidecarPath).pipe(Effect.mapError((cause) => new FileSystemError({ operation: "read", path: sidecarPath, cause })));
98
+ const parsed = yield* Effect.try({
99
+ try: () => JSON.parse(raw),
100
+ catch: (cause) => new FileSystemError({ operation: "read", path: sidecarPath, cause })
101
+ });
102
+ return yield* Schema.decodeUnknownEffect(AdfMetadataSidecarSchema)(parsed).pipe(Effect.mapError((cause) => new FileSystemError({ operation: "read", path: sidecarPath, cause })));
103
+ });
104
+ const hydrateMarkdownForFile = (filePath, markdown) => Effect.gen(function* () {
105
+ const sidecars = new Map();
106
+ const dir = pathService.dirname(filePath);
107
+ for (const href of collectAdfMetadataHrefs(markdown)) {
108
+ const sidecarPath = pathService.resolve(dir, href);
109
+ const sidecar = yield* readAdfMetadataSidecar(sidecarPath);
110
+ if (sidecar !== null)
111
+ sidecars.set(href, sidecar);
112
+ }
113
+ return hydrateAdfMetadata(markdown, sidecars);
114
+ });
52
115
  /**
53
116
  * Build a map of relative path (without .md) to pageId for resolving parents.
54
117
  * e.g., "guide" -> pageId, "guide/getting-started" -> pageId
@@ -173,16 +236,16 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
173
236
  /**
174
237
  * Get user info with caching.
175
238
  */
176
- const getUser = (accountId) => userCache.getOrFetch(accountId, client.getUser).pipe(Effect.catchAll(() => Effect.succeed(undefined)));
239
+ const getUser = (accountId) => userCache.getOrFetch(accountId, client.getUser).pipe(Effect.catchCause(() => Effect.succeed(undefined)));
177
240
  /**
178
241
  * Convert version content to markdown and front-matter.
179
242
  */
180
- const versionToMarkdown = (pageId, version, title, parentId, position) => Effect.gen(function* () {
181
- const htmlContent = version.body?.storage?.value ?? "";
182
- const markdown = yield* converter.htmlToMarkdown(htmlContent, {
183
- includeRawSource: config.saveSource
184
- });
185
- const contentHash = yield* computeHash(markdown).pipe(Effect.provide(HashServiceLive));
243
+ const versionToMarkdown = (filePath, pageId, version, title, parentId, position) => Effect.gen(function* () {
244
+ const adfJson = version.body?.atlas_doc_format?.value ?? "";
245
+ const rawMarkdown = yield* converter.adfToMarkdown(adfJson);
246
+ const prepared = prepareMarkdownForFile(filePath, rawMarkdown, pageId);
247
+ const { markdown } = prepared;
248
+ const contentHash = yield* hashBody(markdown);
186
249
  // Get author info
187
250
  const author = version.authorId ? yield* getUser(version.authorId) : undefined;
188
251
  const frontMatter = {
@@ -197,7 +260,7 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
197
260
  ...(author?.displayName ? { authorName: author.displayName } : {}),
198
261
  ...(author?.email ? { authorEmail: author.email } : {})
199
262
  };
200
- return { markdown, frontMatter };
263
+ return { markdown, frontMatter, prepared };
201
264
  });
202
265
  /**
203
266
  * Pull a single page and its children recursively.
@@ -255,10 +318,10 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
255
318
  versionIdx++;
256
319
  // Report progress
257
320
  if (options.onProgress) {
258
- options.onProgress(versionIdx, totalVersions, `${fullPage.title} v${versionInfo.number}`);
321
+ yield* options.onProgress(versionIdx, totalVersions, `${fullPage.title} v${versionInfo.number}`);
259
322
  }
260
323
  // Check if body content is available from the versions list
261
- const bodyContent = versionInfo.page?.body?.storage?.value;
324
+ const bodyContent = versionInfo.page?.body?.atlas_doc_format?.value;
262
325
  if (!bodyContent) {
263
326
  // No body content available - history replay not supported
264
327
  historyReplayFailed = true;
@@ -271,19 +334,19 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
271
334
  createdAt: versionInfo.createdAt,
272
335
  message: versionInfo.message,
273
336
  body: {
274
- storage: {
337
+ atlas_doc_format: {
275
338
  value: bodyContent,
276
- representation: "storage"
339
+ representation: "atlas_doc_format"
277
340
  }
278
341
  }
279
342
  };
280
- const { frontMatter, markdown } = yield* versionToMarkdown(pageId, versionContent, versionInfo.page?.title ?? fullPage.title, effectiveParentId, page.position);
343
+ const { frontMatter, prepared } = yield* versionToMarkdown(filePath, pageId, versionContent, versionInfo.page?.title ?? fullPage.title, effectiveParentId, page.position);
281
344
  // Write file
282
- yield* localFs.writeMarkdownFile(filePath, frontMatter, markdown);
283
- // Save source HTML if configured
284
- if (config.saveSource && versionContent.body?.storage?.value) {
285
- const sourceFilePath = filePath.replace(/\.md$/, ".html");
286
- yield* localFs.writeFile(sourceFilePath, versionContent.body.storage.value);
345
+ yield* writePreparedMarkdownWithAdfMetadata(filePath, frontMatter, prepared);
346
+ // Save source ADF JSON if configured
347
+ if (config.saveSource && versionContent.body?.atlas_doc_format?.value) {
348
+ const sourceFilePath = filePath.replace(/\.md$/, ".source.json");
349
+ yield* localFs.writeFile(sourceFilePath, prettyAdf(versionContent.body.atlas_doc_format.value));
287
350
  }
288
351
  // Commit this version
289
352
  const author = versionInfo.authorId ? yield* getUser(versionInfo.authorId) : undefined;
@@ -308,10 +371,8 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
308
371
  yield* Effect.logWarning("History replay not available. Confluence Cloud API does not return body content for historical versions. Falling back to simple pull.");
309
372
  }
310
373
  // Simple pull without history replay
311
- const htmlContent = fullPage.body?.storage?.value ?? "";
312
- let markdown = yield* converter.htmlToMarkdown(htmlContent, {
313
- includeRawSource: config.saveSource
314
- });
374
+ const adfJson = fullPage.body?.atlas_doc_format?.value ?? "";
375
+ let rawMarkdown = yield* converter.adfToMarkdown(adfJson);
315
376
  // Add child page links for index pages
316
377
  if (hasChildren && config.spaceKey) {
317
378
  const childLinks = children
@@ -320,9 +381,11 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
320
381
  return `- [${child.title}](${pageUrl})`;
321
382
  })
322
383
  .join("\n");
323
- markdown = markdown.trim() + "\n\n## Child Pages\n\n" + childLinks + "\n";
384
+ rawMarkdown = rawMarkdown.trim() + "\n\n## Child Pages\n\n" + childLinks + "\n";
324
385
  }
325
- const contentHash = yield* computeHash(markdown).pipe(Effect.provide(HashServiceLive));
386
+ const prepared = prepareMarkdownForFile(filePath, rawMarkdown, pageId);
387
+ const { markdown } = prepared;
388
+ const contentHash = yield* hashBody(markdown);
326
389
  // Get author info
327
390
  const author = fullPage.version.authorId ? yield* getUser(fullPage.version.authorId) : undefined;
328
391
  // Write file
@@ -338,11 +401,11 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
338
401
  ...(author?.displayName ? { authorName: author.displayName } : {}),
339
402
  ...(author?.email ? { authorEmail: author.email } : {})
340
403
  };
341
- yield* localFs.writeMarkdownFile(filePath, frontMatter, markdown);
342
- // Save source HTML if configured
343
- if (config.saveSource && htmlContent) {
344
- const sourceFilePath = filePath.replace(/\.md$/, ".html");
345
- yield* localFs.writeFile(sourceFilePath, htmlContent);
404
+ yield* writePreparedMarkdownWithAdfMetadata(filePath, frontMatter, prepared);
405
+ // Save source ADF JSON if configured
406
+ if (config.saveSource && adfJson) {
407
+ const sourceFilePath = filePath.replace(/\.md$/, ".source.json");
408
+ yield* localFs.writeFile(sourceFilePath, prettyAdf(adfJson));
346
409
  }
347
410
  }
348
411
  // Pull children
@@ -369,28 +432,39 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
369
432
  // Switch to origin/confluence to pull updates there
370
433
  yield* git.checkout("origin/confluence");
371
434
  }
372
- const rootPage = yield* client.getPage(config.rootPageId);
373
- const result = yield* pullPage(rootPage, docsPath, options, gitInitialized);
374
- // If git is initialized and we have changes but didn't replay history, auto-commit
375
- if (gitInitialized && !options.replayHistory && result.pulled > 0) {
376
- yield* git.addAll();
377
- yield* git.commit({
378
- message: `Pull from Confluence (${result.pulled} page${result.pulled !== 1 ? "s" : ""})`
379
- }).pipe(Effect.catchTag("GitNoChangesError", () => Effect.void));
380
- }
381
- // Two-branch model: merge origin/confluence into current branch
382
- if (hasRemoteBranch && originalBranch && originalBranch !== "origin/confluence") {
383
- yield* git.checkout(originalBranch);
384
- yield* git.merge("origin/confluence", {
385
- message: `Merge remote changes from Confluence`
386
- }).pipe(Effect.catchAll(() => Effect.void)); // May fail if no changes
387
- }
388
- return {
389
- pulled: result.pulled,
390
- skipped: 0,
391
- commits: result.commits,
392
- errors: []
393
- };
435
+ const pullAndMerge = Effect.gen(function* () {
436
+ const rootPage = yield* client.getPage(config.rootPageId);
437
+ const result = yield* pullPage(rootPage, docsPath, options, gitInitialized);
438
+ // If git is initialized and we have changes but didn't replay history, auto-commit
439
+ if (gitInitialized && !options.replayHistory && result.pulled > 0) {
440
+ yield* git.addAll();
441
+ yield* git.commit({
442
+ message: `Pull from Confluence (${result.pulled} page${result.pulled !== 1 ? "s" : ""})`
443
+ }).pipe(Effect.catchTag("GitNoChangesError", () => Effect.void));
444
+ }
445
+ // Two-branch model: merge origin/confluence into current branch
446
+ if (hasRemoteBranch && originalBranch && originalBranch !== "origin/confluence") {
447
+ yield* git.checkout(originalBranch);
448
+ yield* git.merge("origin/confluence", {
449
+ message: `Merge remote changes from Confluence`
450
+ }).pipe(Effect.catchIf(() => true, () => Effect.void)); // May fail if no changes
451
+ }
452
+ return {
453
+ pulled: result.pulled,
454
+ skipped: 0,
455
+ commits: result.commits,
456
+ errors: []
457
+ };
458
+ });
459
+ // Any failure after the origin/confluence checkout (API, conversion,
460
+ // git) must not strand the repo on a detached HEAD — same protection
461
+ // as findUnpushedCommits. On success this re-checkout is a no-op.
462
+ // The restore itself can fail (a half-written pull leaves dirty files
463
+ // that differ between branches); that must be loud, not swallowed.
464
+ return yield* pullAndMerge.pipe(Effect.ensuring(hasRemoteBranch && originalBranch
465
+ ? git.checkout(originalBranch).pipe(Effect.catchCause((cause) => Effect.logWarning(`pull: could not restore branch '${originalBranch}' — the repo may still be on origin/confluence. ` +
466
+ `Restore manually with \`git checkout ${originalBranch}\` (stash local changes first if needed). Cause: ${String(cause)}`)))
467
+ : Effect.void));
394
468
  });
395
469
  /**
396
470
  * Push a single file's content to Confluence.
@@ -405,42 +479,36 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
405
479
  const baseName = pathService.basename(filePath, ".md");
406
480
  // For new pages, re-parse front-matter to get title
407
481
  // The localFile only has the content (body), not the original front-matter
408
- const title = yield* Effect.tryPromise({
409
- try: async () => {
410
- const fs = await import("node:fs/promises");
411
- const matter = await import("gray-matter");
412
- const rawFile = await fs.readFile(filePath, "utf-8");
413
- const parsed = matter.default(rawFile);
414
- return parsed.data.title ?? baseName;
415
- },
416
- catch: (cause) => new FileSystemError({ operation: "read", path: filePath, cause })
417
- });
482
+ const rawFile = yield* fs.readFileString(filePath).pipe(Effect.mapError((cause) => new FileSystemError({ operation: "read", path: filePath, cause })));
483
+ const parsed = yield* parseMarkdown(filePath, rawFile);
484
+ const title = parsed.frontMatter?.title ?? baseName;
418
485
  // Resolve parent from directory structure
419
486
  const parentId = yield* resolveParent(filePath, pageIdMap);
420
- // Convert markdown to HTML
421
- const html = yield* converter.markdownToHtml(localFile.content);
487
+ // Convert markdown to ADF
488
+ const hydratedContent = yield* hydrateMarkdownForFile(filePath, localFile.content);
489
+ const adfValue = yield* converter.markdownToAdf(hydratedContent);
422
490
  // Create the page
423
491
  const createdPage = yield* client.createPage({
424
492
  spaceId,
425
493
  parentId,
426
494
  title,
427
495
  body: {
428
- representation: "storage",
429
- value: html
496
+ representation: "atlas_doc_format",
497
+ value: adfValue
430
498
  }
431
499
  });
432
500
  // Set editor version to v2 (new editor)
433
- yield* client.setEditorVersion(createdPage.id, "v2").pipe(Effect.catchAll((error) => {
501
+ yield* client.setEditorVersion(createdPage.id, "v2").pipe(Effect.catchIf(() => true, (error) => {
434
502
  // Log warning but don't fail the push
435
503
  return Effect.logWarning(`Failed to set editor v2 for page ${createdPage.id}: ${error.message}`);
436
504
  }));
437
505
  // Fetch canonical content back from Confluence
438
506
  const canonicalPage = yield* client.getPage(createdPage.id);
439
- const canonicalHtml = canonicalPage.body?.storage?.value ?? "";
440
- const canonicalMarkdown = yield* converter.htmlToMarkdown(canonicalHtml, {
441
- includeRawSource: config.saveSource
442
- });
443
- const canonicalHash = yield* computeHash(canonicalMarkdown).pipe(Effect.provide(HashServiceLive));
507
+ const canonicalAdf = canonicalPage.body?.atlas_doc_format?.value ?? "";
508
+ const rawCanonicalMarkdown = yield* converter.adfToMarkdown(canonicalAdf);
509
+ const preparedCanonicalMarkdown = prepareMarkdownForFile(filePath, rawCanonicalMarkdown, createdPage.id);
510
+ const { markdown: canonicalMarkdown } = preparedCanonicalMarkdown;
511
+ const canonicalHash = yield* hashBody(canonicalMarkdown);
444
512
  // Write canonical content with full front-matter
445
513
  const newFrontMatter = {
446
514
  pageId: createdPage.id,
@@ -450,7 +518,7 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
450
518
  parentId: parentId,
451
519
  contentHash: canonicalHash
452
520
  };
453
- yield* localFs.writeMarkdownFile(filePath, newFrontMatter, canonicalMarkdown);
521
+ yield* writePreparedMarkdownWithAdfMetadata(filePath, newFrontMatter, preparedCanonicalMarkdown);
454
522
  // Update pageIdMap with new page
455
523
  const key = relativePath.replace(/\.md$/, "");
456
524
  pageIdMap.set(key, createdPage.id);
@@ -463,7 +531,8 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
463
531
  }
464
532
  // Fetch current version to avoid conflicts
465
533
  const remotePage = yield* client.getPage(fm.pageId);
466
- const html = yield* converter.markdownToHtml(localFile.content);
534
+ const hydratedContent = yield* hydrateMarkdownForFile(filePath, localFile.content);
535
+ const adfValue = yield* converter.markdownToAdf(hydratedContent);
467
536
  const updatedPage = yield* client.updatePage({
468
537
  id: fm.pageId,
469
538
  title: fm.title,
@@ -473,17 +542,17 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
473
542
  message: revisionMessage
474
543
  },
475
544
  body: {
476
- representation: "storage",
477
- value: html
545
+ representation: "atlas_doc_format",
546
+ value: adfValue
478
547
  }
479
548
  });
480
549
  // Fetch canonical content back from Confluence
481
550
  const canonicalPage = yield* client.getPage(fm.pageId);
482
- const canonicalHtml = canonicalPage.body?.storage?.value ?? "";
483
- const canonicalMarkdown = yield* converter.htmlToMarkdown(canonicalHtml, {
484
- includeRawSource: config.saveSource
485
- });
486
- const canonicalHash = yield* computeHash(canonicalMarkdown).pipe(Effect.provide(HashServiceLive));
551
+ const canonicalAdf = canonicalPage.body?.atlas_doc_format?.value ?? "";
552
+ const rawCanonicalMarkdown = yield* converter.adfToMarkdown(canonicalAdf);
553
+ const preparedCanonicalMarkdown = prepareMarkdownForFile(filePath, rawCanonicalMarkdown, fm.pageId);
554
+ const { markdown: canonicalMarkdown } = preparedCanonicalMarkdown;
555
+ const canonicalHash = yield* hashBody(canonicalMarkdown);
487
556
  // Write canonical content with updated front-matter
488
557
  const newFrontMatter = {
489
558
  ...fm,
@@ -491,7 +560,7 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
491
560
  updated: new Date(canonicalPage.version.createdAt ?? new Date().toISOString()),
492
561
  contentHash: canonicalHash
493
562
  };
494
- yield* localFs.writeMarkdownFile(filePath, newFrontMatter, canonicalMarkdown);
563
+ yield* writePreparedMarkdownWithAdfMetadata(filePath, newFrontMatter, preparedCanonicalMarkdown);
495
564
  return { pushed: true, created: false };
496
565
  });
497
566
  /**
@@ -514,30 +583,37 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
514
583
  const allCommits = yield* git.log({ n: 100 });
515
584
  if (allCommits.length === 0)
516
585
  return [];
517
- const unpushed = [];
518
- for (const commit of allCommits) {
519
- yield* git.checkout(commit.hash);
520
- let hasChanges = false;
521
- for (const filePath of files) {
522
- const exists = yield* localFs.exists(filePath);
523
- if (!exists)
524
- continue;
525
- const localFile = yield* localFs.readMarkdownFile(filePath);
526
- if (!localFile.frontMatter) {
527
- hasChanges = true;
528
- break;
586
+ // We checkout each commit to compare content; restore HEAD before returning
587
+ // so subsequent pushFile() calls see the working-tree content the user staged,
588
+ // not whatever commit we last inspected.
589
+ const originalBranch = yield* git.getCurrentBranch();
590
+ const collect = Effect.gen(function* () {
591
+ const unpushed = [];
592
+ for (const commit of allCommits) {
593
+ yield* git.checkout(commit.hash);
594
+ let hasChanges = false;
595
+ for (const filePath of files) {
596
+ const exists = yield* localFs.exists(filePath);
597
+ if (!exists)
598
+ continue;
599
+ const localFile = yield* localFs.readMarkdownFile(filePath);
600
+ if (!localFile.frontMatter) {
601
+ hasChanges = true;
602
+ break;
603
+ }
604
+ const currentHash = yield* computeHash(localFile.content).pipe(Effect.provide(HashServiceLive));
605
+ if (currentHash !== localFile.frontMatter.contentHash) {
606
+ hasChanges = true;
607
+ break;
608
+ }
529
609
  }
530
- const currentHash = yield* computeHash(localFile.content).pipe(Effect.provide(HashServiceLive));
531
- if (currentHash !== localFile.frontMatter.contentHash) {
532
- hasChanges = true;
610
+ if (!hasChanges)
533
611
  break;
534
- }
612
+ unpushed.push({ hash: commit.hash, message: commit.message });
535
613
  }
536
- if (!hasChanges)
537
- break;
538
- unpushed.push({ hash: commit.hash, message: commit.message });
539
- }
540
- return unpushed.reverse();
614
+ return unpushed.reverse();
615
+ });
616
+ return yield* collect.pipe(Effect.ensuring(originalBranch ? git.checkout(originalBranch).pipe(Effect.ignore) : Effect.void));
541
617
  });
542
618
  const push = (options) => Effect.gen(function* () {
543
619
  // Validate structure before push
@@ -564,7 +640,7 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
564
640
  pushed++;
565
641
  continue;
566
642
  }
567
- const result = yield* pushFile(filePath, options.message ?? "Updated via confluence-to-markdown", spaceId, pageIdMap).pipe(Effect.catchAll((error) => Effect.succeed({
643
+ const result = yield* pushFile(filePath, options.message ?? "Updated via confluence-to-markdown", spaceId, pageIdMap).pipe(Effect.catchIf(() => true, (error) => Effect.succeed({
568
644
  pushed: false,
569
645
  created: false,
570
646
  error: `Failed: ${error._tag}`
@@ -615,9 +691,9 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
615
691
  const pageIdFromOrigin = yield* git.getFileContentAt("origin/confluence", deletedPath).pipe(Effect.map((content) => {
616
692
  const match = content.match(/pageId:\s*['"]?(\d+)['"]?/);
617
693
  return match ? match[1] : null;
618
- }), Effect.catchAll(() => Effect.succeed(null)));
694
+ }), Effect.catchIf(() => true, () => Effect.succeed(null)));
619
695
  if (pageIdFromOrigin) {
620
- yield* client.deletePage(PageId(pageIdFromOrigin)).pipe(Effect.tap(() => Effect.sync(() => deleted++)), Effect.catchAll((error) => {
696
+ yield* client.deletePage(PageId(pageIdFromOrigin)).pipe(Effect.tap(() => Effect.sync(() => deleted++)), Effect.catchIf(() => true, (error) => {
621
697
  errors.push(`Failed to delete page ${pageIdFromOrigin}: ${error.message}`);
622
698
  return Effect.void;
623
699
  }));
@@ -625,7 +701,7 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
625
701
  }
626
702
  }
627
703
  for (const filePath of sortedFiles) {
628
- const result = yield* pushFile(filePath, revisionMessage, spaceId, pageIdMap).pipe(Effect.catchAll((error) => Effect.succeed({
704
+ const result = yield* pushFile(filePath, revisionMessage, spaceId, pageIdMap).pipe(Effect.catchIf(() => true, (error) => Effect.succeed({
629
705
  pushed: false,
630
706
  created: false,
631
707
  error: `Failed to push ${filePath}: ${error._tag}`
@@ -639,7 +715,7 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
639
715
  }
640
716
  // Amend the last commit with canonical content
641
717
  yield* git.addAll();
642
- yield* git.amend({ noEdit: true }).pipe(Effect.catchAll(() => Effect.void));
718
+ yield* git.amend({ noEdit: true }).pipe(Effect.catchIf(() => true, () => Effect.void));
643
719
  // Two-branch model: update origin/confluence to match HEAD
644
720
  if (hasRemoteBranch) {
645
721
  yield* git.updateBranch("origin/confluence", "HEAD");
@@ -665,13 +741,13 @@ export const layer = Layer.effect(SyncEngine, Effect.gen(function* () {
665
741
  const fm = localFile.frontMatter;
666
742
  const currentHash = yield* computeHash(localFile.content).pipe(Effect.provide(HashServiceLive));
667
743
  // Fetch remote page
668
- const remotePage = yield* Effect.either(client.getPage(fm.pageId));
669
- if (remotePage._tag === "Left") {
744
+ const remotePage = yield* Effect.result(client.getPage(fm.pageId));
745
+ if (Result.isFailure(remotePage)) {
670
746
  statuses.push({ _tag: "LocalOnly", path: filePath, title: fm.title });
671
747
  localOnly++;
672
748
  continue;
673
749
  }
674
- const page = remotePage.right;
750
+ const page = remotePage.success;
675
751
  const localChanged = currentHash !== fm.contentHash;
676
752
  const remoteChanged = page.version.number > fm.version;
677
753
  if (localChanged && remoteChanged) {