@knpkv/confluence-to-markdown 0.5.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 (395) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +58 -14
  3. package/dist/AdfPlaceholders.d.ts +42 -0
  4. package/dist/AdfPlaceholders.d.ts.map +1 -0
  5. package/dist/AdfPlaceholders.js +547 -0
  6. package/dist/AdfPlaceholders.js.map +1 -0
  7. package/dist/AdfSchemaValidator.d.ts +37 -0
  8. package/dist/AdfSchemaValidator.d.ts.map +1 -0
  9. package/dist/AdfSchemaValidator.js +37 -0
  10. package/dist/AdfSchemaValidator.js.map +1 -0
  11. package/dist/AdfWalker.d.ts +39 -0
  12. package/dist/AdfWalker.d.ts.map +1 -0
  13. package/dist/AdfWalker.js +527 -0
  14. package/dist/AdfWalker.js.map +1 -0
  15. package/dist/AtlaskitTransformers.d.ts +35 -0
  16. package/dist/AtlaskitTransformers.d.ts.map +1 -0
  17. package/dist/AtlaskitTransformers.js +48 -0
  18. package/dist/AtlaskitTransformers.js.map +1 -0
  19. package/dist/Brand.d.ts +6 -6
  20. package/dist/Brand.d.ts.map +1 -1
  21. package/dist/Brand.js +8 -6
  22. package/dist/Brand.js.map +1 -1
  23. package/dist/ConfluenceAuth.d.ts +4 -4
  24. package/dist/ConfluenceAuth.d.ts.map +1 -1
  25. package/dist/ConfluenceAuth.js +15 -27
  26. package/dist/ConfluenceAuth.js.map +1 -1
  27. package/dist/ConfluenceClient.d.ts +4 -4
  28. package/dist/ConfluenceClient.d.ts.map +1 -1
  29. package/dist/ConfluenceClient.js +21 -14
  30. package/dist/ConfluenceClient.js.map +1 -1
  31. package/dist/ConfluenceConfig.d.ts +3 -3
  32. package/dist/ConfluenceConfig.d.ts.map +1 -1
  33. package/dist/ConfluenceConfig.js +13 -11
  34. package/dist/ConfluenceConfig.js.map +1 -1
  35. package/dist/ConfluenceError.d.ts +56 -4
  36. package/dist/ConfluenceError.d.ts.map +1 -1
  37. package/dist/ConfluenceError.js +30 -1
  38. package/dist/ConfluenceError.js.map +1 -1
  39. package/dist/GitService.d.ts +11 -3
  40. package/dist/GitService.d.ts.map +1 -1
  41. package/dist/GitService.js +19 -27
  42. package/dist/GitService.js.map +1 -1
  43. package/dist/LocalFileSystem.d.ts +3 -3
  44. package/dist/LocalFileSystem.d.ts.map +1 -1
  45. package/dist/LocalFileSystem.js +6 -6
  46. package/dist/LocalFileSystem.js.map +1 -1
  47. package/dist/MarkdownConverter.d.ts +16 -65
  48. package/dist/MarkdownConverter.d.ts.map +1 -1
  49. package/dist/MarkdownConverter.js +64 -85
  50. package/dist/MarkdownConverter.js.map +1 -1
  51. package/dist/Schemas.d.ts +128 -141
  52. package/dist/Schemas.d.ts.map +1 -1
  53. package/dist/Schemas.js +21 -23
  54. package/dist/Schemas.js.map +1 -1
  55. package/dist/SyncEngine.d.ts +8 -5
  56. package/dist/SyncEngine.d.ts.map +1 -1
  57. package/dist/SyncEngine.js +189 -113
  58. package/dist/SyncEngine.js.map +1 -1
  59. package/dist/bin.js +23 -35
  60. package/dist/bin.js.map +1 -1
  61. package/dist/commands/auth.d.ts +2 -14
  62. package/dist/commands/auth.d.ts.map +1 -1
  63. package/dist/commands/auth.js +11 -16
  64. package/dist/commands/auth.js.map +1 -1
  65. package/dist/commands/clone.d.ts +4 -6
  66. package/dist/commands/clone.d.ts.map +1 -1
  67. package/dist/commands/clone.js +34 -32
  68. package/dist/commands/clone.js.map +1 -1
  69. package/dist/commands/delete.d.ts +2 -10
  70. package/dist/commands/delete.d.ts.map +1 -1
  71. package/dist/commands/delete.js +5 -4
  72. package/dist/commands/delete.js.map +1 -1
  73. package/dist/commands/errorHandler.d.ts +2 -1
  74. package/dist/commands/errorHandler.d.ts.map +1 -1
  75. package/dist/commands/errorHandler.js +22 -15
  76. package/dist/commands/errorHandler.js.map +1 -1
  77. package/dist/commands/fetch.d.ts +27 -0
  78. package/dist/commands/fetch.d.ts.map +1 -0
  79. package/dist/commands/fetch.js +48 -0
  80. package/dist/commands/fetch.js.map +1 -0
  81. package/dist/commands/git.d.ts +7 -10
  82. package/dist/commands/git.d.ts.map +1 -1
  83. package/dist/commands/git.js +6 -6
  84. package/dist/commands/git.js.map +1 -1
  85. package/dist/commands/index.d.ts +1 -0
  86. package/dist/commands/index.d.ts.map +1 -1
  87. package/dist/commands/index.js +1 -0
  88. package/dist/commands/index.js.map +1 -1
  89. package/dist/commands/layers.d.ts +10 -9
  90. package/dist/commands/layers.d.ts.map +1 -1
  91. package/dist/commands/layers.js +41 -30
  92. package/dist/commands/layers.js.map +1 -1
  93. package/dist/commands/new.d.ts +2 -6
  94. package/dist/commands/new.d.ts.map +1 -1
  95. package/dist/commands/new.js +5 -4
  96. package/dist/commands/new.js.map +1 -1
  97. package/dist/commands/pageInput.d.ts +19 -0
  98. package/dist/commands/pageInput.d.ts.map +1 -0
  99. package/dist/commands/pageInput.js +68 -0
  100. package/dist/commands/pageInput.js.map +1 -0
  101. package/dist/commands/root.d.ts +8 -0
  102. package/dist/commands/root.d.ts.map +1 -0
  103. package/dist/commands/root.js +29 -0
  104. package/dist/commands/root.js.map +1 -0
  105. package/dist/commands/sync.d.ts +6 -9
  106. package/dist/commands/sync.d.ts.map +1 -1
  107. package/dist/commands/sync.js +5 -6
  108. package/dist/commands/sync.js.map +1 -1
  109. package/dist/index.d.ts +3 -8
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js +2 -13
  112. package/dist/index.js.map +1 -1
  113. package/dist/internal/NodeLayers.d.ts.map +1 -1
  114. package/dist/internal/NodeLayers.js +1 -2
  115. package/dist/internal/NodeLayers.js.map +1 -1
  116. package/dist/internal/adfMetadata.d.ts +30 -0
  117. package/dist/internal/adfMetadata.d.ts.map +1 -0
  118. package/dist/internal/adfMetadata.js +126 -0
  119. package/dist/internal/adfMetadata.js.map +1 -0
  120. package/dist/internal/cleanMarkdown.d.ts +5 -0
  121. package/dist/internal/cleanMarkdown.d.ts.map +1 -0
  122. package/dist/internal/cleanMarkdown.js +13 -0
  123. package/dist/internal/cleanMarkdown.js.map +1 -0
  124. package/dist/internal/frontmatter.d.ts.map +1 -1
  125. package/dist/internal/frontmatter.js +41 -8
  126. package/dist/internal/frontmatter.js.map +1 -1
  127. package/dist/internal/gitCommands.d.ts +9 -3
  128. package/dist/internal/gitCommands.d.ts.map +1 -1
  129. package/dist/internal/gitCommands.js +18 -9
  130. package/dist/internal/gitCommands.js.map +1 -1
  131. package/dist/internal/hashUtils.d.ts +1 -1
  132. package/dist/internal/hashUtils.d.ts.map +1 -1
  133. package/dist/internal/hashUtils.js +1 -1
  134. package/dist/internal/hashUtils.js.map +1 -1
  135. package/dist/internal/oauthServer.d.ts +10 -5
  136. package/dist/internal/oauthServer.d.ts.map +1 -1
  137. package/dist/internal/oauthServer.js +19 -40
  138. package/dist/internal/oauthServer.js.map +1 -1
  139. package/dist/internal/pathUtils.d.ts +1 -1
  140. package/dist/internal/pathUtils.d.ts.map +1 -1
  141. package/dist/internal/pathUtils.js +1 -1
  142. package/dist/internal/pathUtils.js.map +1 -1
  143. package/dist/internal/process.d.ts +15 -0
  144. package/dist/internal/process.d.ts.map +1 -0
  145. package/dist/internal/process.js +10 -0
  146. package/dist/internal/process.js.map +1 -0
  147. package/dist/internal/stdio.d.ts +6 -0
  148. package/dist/internal/stdio.d.ts.map +1 -0
  149. package/dist/internal/stdio.js +15 -0
  150. package/dist/internal/stdio.js.map +1 -0
  151. package/dist/internal/tokenStorage.d.ts +3 -13
  152. package/dist/internal/tokenStorage.d.ts.map +1 -1
  153. package/dist/internal/tokenStorage.js +26 -24
  154. package/dist/internal/tokenStorage.js.map +1 -1
  155. package/dist/internal/userCache.d.ts +1 -1
  156. package/dist/internal/userCache.d.ts.map +1 -1
  157. package/dist/internal/userCache.js +1 -1
  158. package/dist/internal/userCache.js.map +1 -1
  159. package/package.json +29 -20
  160. package/skills/confluence/SKILL.md +143 -0
  161. package/skills/confluence/agents/openai.yaml +4 -0
  162. package/src/AdfPlaceholders.ts +563 -0
  163. package/src/AdfSchemaValidator.ts +65 -0
  164. package/src/AdfWalker.ts +591 -0
  165. package/src/AtlaskitTransformers.ts +70 -0
  166. package/src/Brand.ts +11 -16
  167. package/src/ConfluenceAuth.ts +22 -30
  168. package/src/ConfluenceClient.ts +28 -24
  169. package/src/ConfluenceConfig.ts +14 -14
  170. package/src/ConfluenceError.ts +65 -3
  171. package/src/GitService.ts +39 -49
  172. package/src/LocalFileSystem.ts +7 -9
  173. package/src/MarkdownConverter.ts +108 -143
  174. package/src/Schemas.ts +17 -16
  175. package/src/SyncEngine.ts +272 -127
  176. package/src/atlaskit-adf-schema.d.ts +3 -0
  177. package/src/bin.ts +30 -56
  178. package/src/commands/auth.ts +21 -18
  179. package/src/commands/clone.ts +46 -38
  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 +64 -37
  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/index.ts +3 -18
  191. package/src/internal/NodeLayers.ts +1 -2
  192. package/src/internal/adfMetadata.ts +145 -0
  193. package/src/internal/cleanMarkdown.ts +15 -0
  194. package/src/internal/frontmatter.ts +45 -8
  195. package/src/internal/gitCommands.ts +23 -17
  196. package/src/internal/hashUtils.ts +2 -2
  197. package/src/internal/oauthServer.ts +84 -105
  198. package/src/internal/pathUtils.ts +1 -1
  199. package/src/internal/process.ts +15 -0
  200. package/src/internal/stdio.ts +22 -0
  201. package/src/internal/tokenStorage.ts +39 -29
  202. package/src/internal/userCache.ts +2 -2
  203. package/test/AdfPlaceholders.test.ts +508 -0
  204. package/test/AdfSchemaValidator.test.ts +34 -0
  205. package/test/AdfWalker.test.ts +676 -0
  206. package/test/AtlaskitTransformers.test.ts +25 -0
  207. package/test/Brand.test.ts +11 -11
  208. package/test/GitService.test.ts +6 -2
  209. package/test/MarkdownConverter.test.ts +121 -105
  210. package/test/RoundTrip.test.ts +521 -0
  211. package/test/Schemas.test.ts +40 -40
  212. package/test/adfMetadata.test.ts +110 -0
  213. package/test/cleanMarkdown.test.ts +36 -0
  214. package/test/commandHarness.test.ts +79 -0
  215. package/test/commandHarness.ts +147 -0
  216. package/test/fetch.test.ts +61 -0
  217. package/test/frontmatter.test.ts +41 -0
  218. package/test/integration.test.ts +569 -156
  219. package/test/layers.test.ts +12 -0
  220. package/test/oauthServer.test.ts +4 -5
  221. package/test/pageInput.test.ts +83 -0
  222. package/test/tokenStorage.test.ts +17 -17
  223. package/dist/SchemaConverterError.d.ts +0 -108
  224. package/dist/SchemaConverterError.d.ts.map +0 -1
  225. package/dist/SchemaConverterError.js +0 -84
  226. package/dist/SchemaConverterError.js.map +0 -1
  227. package/dist/ast/BlockNode.d.ts +0 -453
  228. package/dist/ast/BlockNode.d.ts.map +0 -1
  229. package/dist/ast/BlockNode.js +0 -310
  230. package/dist/ast/BlockNode.js.map +0 -1
  231. package/dist/ast/Document.d.ts +0 -216
  232. package/dist/ast/Document.d.ts.map +0 -1
  233. package/dist/ast/Document.js +0 -69
  234. package/dist/ast/Document.js.map +0 -1
  235. package/dist/ast/InlineNode.d.ts +0 -477
  236. package/dist/ast/InlineNode.d.ts.map +0 -1
  237. package/dist/ast/InlineNode.js +0 -263
  238. package/dist/ast/InlineNode.js.map +0 -1
  239. package/dist/ast/MacroNode.d.ts +0 -267
  240. package/dist/ast/MacroNode.d.ts.map +0 -1
  241. package/dist/ast/MacroNode.js +0 -164
  242. package/dist/ast/MacroNode.js.map +0 -1
  243. package/dist/ast/index.d.ts +0 -10
  244. package/dist/ast/index.d.ts.map +0 -1
  245. package/dist/ast/index.js +0 -14
  246. package/dist/ast/index.js.map +0 -1
  247. package/dist/parsers/ConfluenceParser.d.ts +0 -26
  248. package/dist/parsers/ConfluenceParser.d.ts.map +0 -1
  249. package/dist/parsers/ConfluenceParser.js +0 -797
  250. package/dist/parsers/ConfluenceParser.js.map +0 -1
  251. package/dist/parsers/MarkdownParser.d.ts +0 -26
  252. package/dist/parsers/MarkdownParser.d.ts.map +0 -1
  253. package/dist/parsers/MarkdownParser.js +0 -982
  254. package/dist/parsers/MarkdownParser.js.map +0 -1
  255. package/dist/parsers/index.d.ts +0 -8
  256. package/dist/parsers/index.d.ts.map +0 -1
  257. package/dist/parsers/index.js +0 -8
  258. package/dist/parsers/index.js.map +0 -1
  259. package/dist/schemas/ConfluenceSchema.d.ts +0 -21
  260. package/dist/schemas/ConfluenceSchema.d.ts.map +0 -1
  261. package/dist/schemas/ConfluenceSchema.js +0 -38
  262. package/dist/schemas/ConfluenceSchema.js.map +0 -1
  263. package/dist/schemas/ConversionSchema.d.ts +0 -35
  264. package/dist/schemas/ConversionSchema.d.ts.map +0 -1
  265. package/dist/schemas/ConversionSchema.js +0 -208
  266. package/dist/schemas/ConversionSchema.js.map +0 -1
  267. package/dist/schemas/MarkdownSchema.d.ts +0 -21
  268. package/dist/schemas/MarkdownSchema.d.ts.map +0 -1
  269. package/dist/schemas/MarkdownSchema.js +0 -38
  270. package/dist/schemas/MarkdownSchema.js.map +0 -1
  271. package/dist/schemas/hast/HastFromHtml.d.ts +0 -27
  272. package/dist/schemas/hast/HastFromHtml.d.ts.map +0 -1
  273. package/dist/schemas/hast/HastFromHtml.js +0 -107
  274. package/dist/schemas/hast/HastFromHtml.js.map +0 -1
  275. package/dist/schemas/hast/HastSchema.d.ts +0 -195
  276. package/dist/schemas/hast/HastSchema.d.ts.map +0 -1
  277. package/dist/schemas/hast/HastSchema.js +0 -183
  278. package/dist/schemas/hast/HastSchema.js.map +0 -1
  279. package/dist/schemas/hast/index.d.ts +0 -9
  280. package/dist/schemas/hast/index.d.ts.map +0 -1
  281. package/dist/schemas/hast/index.js +0 -3
  282. package/dist/schemas/hast/index.js.map +0 -1
  283. package/dist/schemas/index.d.ts +0 -14
  284. package/dist/schemas/index.d.ts.map +0 -1
  285. package/dist/schemas/index.js +0 -16
  286. package/dist/schemas/index.js.map +0 -1
  287. package/dist/schemas/mdast/MdastFromMarkdown.d.ts +0 -30
  288. package/dist/schemas/mdast/MdastFromMarkdown.d.ts.map +0 -1
  289. package/dist/schemas/mdast/MdastFromMarkdown.js +0 -79
  290. package/dist/schemas/mdast/MdastFromMarkdown.js.map +0 -1
  291. package/dist/schemas/mdast/MdastSchema.d.ts +0 -385
  292. package/dist/schemas/mdast/MdastSchema.d.ts.map +0 -1
  293. package/dist/schemas/mdast/MdastSchema.js +0 -266
  294. package/dist/schemas/mdast/MdastSchema.js.map +0 -1
  295. package/dist/schemas/mdast/index.d.ts +0 -10
  296. package/dist/schemas/mdast/index.d.ts.map +0 -1
  297. package/dist/schemas/mdast/index.js +0 -4
  298. package/dist/schemas/mdast/index.js.map +0 -1
  299. package/dist/schemas/mdast/mdastToString.d.ts +0 -13
  300. package/dist/schemas/mdast/mdastToString.d.ts.map +0 -1
  301. package/dist/schemas/mdast/mdastToString.js +0 -85
  302. package/dist/schemas/mdast/mdastToString.js.map +0 -1
  303. package/dist/schemas/nodes/block/BlockSchema.d.ts +0 -43
  304. package/dist/schemas/nodes/block/BlockSchema.d.ts.map +0 -1
  305. package/dist/schemas/nodes/block/BlockSchema.js +0 -634
  306. package/dist/schemas/nodes/block/BlockSchema.js.map +0 -1
  307. package/dist/schemas/nodes/block/index.d.ts +0 -7
  308. package/dist/schemas/nodes/block/index.d.ts.map +0 -1
  309. package/dist/schemas/nodes/block/index.js +0 -7
  310. package/dist/schemas/nodes/block/index.js.map +0 -1
  311. package/dist/schemas/nodes/index.d.ts +0 -9
  312. package/dist/schemas/nodes/index.d.ts.map +0 -1
  313. package/dist/schemas/nodes/index.js +0 -12
  314. package/dist/schemas/nodes/index.js.map +0 -1
  315. package/dist/schemas/nodes/inline/InlineSchema.d.ts +0 -48
  316. package/dist/schemas/nodes/inline/InlineSchema.d.ts.map +0 -1
  317. package/dist/schemas/nodes/inline/InlineSchema.js +0 -436
  318. package/dist/schemas/nodes/inline/InlineSchema.js.map +0 -1
  319. package/dist/schemas/nodes/inline/index.d.ts +0 -7
  320. package/dist/schemas/nodes/inline/index.d.ts.map +0 -1
  321. package/dist/schemas/nodes/inline/index.js +0 -7
  322. package/dist/schemas/nodes/inline/index.js.map +0 -1
  323. package/dist/schemas/nodes/macro/MacroSchema.d.ts +0 -27
  324. package/dist/schemas/nodes/macro/MacroSchema.d.ts.map +0 -1
  325. package/dist/schemas/nodes/macro/MacroSchema.js +0 -162
  326. package/dist/schemas/nodes/macro/MacroSchema.js.map +0 -1
  327. package/dist/schemas/nodes/macro/index.d.ts +0 -7
  328. package/dist/schemas/nodes/macro/index.d.ts.map +0 -1
  329. package/dist/schemas/nodes/macro/index.js +0 -7
  330. package/dist/schemas/nodes/macro/index.js.map +0 -1
  331. package/dist/schemas/preprocessing/ConfluencePreprocessor.d.ts +0 -24
  332. package/dist/schemas/preprocessing/ConfluencePreprocessor.d.ts.map +0 -1
  333. package/dist/schemas/preprocessing/ConfluencePreprocessor.js +0 -359
  334. package/dist/schemas/preprocessing/ConfluencePreprocessor.js.map +0 -1
  335. package/dist/schemas/preprocessing/index.d.ts +0 -8
  336. package/dist/schemas/preprocessing/index.d.ts.map +0 -1
  337. package/dist/schemas/preprocessing/index.js +0 -2
  338. package/dist/schemas/preprocessing/index.js.map +0 -1
  339. package/dist/serializers/ConfluenceSerializer.d.ts +0 -30
  340. package/dist/serializers/ConfluenceSerializer.d.ts.map +0 -1
  341. package/dist/serializers/ConfluenceSerializer.js +0 -560
  342. package/dist/serializers/ConfluenceSerializer.js.map +0 -1
  343. package/dist/serializers/MarkdownSerializer.d.ts +0 -34
  344. package/dist/serializers/MarkdownSerializer.d.ts.map +0 -1
  345. package/dist/serializers/MarkdownSerializer.js +0 -395
  346. package/dist/serializers/MarkdownSerializer.js.map +0 -1
  347. package/dist/serializers/index.d.ts +0 -8
  348. package/dist/serializers/index.d.ts.map +0 -1
  349. package/dist/serializers/index.js +0 -8
  350. package/dist/serializers/index.js.map +0 -1
  351. package/src/SchemaConverterError.ts +0 -108
  352. package/src/ast/BlockNode.ts +0 -469
  353. package/src/ast/Document.ts +0 -90
  354. package/src/ast/InlineNode.ts +0 -323
  355. package/src/ast/MacroNode.ts +0 -245
  356. package/src/ast/index.ts +0 -83
  357. package/src/parsers/ConfluenceParser.ts +0 -956
  358. package/src/parsers/MarkdownParser.ts +0 -1338
  359. package/src/parsers/index.ts +0 -8
  360. package/src/schemas/ConfluenceSchema.ts +0 -56
  361. package/src/schemas/ConversionSchema.ts +0 -318
  362. package/src/schemas/MarkdownSchema.ts +0 -56
  363. package/src/schemas/hast/HastFromHtml.ts +0 -153
  364. package/src/schemas/hast/HastSchema.ts +0 -274
  365. package/src/schemas/hast/index.ts +0 -35
  366. package/src/schemas/index.ts +0 -20
  367. package/src/schemas/mdast/MdastFromMarkdown.ts +0 -118
  368. package/src/schemas/mdast/MdastSchema.ts +0 -566
  369. package/src/schemas/mdast/index.ts +0 -59
  370. package/src/schemas/mdast/mdastToString.ts +0 -102
  371. package/src/schemas/nodes/block/BlockSchema.ts +0 -773
  372. package/src/schemas/nodes/block/index.ts +0 -13
  373. package/src/schemas/nodes/index.ts +0 -20
  374. package/src/schemas/nodes/inline/InlineSchema.ts +0 -523
  375. package/src/schemas/nodes/inline/index.ts +0 -14
  376. package/src/schemas/nodes/macro/MacroSchema.ts +0 -226
  377. package/src/schemas/nodes/macro/index.ts +0 -6
  378. package/src/schemas/preprocessing/ConfluencePreprocessor.ts +0 -455
  379. package/src/schemas/preprocessing/index.ts +0 -8
  380. package/src/serializers/ConfluenceSerializer.ts +0 -737
  381. package/src/serializers/MarkdownSerializer.ts +0 -543
  382. package/src/serializers/index.ts +0 -8
  383. package/test/ast/BlockNode.test.ts +0 -265
  384. package/test/ast/Document.test.ts +0 -126
  385. package/test/ast/InlineNode.test.ts +0 -161
  386. package/test/fixtures/integration-test.html.fixture +0 -103
  387. package/test/fixtures/integration-test.md.expected +0 -257
  388. package/test/parsers/ConfluenceParser.test.ts +0 -452
  389. package/test/schemas/ConfluencePreprocessor.test.ts +0 -180
  390. package/test/schemas/ConversionSchema.test.ts +0 -159
  391. package/test/schemas/HastSchema.test.ts +0 -138
  392. package/test/schemas/MdastSchema.test.ts +0 -145
  393. package/test/schemas/nodes/block/BlockSchema.test.ts +0 -173
  394. package/test/schemas/nodes/inline/InlineSchema.test.ts +0 -198
  395. package/test/schemas/nodes/macro/MacroSchema.test.ts +0 -142
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import * as Effect from "effect/Effect"
8
8
  import * as Schema from "effect/Schema"
9
- import matter from "gray-matter"
9
+ import * as yaml from "js-yaml"
10
10
  import { FrontMatterError } from "../ConfluenceError.js"
11
11
  import type { NewPageFrontMatter, PageFrontMatter } from "../Schemas.js"
12
12
  import { NewPageFrontMatterSchema, PageFrontMatterSchema } from "../Schemas.js"
@@ -20,6 +20,33 @@ export interface ParsedMarkdown {
20
20
  readonly isNew: boolean
21
21
  }
22
22
 
23
+ const parseRawMarkdown = (content: string): { readonly data: Record<string, unknown>; readonly content: string } => {
24
+ if (!content.startsWith("---\n") && !content.startsWith("---\r\n")) {
25
+ return { data: {}, content }
26
+ }
27
+
28
+ const newline = content.startsWith("---\r\n") ? "\r\n" : "\n"
29
+ const headerStart = 3 + newline.length
30
+ const closingMarker = `${newline}---`
31
+ const closingStart = content.indexOf(closingMarker, headerStart)
32
+ if (closingStart === -1) {
33
+ return { data: {}, content }
34
+ }
35
+
36
+ const header = content.slice(headerStart, closingStart)
37
+ const afterClosingStart = closingStart + closingMarker.length
38
+ const afterClosing = content.startsWith("\r\n", afterClosingStart)
39
+ ? content.slice(afterClosingStart + 2)
40
+ : content.startsWith("\n", afterClosingStart)
41
+ ? content.slice(afterClosingStart + 1)
42
+ : content.slice(afterClosingStart)
43
+ const loaded = yaml.load(header)
44
+ const data = loaded !== null && typeof loaded === "object" && !Array.isArray(loaded)
45
+ ? loaded as Record<string, unknown>
46
+ : {}
47
+ return { data, content: afterClosing }
48
+ }
49
+
23
50
  /**
24
51
  * Parse a markdown file with YAML front-matter.
25
52
  *
@@ -35,7 +62,7 @@ export const parseMarkdown = (
35
62
  ): Effect.Effect<ParsedMarkdown, FrontMatterError> =>
36
63
  Effect.gen(function*() {
37
64
  const parsed = yield* Effect.try({
38
- try: () => matter(content),
65
+ try: () => parseRawMarkdown(content),
39
66
  catch: (cause) => new FrontMatterError({ path: filePath, cause })
40
67
  })
41
68
 
@@ -49,21 +76,21 @@ export const parseMarkdown = (
49
76
  }
50
77
 
51
78
  // Try to parse as existing page front-matter
52
- const existingResult = yield* Schema.decodeUnknown(PageFrontMatterSchema)(parsed.data).pipe(
79
+ const existingResult = yield* Schema.decodeUnknownEffect(PageFrontMatterSchema)(parsed.data).pipe(
53
80
  Effect.map((fm) => ({
54
81
  frontMatter: fm,
55
82
  content: parsed.content.trim(),
56
83
  isNew: false
57
84
  })),
58
- Effect.catchAll(() =>
85
+ Effect.catchCause(() =>
59
86
  // Try to parse as new page front-matter
60
- Schema.decodeUnknown(NewPageFrontMatterSchema)(parsed.data).pipe(
87
+ Schema.decodeUnknownEffect(NewPageFrontMatterSchema)(parsed.data).pipe(
61
88
  Effect.map((fm) => ({
62
89
  frontMatter: fm as NewPageFrontMatter,
63
90
  content: parsed.content.trim(),
64
91
  isNew: true
65
92
  })),
66
- Effect.catchAll((cause) => Effect.fail(new FrontMatterError({ path: filePath, cause })))
93
+ Effect.catchCause((cause) => Effect.fail(new FrontMatterError({ path: filePath, cause })))
67
94
  )
68
95
  )
69
96
  )
@@ -94,7 +121,7 @@ export const serializeMarkdown = (
94
121
  contentHash: frontMatter.contentHash
95
122
  }
96
123
 
97
- return matter.stringify(content, fm)
124
+ return stringifyFrontmatter(content, fm)
98
125
  }
99
126
 
100
127
  /**
@@ -115,5 +142,15 @@ export const serializeNewPageMarkdown = (
115
142
  ...(frontMatter.parentId !== undefined ? { parentId: frontMatter.parentId } : {})
116
143
  }
117
144
 
118
- return matter.stringify(content, fm)
145
+ return stringifyFrontmatter(content, fm)
146
+ }
147
+
148
+ const stringifyFrontmatter = (content: string, frontMatter: Record<string, unknown>): string => {
149
+ const header = yaml.dump(frontMatter, {
150
+ lineWidth: -1,
151
+ noRefs: true,
152
+ sortKeys: false
153
+ }).trimEnd()
154
+ const body = content.endsWith("\n") ? content : `${content}\n`
155
+ return `---\n${header}\n---\n${body}`
119
156
  }
@@ -4,11 +4,10 @@
4
4
  * @module
5
5
  * @internal
6
6
  */
7
- import * as Command from "@effect/platform/Command"
8
- import type * as CommandExecutor from "@effect/platform/CommandExecutor"
9
- import type * as PlatformError from "@effect/platform/Error"
10
7
  import * as Effect from "effect/Effect"
11
- import * as String from "effect/String"
8
+ import * as EffectString from "effect/String"
9
+ import { ChildProcessSpawner } from "effect/unstable/process"
10
+ import * as ChildProcess from "effect/unstable/process/ChildProcess"
12
11
  import { GitError, GitNotInstalledError } from "../GitError.js"
13
12
 
14
13
  /**
@@ -48,17 +47,26 @@ export interface GitLogEntry {
48
47
  * Convert PlatformError to GitError or GitNotInstalledError.
49
48
  */
50
49
  const mapPlatformError = (
51
- error: PlatformError.PlatformError,
50
+ error: unknown,
52
51
  commandStr: string
53
52
  ): GitError | GitNotInstalledError => {
54
- if (error._tag === "SystemError" && error.reason === "NotFound") {
53
+ if (
54
+ typeof error === "object"
55
+ && error !== null
56
+ && "_tag" in error
57
+ && "reason" in error
58
+ && error._tag === "SystemError"
59
+ && error.reason === "NotFound"
60
+ ) {
61
+ const message = "message" in error ? globalThis.String(error.message) : "command not found"
55
62
  return new GitNotInstalledError({
56
- message: `Git not found: ${error.message}. Please install git.`
63
+ message: `Git not found: ${message}. Please install git.`
57
64
  })
58
65
  }
66
+ const message = error instanceof Error ? error.message : globalThis.String(error)
59
67
  return new GitError({
60
68
  command: commandStr,
61
- message: error.message
69
+ message
62
70
  })
63
71
  }
64
72
 
@@ -74,15 +82,13 @@ const mapPlatformError = (
74
82
  export const runGit = (
75
83
  args: ReadonlyArray<string>,
76
84
  cwd: string
77
- ): Effect.Effect<string, GitError | GitNotInstalledError, CommandExecutor.CommandExecutor> =>
85
+ ): Effect.Effect<string, GitError | GitNotInstalledError, ChildProcessSpawner.ChildProcessSpawner> =>
78
86
  Effect.gen(function*() {
79
- const command = Command.make("git", ...args).pipe(
80
- Command.workingDirectory(cwd)
81
- )
82
-
87
+ const spawner = yield* ChildProcessSpawner.ChildProcessSpawner
88
+ const command = ChildProcess.make("git", ["-C", cwd, ...args])
83
89
  const commandStr = `git ${args.join(" ")}`
84
90
 
85
- const result = yield* Command.string(command).pipe(
91
+ const result = yield* spawner.string(command).pipe(
86
92
  Effect.mapError((error) => mapPlatformError(error, commandStr))
87
93
  )
88
94
 
@@ -98,7 +104,7 @@ export const runGit = (
98
104
  export const runGitAllowEmpty = (
99
105
  args: ReadonlyArray<string>,
100
106
  cwd: string
101
- ): Effect.Effect<string, GitError | GitNotInstalledError, CommandExecutor.CommandExecutor> =>
107
+ ): Effect.Effect<string, GitError | GitNotInstalledError, ChildProcessSpawner.ChildProcessSpawner> =>
102
108
  runGit(args, cwd).pipe(
103
109
  Effect.catchIf(
104
110
  (e): e is GitError => e._tag === "GitError",
@@ -115,7 +121,7 @@ export const runGitAllowEmpty = (
115
121
  * @internal
116
122
  */
117
123
  export const parseGitStatus = (output: string): ReadonlyArray<GitStatusEntry> => {
118
- if (String.isEmpty(output.trim())) {
124
+ if (EffectString.isEmpty(output.trim())) {
119
125
  return []
120
126
  }
121
127
 
@@ -171,7 +177,7 @@ const parseStatusCode = (code: string): GitFileStatus => {
171
177
  * @internal
172
178
  */
173
179
  export const parseGitLog = (output: string): ReadonlyArray<GitLogEntry> => {
174
- if (String.isEmpty(output.trim())) {
180
+ if (EffectString.isEmpty(output.trim())) {
175
181
  return []
176
182
  }
177
183
 
@@ -24,10 +24,10 @@ export interface HashService {
24
24
  *
25
25
  * @category Services
26
26
  */
27
- export class HashServiceTag extends Context.Tag("@knpkv/confluence-to-markdown/HashService")<
27
+ export class HashServiceTag extends Context.Service<
28
28
  HashServiceTag,
29
29
  HashService
30
- >() {}
30
+ >()("@knpkv/confluence-to-markdown/HashService") {}
31
31
 
32
32
  /**
33
33
  * Create a HashService layer from a hash function.
@@ -3,20 +3,20 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- import * as HttpRouter from "@effect/platform/HttpRouter"
7
- import * as HttpServer from "@effect/platform/HttpServer"
8
- import type { ServeError } from "@effect/platform/HttpServerError"
9
- import * as HttpServerRequest from "@effect/platform/HttpServerRequest"
10
- import * as HttpServerResponse from "@effect/platform/HttpServerResponse"
11
6
  import * as Context from "effect/Context"
12
7
  import * as Deferred from "effect/Deferred"
13
8
  import * as Effect from "effect/Effect"
9
+ import * as Exit from "effect/Exit"
14
10
  import * as Fiber from "effect/Fiber"
15
11
  import * as Layer from "effect/Layer"
12
+ import * as Scope from "effect/Scope"
13
+ import type { HttpServerError } from "effect/unstable/http"
14
+ import { HttpRouter, HttpServer, HttpServerRequest, HttpServerResponse } from "effect/unstable/http"
16
15
  import { OAuthError } from "../ConfluenceError.js"
17
16
 
18
17
  const DEFAULT_PORT = 8585
19
- const MAX_PORT_ATTEMPTS = 10
18
+ const MAX_PORT = 8594
19
+ type HttpServerInstance = Effect.Success<typeof HttpServer.HttpServer>
20
20
 
21
21
  /**
22
22
  * Factory service for creating HTTP servers.
@@ -27,7 +27,7 @@ const MAX_PORT_ATTEMPTS = 10
27
27
  export interface HttpServerFactory {
28
28
  readonly createServerLayer: (port: number) => Layer.Layer<
29
29
  HttpServer.HttpServer,
30
- ServeError,
30
+ HttpServerError.ServeError,
31
31
  never
32
32
  >
33
33
  }
@@ -37,10 +37,10 @@ export interface HttpServerFactory {
37
37
  *
38
38
  * @category Services
39
39
  */
40
- export class HttpServerFactoryTag extends Context.Tag("@knpkv/confluence-to-markdown/HttpServerFactory")<
40
+ export class HttpServerFactoryTag extends Context.Service<
41
41
  HttpServerFactoryTag,
42
42
  HttpServerFactory
43
- >() {}
43
+ >()("@knpkv/confluence-to-markdown/HttpServerFactory") {}
44
44
 
45
45
  /**
46
46
  * Create a HttpServerFactory layer from a layer factory function.
@@ -52,51 +52,12 @@ export class HttpServerFactoryTag extends Context.Tag("@knpkv/confluence-to-mark
52
52
  * @category Layers
53
53
  */
54
54
  export const makeHttpServerFactory = (
55
- createLayerFn: (port: number) => Layer.Layer<HttpServer.HttpServer, ServeError, never>
55
+ createLayerFn: (port: number) => Layer.Layer<HttpServer.HttpServer, HttpServerError.ServeError, never>
56
56
  ): Layer.Layer<HttpServerFactoryTag> =>
57
57
  Layer.succeed(HttpServerFactoryTag, {
58
58
  createServerLayer: createLayerFn
59
59
  })
60
60
 
61
- /**
62
- * Check if a port is available by attempting to start a server.
63
- */
64
- const isPortAvailable = (port: number): Effect.Effect<boolean, never, HttpServerFactoryTag> =>
65
- Effect.gen(function*() {
66
- const factory = yield* HttpServerFactoryTag
67
- const serverLayer = factory.createServerLayer(port)
68
-
69
- // Try to acquire and immediately release
70
- const result = yield* Layer.build(serverLayer).pipe(
71
- Effect.scoped,
72
- Effect.as(true),
73
- Effect.catchAll(() => Effect.succeed(false))
74
- )
75
- return result
76
- })
77
-
78
- /**
79
- * Find an available port starting from the default.
80
- */
81
- const findAvailablePort = (): Effect.Effect<number, OAuthError, HttpServerFactoryTag> =>
82
- Effect.gen(function*() {
83
- for (let attempt = 0; attempt < MAX_PORT_ATTEMPTS; attempt++) {
84
- const port = DEFAULT_PORT + attempt
85
- const available = yield* isPortAvailable(port)
86
- if (available) {
87
- return port
88
- }
89
- }
90
- return yield* Effect.fail(
91
- new OAuthError({
92
- step: "authorize",
93
- cause: `Could not find available port (tried ${DEFAULT_PORT}-${
94
- DEFAULT_PORT + MAX_PORT_ATTEMPTS - 1
95
- }). Close other applications using these ports.`
96
- })
97
- )
98
- })
99
-
100
61
  /**
101
62
  * Result from the OAuth callback server.
102
63
  */
@@ -122,70 +83,85 @@ export const startCallbackServer = (
122
83
  ): Effect.Effect<CallbackServerResult, OAuthError, HttpServerFactoryTag> =>
123
84
  Effect.gen(function*() {
124
85
  const factory = yield* HttpServerFactoryTag
125
- const port = yield* findAvailablePort()
126
86
  const deferred = yield* Deferred.make<string, OAuthError>()
127
87
  const readyDeferred = yield* Deferred.make<void, OAuthError>()
88
+ const scope = yield* Scope.make()
89
+
90
+ const buildServer = (port: number): Effect.Effect<HttpServerInstance, OAuthError> =>
91
+ Layer.build(factory.createServerLayer(port)).pipe(
92
+ Scope.provide(scope),
93
+ Effect.map((context) => Context.get(context, HttpServer.HttpServer)),
94
+ Effect.catchCause((cause) =>
95
+ port < MAX_PORT
96
+ ? buildServer(port + 1)
97
+ : Effect.fail(new OAuthError({ step: "authorize", cause }))
98
+ )
99
+ )
128
100
 
129
- const app = HttpRouter.empty.pipe(
130
- HttpRouter.get(
131
- "/callback",
132
- Effect.gen(function*() {
133
- const req = yield* HttpServerRequest.HttpServerRequest
134
- const url = new URL(req.url, `http://localhost:${port}`)
135
- const code = url.searchParams.get("code")
136
- const state = url.searchParams.get("state")
137
- const error = url.searchParams.get("error")
138
- const errorDescription = url.searchParams.get("error_description")
139
-
140
- if (error) {
141
- yield* Deferred.fail(
142
- deferred,
143
- new OAuthError({ step: "authorize", cause: errorDescription || error })
144
- )
145
- return HttpServerResponse.html(
146
- "<html><body><h1>Authorization Failed</h1><p>You can close this window.</p></body></html>"
147
- )
148
- }
149
-
150
- if (state !== expectedState) {
151
- yield* Deferred.fail(
152
- deferred,
153
- new OAuthError({ step: "authorize", cause: "State mismatch - possible CSRF attack" })
154
- )
155
- return HttpServerResponse.html(
156
- "<html><body><h1>Security Error</h1><p>State verification failed.</p></body></html>"
157
- )
158
- }
159
-
160
- if (!code) {
161
- yield* Deferred.fail(
162
- deferred,
163
- new OAuthError({ step: "authorize", cause: "No authorization code received" })
164
- )
165
- return HttpServerResponse.html(
166
- "<html><body><h1>Error</h1><p>No authorization code received.</p></body></html>"
167
- )
168
- }
169
-
170
- yield* Deferred.succeed(deferred, code)
101
+ const server = yield* buildServer(DEFAULT_PORT)
102
+
103
+ if (server.address._tag !== "TcpAddress") {
104
+ return yield* Effect.fail(
105
+ new OAuthError({ step: "authorize", cause: "OAuth callback server did not bind to a TCP address" })
106
+ )
107
+ }
108
+ const port = server.address.port
109
+
110
+ const router = yield* HttpRouter.make
111
+ yield* router.add(
112
+ "GET",
113
+ "/callback",
114
+ Effect.gen(function*() {
115
+ const req = yield* HttpServerRequest.HttpServerRequest
116
+ const url = new URL(req.url, `http://localhost:${port}`)
117
+ const code = url.searchParams.get("code")
118
+ const state = url.searchParams.get("state")
119
+ const error = url.searchParams.get("error")
120
+ const errorDescription = url.searchParams.get("error_description")
121
+
122
+ if (error) {
123
+ yield* Deferred.fail(
124
+ deferred,
125
+ new OAuthError({ step: "authorize", cause: errorDescription || error })
126
+ )
171
127
  return HttpServerResponse.html(
172
- "<html><body><h1>Success!</h1><p>You can close this window and return to the terminal.</p></body></html>"
128
+ "<html><body><h1>Authorization Failed</h1><p>You can close this window.</p></body></html>"
173
129
  )
174
- })
175
- )
176
- )
130
+ }
131
+
132
+ if (state !== expectedState) {
133
+ yield* Deferred.fail(
134
+ deferred,
135
+ new OAuthError({ step: "authorize", cause: "State mismatch - possible CSRF attack" })
136
+ )
137
+ return HttpServerResponse.html(
138
+ "<html><body><h1>Security Error</h1><p>State verification failed.</p></body></html>"
139
+ )
140
+ }
141
+
142
+ if (!code) {
143
+ yield* Deferred.fail(
144
+ deferred,
145
+ new OAuthError({ step: "authorize", cause: "No authorization code received" })
146
+ )
147
+ return HttpServerResponse.html(
148
+ "<html><body><h1>Error</h1><p>No authorization code received.</p></body></html>"
149
+ )
150
+ }
177
151
 
178
- const serverLayer = factory.createServerLayer(port)
152
+ yield* Deferred.succeed(deferred, code)
153
+ return HttpServerResponse.html(
154
+ "<html><body><h1>Success!</h1><p>You can close this window and return to the terminal.</p></body></html>"
155
+ )
156
+ })
157
+ )
179
158
 
180
- const serverFiber = yield* HttpServer.serve(app).pipe(
181
- Layer.provide(serverLayer),
182
- Layer.build,
159
+ const serverFiber = yield* HttpServer.serveEffect(router.asHttpEffect()).pipe(
160
+ Effect.provideService(HttpServer.HttpServer, server),
161
+ Scope.provide(scope),
183
162
  Effect.tap(() => Deferred.succeed(readyDeferred, undefined)),
184
163
  Effect.tapError((err) => Deferred.fail(readyDeferred, new OAuthError({ step: "authorize", cause: err }))),
185
- // Keep the layer alive until fiber is interrupted
186
- Effect.flatMap(() => Effect.never),
187
- Effect.scoped,
188
- Effect.fork
164
+ Effect.forkIn(scope)
189
165
  )
190
166
 
191
167
  // Wait for server to be ready (or fail)
@@ -193,7 +169,10 @@ export const startCallbackServer = (
193
169
 
194
170
  return {
195
171
  codePromise: Deferred.await(deferred),
196
- shutdown: Fiber.interrupt(serverFiber).pipe(Effect.asVoid),
172
+ shutdown: Fiber.interrupt(serverFiber).pipe(
173
+ Effect.andThen(Scope.close(scope, Exit.void)),
174
+ Effect.asVoid
175
+ ),
197
176
  port
198
177
  }
199
178
  })
@@ -4,8 +4,8 @@
4
4
  * @module
5
5
  * @internal
6
6
  */
7
- import * as Path from "@effect/platform/Path"
8
7
  import * as Effect from "effect/Effect"
8
+ import * as Path from "effect/Path"
9
9
 
10
10
  /**
11
11
  * Convert a page title to a URL-safe slug.
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Process metadata service.
3
+ *
4
+ * @module
5
+ * @internal
6
+ */
7
+ import * as Context from "effect/Context"
8
+ import type * as Effect from "effect/Effect"
9
+
10
+ export class ProcessArgs extends Context.Service<
11
+ ProcessArgs,
12
+ {
13
+ readonly argv: Effect.Effect<ReadonlyArray<string>>
14
+ }
15
+ >()("@knpkv/confluence-to-markdown/ProcessArgs") {}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Standard output helpers backed by the Effect Stdio service.
3
+ *
4
+ * @module
5
+ * @internal
6
+ */
7
+ import * as Console from "effect/Console"
8
+ import * as Effect from "effect/Effect"
9
+ import type * as PlatformError from "effect/PlatformError"
10
+ import * as Terminal from "effect/Terminal"
11
+
12
+ export const writeStdout = (
13
+ message: string
14
+ ): Effect.Effect<void, PlatformError.PlatformError, Terminal.Terminal> =>
15
+ Effect.gen(function*() {
16
+ const terminal = yield* Terminal.Terminal
17
+ yield* terminal.display(message)
18
+ })
19
+
20
+ export const writeStderr = (
21
+ message: string
22
+ ): Effect.Effect<void> => Console.error(message)
@@ -3,11 +3,12 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- import * as FileSystem from "@effect/platform/FileSystem"
7
- import * as Path from "@effect/platform/Path"
6
+ import * as Config from "effect/Config"
8
7
  import * as Context from "effect/Context"
9
8
  import * as Effect from "effect/Effect"
9
+ import * as FileSystem from "effect/FileSystem"
10
10
  import * as Layer from "effect/Layer"
11
+ import * as Path from "effect/Path"
11
12
  import * as Schema from "effect/Schema"
12
13
  import { FileSystemError } from "../ConfluenceError.js"
13
14
  import { type OAuthConfig, OAuthConfigSchema, type OAuthToken, OAuthTokenSchema } from "../Schemas.js"
@@ -16,6 +17,14 @@ const TOKEN_DIR_NAME = ".confluence"
16
17
  const TOKEN_FILE_NAME = "auth.json"
17
18
  const CONFIG_FILE_NAME = "config.json"
18
19
 
20
+ const parseJsonOrNull = (content: string): unknown | null => {
21
+ try {
22
+ return JSON.parse(content) as unknown
23
+ } catch {
24
+ return null
25
+ }
26
+ }
27
+
19
28
  /**
20
29
  * Service for getting the home directory.
21
30
  * This allows mocking in tests.
@@ -31,21 +40,31 @@ export interface HomeDirectory {
31
40
  *
32
41
  * @category Services
33
42
  */
34
- export class HomeDirectoryTag extends Context.Tag("@knpkv/confluence-to-markdown/HomeDirectory")<
43
+ export class HomeDirectoryTag extends Context.Service<
35
44
  HomeDirectoryTag,
36
45
  HomeDirectory
37
- >() {}
46
+ >()("@knpkv/confluence-to-markdown/HomeDirectory") {}
38
47
 
39
48
  /**
40
- * Default implementation using process.env.HOME.
49
+ * Default implementation using Effect Config.
41
50
  *
42
51
  * @category Layers
43
52
  */
44
- export const HomeDirectoryLive: Layer.Layer<HomeDirectoryTag> = Layer.succeed(
53
+ const homeDirectoryPath = Config.string("HOME").pipe(
54
+ Config.orElse(() => Config.string("USERPROFILE")),
55
+ Config.orElse(() => Config.succeed("/"))
56
+ )
57
+
58
+ export const HomeDirectoryLive: Layer.Layer<HomeDirectoryTag> = Layer.effect(
45
59
  HomeDirectoryTag,
46
- {
47
- get: () => Effect.sync(() => process.env.HOME ?? process.env.USERPROFILE ?? "/")
48
- }
60
+ homeDirectoryPath.pipe(
61
+ Effect.catchCause(() => Effect.succeed("/")),
62
+ Effect.map((home) =>
63
+ HomeDirectoryTag.of({
64
+ get: () => Effect.succeed(home)
65
+ })
66
+ )
67
+ )
49
68
  )
50
69
 
51
70
  /**
@@ -96,7 +115,7 @@ export const loadToken = (): Effect.Effect<
96
115
  const tokenPath = yield* getTokenPath()
97
116
 
98
117
  const exists = yield* fs.exists(tokenPath).pipe(
99
- Effect.catchAll(() => Effect.succeed(false))
118
+ Effect.catchCause(() => Effect.succeed(false))
100
119
  )
101
120
  if (!exists) {
102
121
  return null
@@ -106,15 +125,11 @@ export const loadToken = (): Effect.Effect<
106
125
  Effect.mapError((cause) => new FileSystemError({ operation: "read", path: tokenPath, cause }))
107
126
  )
108
127
 
109
- let parsed: unknown
110
- try {
111
- parsed = JSON.parse(content)
112
- } catch {
113
- return null
114
- }
128
+ const parsed = yield* Effect.sync(() => parseJsonOrNull(content))
129
+ if (parsed === null) return null
115
130
 
116
- const decoded = yield* Schema.decodeUnknown(OAuthTokenSchema)(parsed).pipe(
117
- Effect.catchAll(() => Effect.succeed(null))
131
+ const decoded = yield* Schema.decodeUnknownEffect(OAuthTokenSchema)(parsed).pipe(
132
+ Effect.catchCause(() => Effect.succeed(null))
118
133
  )
119
134
 
120
135
  return decoded
@@ -164,8 +179,7 @@ export const deleteToken = (): Effect.Effect<
164
179
  const tokenPath = yield* getTokenPath()
165
180
 
166
181
  yield* fs.remove(tokenPath).pipe(
167
- Effect.catchAll(() => Effect.void),
168
- Effect.mapError((cause) => new FileSystemError({ operation: "delete", path: tokenPath, cause }))
182
+ Effect.catchCause(() => Effect.void)
169
183
  )
170
184
  })
171
185
 
@@ -186,7 +200,7 @@ export const loadOAuthConfig = (): Effect.Effect<
186
200
  const configPath = yield* getConfigPath()
187
201
 
188
202
  const exists = yield* fs.exists(configPath).pipe(
189
- Effect.catchAll(() => Effect.succeed(false))
203
+ Effect.catchCause(() => Effect.succeed(false))
190
204
  )
191
205
  if (!exists) {
192
206
  return null
@@ -196,15 +210,11 @@ export const loadOAuthConfig = (): Effect.Effect<
196
210
  Effect.mapError((cause) => new FileSystemError({ operation: "read", path: configPath, cause }))
197
211
  )
198
212
 
199
- let parsed: unknown
200
- try {
201
- parsed = JSON.parse(content)
202
- } catch {
203
- return null
204
- }
213
+ const parsed = yield* Effect.sync(() => parseJsonOrNull(content))
214
+ if (parsed === null) return null
205
215
 
206
- const decoded = yield* Schema.decodeUnknown(OAuthConfigSchema)(parsed).pipe(
207
- Effect.catchAll(() => Effect.succeed(null))
216
+ const decoded = yield* Schema.decodeUnknownEffect(OAuthConfigSchema)(parsed).pipe(
217
+ Effect.catchCause(() => Effect.succeed(null))
208
218
  )
209
219
 
210
220
  return decoded
@@ -14,7 +14,7 @@ import type { AtlassianUser } from "../Schemas.js"
14
14
  *
15
15
  * @category Cache
16
16
  */
17
- export class UserCache extends Context.Tag("@knpkv/confluence-to-markdown/UserCache")<
17
+ export class UserCache extends Context.Service<
18
18
  UserCache,
19
19
  {
20
20
  /**
@@ -40,7 +40,7 @@ export class UserCache extends Context.Tag("@knpkv/confluence-to-markdown/UserCa
40
40
  */
41
41
  readonly clear: () => Effect.Effect<void>
42
42
  }
43
- >() {}
43
+ >()("@knpkv/confluence-to-markdown/UserCache") {}
44
44
 
45
45
  /**
46
46
  * Create the user cache service.