@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.
- package/CHANGELOG.md +61 -0
- package/README.md +58 -14
- package/dist/AdfPlaceholders.d.ts +42 -0
- package/dist/AdfPlaceholders.d.ts.map +1 -0
- package/dist/AdfPlaceholders.js +547 -0
- package/dist/AdfPlaceholders.js.map +1 -0
- package/dist/AdfSchemaValidator.d.ts +37 -0
- package/dist/AdfSchemaValidator.d.ts.map +1 -0
- package/dist/AdfSchemaValidator.js +37 -0
- package/dist/AdfSchemaValidator.js.map +1 -0
- package/dist/AdfWalker.d.ts +39 -0
- package/dist/AdfWalker.d.ts.map +1 -0
- package/dist/AdfWalker.js +527 -0
- package/dist/AdfWalker.js.map +1 -0
- package/dist/AtlaskitTransformers.d.ts +35 -0
- package/dist/AtlaskitTransformers.d.ts.map +1 -0
- package/dist/AtlaskitTransformers.js +48 -0
- package/dist/AtlaskitTransformers.js.map +1 -0
- package/dist/Brand.d.ts +6 -6
- package/dist/Brand.d.ts.map +1 -1
- package/dist/Brand.js +8 -6
- package/dist/Brand.js.map +1 -1
- package/dist/ConfluenceAuth.d.ts +4 -4
- package/dist/ConfluenceAuth.d.ts.map +1 -1
- package/dist/ConfluenceAuth.js +15 -27
- package/dist/ConfluenceAuth.js.map +1 -1
- package/dist/ConfluenceClient.d.ts +4 -4
- package/dist/ConfluenceClient.d.ts.map +1 -1
- package/dist/ConfluenceClient.js +21 -14
- package/dist/ConfluenceClient.js.map +1 -1
- package/dist/ConfluenceConfig.d.ts +3 -3
- package/dist/ConfluenceConfig.d.ts.map +1 -1
- package/dist/ConfluenceConfig.js +13 -11
- package/dist/ConfluenceConfig.js.map +1 -1
- package/dist/ConfluenceError.d.ts +56 -4
- package/dist/ConfluenceError.d.ts.map +1 -1
- package/dist/ConfluenceError.js +30 -1
- package/dist/ConfluenceError.js.map +1 -1
- package/dist/GitService.d.ts +11 -3
- package/dist/GitService.d.ts.map +1 -1
- package/dist/GitService.js +19 -27
- package/dist/GitService.js.map +1 -1
- package/dist/LocalFileSystem.d.ts +3 -3
- package/dist/LocalFileSystem.d.ts.map +1 -1
- package/dist/LocalFileSystem.js +6 -6
- package/dist/LocalFileSystem.js.map +1 -1
- package/dist/MarkdownConverter.d.ts +16 -65
- package/dist/MarkdownConverter.d.ts.map +1 -1
- package/dist/MarkdownConverter.js +64 -85
- package/dist/MarkdownConverter.js.map +1 -1
- package/dist/Schemas.d.ts +128 -141
- package/dist/Schemas.d.ts.map +1 -1
- package/dist/Schemas.js +21 -23
- package/dist/Schemas.js.map +1 -1
- package/dist/SyncEngine.d.ts +8 -5
- package/dist/SyncEngine.d.ts.map +1 -1
- package/dist/SyncEngine.js +189 -113
- package/dist/SyncEngine.js.map +1 -1
- package/dist/bin.js +23 -35
- package/dist/bin.js.map +1 -1
- package/dist/commands/auth.d.ts +2 -14
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +11 -16
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/clone.d.ts +4 -6
- package/dist/commands/clone.d.ts.map +1 -1
- package/dist/commands/clone.js +34 -32
- package/dist/commands/clone.js.map +1 -1
- package/dist/commands/delete.d.ts +2 -10
- package/dist/commands/delete.d.ts.map +1 -1
- package/dist/commands/delete.js +5 -4
- package/dist/commands/delete.js.map +1 -1
- package/dist/commands/errorHandler.d.ts +2 -1
- package/dist/commands/errorHandler.d.ts.map +1 -1
- package/dist/commands/errorHandler.js +22 -15
- package/dist/commands/errorHandler.js.map +1 -1
- package/dist/commands/fetch.d.ts +27 -0
- package/dist/commands/fetch.d.ts.map +1 -0
- package/dist/commands/fetch.js +48 -0
- package/dist/commands/fetch.js.map +1 -0
- package/dist/commands/git.d.ts +7 -10
- package/dist/commands/git.d.ts.map +1 -1
- package/dist/commands/git.js +6 -6
- package/dist/commands/git.js.map +1 -1
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/layers.d.ts +10 -9
- package/dist/commands/layers.d.ts.map +1 -1
- package/dist/commands/layers.js +41 -30
- package/dist/commands/layers.js.map +1 -1
- package/dist/commands/new.d.ts +2 -6
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +5 -4
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/pageInput.d.ts +19 -0
- package/dist/commands/pageInput.d.ts.map +1 -0
- package/dist/commands/pageInput.js +68 -0
- package/dist/commands/pageInput.js.map +1 -0
- package/dist/commands/root.d.ts +8 -0
- package/dist/commands/root.d.ts.map +1 -0
- package/dist/commands/root.js +29 -0
- package/dist/commands/root.js.map +1 -0
- package/dist/commands/sync.d.ts +6 -9
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +5 -6
- package/dist/commands/sync.js.map +1 -1
- package/dist/index.d.ts +3 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -13
- package/dist/index.js.map +1 -1
- package/dist/internal/NodeLayers.d.ts.map +1 -1
- package/dist/internal/NodeLayers.js +1 -2
- package/dist/internal/NodeLayers.js.map +1 -1
- package/dist/internal/adfMetadata.d.ts +30 -0
- package/dist/internal/adfMetadata.d.ts.map +1 -0
- package/dist/internal/adfMetadata.js +126 -0
- package/dist/internal/adfMetadata.js.map +1 -0
- package/dist/internal/cleanMarkdown.d.ts +5 -0
- package/dist/internal/cleanMarkdown.d.ts.map +1 -0
- package/dist/internal/cleanMarkdown.js +13 -0
- package/dist/internal/cleanMarkdown.js.map +1 -0
- package/dist/internal/frontmatter.d.ts.map +1 -1
- package/dist/internal/frontmatter.js +41 -8
- package/dist/internal/frontmatter.js.map +1 -1
- package/dist/internal/gitCommands.d.ts +9 -3
- package/dist/internal/gitCommands.d.ts.map +1 -1
- package/dist/internal/gitCommands.js +18 -9
- package/dist/internal/gitCommands.js.map +1 -1
- package/dist/internal/hashUtils.d.ts +1 -1
- package/dist/internal/hashUtils.d.ts.map +1 -1
- package/dist/internal/hashUtils.js +1 -1
- package/dist/internal/hashUtils.js.map +1 -1
- package/dist/internal/oauthServer.d.ts +10 -5
- package/dist/internal/oauthServer.d.ts.map +1 -1
- package/dist/internal/oauthServer.js +19 -40
- package/dist/internal/oauthServer.js.map +1 -1
- package/dist/internal/pathUtils.d.ts +1 -1
- package/dist/internal/pathUtils.d.ts.map +1 -1
- package/dist/internal/pathUtils.js +1 -1
- package/dist/internal/pathUtils.js.map +1 -1
- package/dist/internal/process.d.ts +15 -0
- package/dist/internal/process.d.ts.map +1 -0
- package/dist/internal/process.js +10 -0
- package/dist/internal/process.js.map +1 -0
- package/dist/internal/stdio.d.ts +6 -0
- package/dist/internal/stdio.d.ts.map +1 -0
- package/dist/internal/stdio.js +15 -0
- package/dist/internal/stdio.js.map +1 -0
- package/dist/internal/tokenStorage.d.ts +3 -13
- package/dist/internal/tokenStorage.d.ts.map +1 -1
- package/dist/internal/tokenStorage.js +26 -24
- package/dist/internal/tokenStorage.js.map +1 -1
- package/dist/internal/userCache.d.ts +1 -1
- package/dist/internal/userCache.d.ts.map +1 -1
- package/dist/internal/userCache.js +1 -1
- package/dist/internal/userCache.js.map +1 -1
- package/package.json +29 -20
- package/skills/confluence/SKILL.md +143 -0
- package/skills/confluence/agents/openai.yaml +4 -0
- package/src/AdfPlaceholders.ts +563 -0
- package/src/AdfSchemaValidator.ts +65 -0
- package/src/AdfWalker.ts +591 -0
- package/src/AtlaskitTransformers.ts +70 -0
- package/src/Brand.ts +11 -16
- package/src/ConfluenceAuth.ts +22 -30
- package/src/ConfluenceClient.ts +28 -24
- package/src/ConfluenceConfig.ts +14 -14
- package/src/ConfluenceError.ts +65 -3
- package/src/GitService.ts +39 -49
- package/src/LocalFileSystem.ts +7 -9
- package/src/MarkdownConverter.ts +108 -143
- package/src/Schemas.ts +17 -16
- package/src/SyncEngine.ts +272 -127
- package/src/atlaskit-adf-schema.d.ts +3 -0
- package/src/bin.ts +30 -56
- package/src/commands/auth.ts +21 -18
- package/src/commands/clone.ts +46 -38
- package/src/commands/delete.ts +5 -4
- package/src/commands/errorHandler.ts +25 -18
- package/src/commands/fetch.ts +90 -0
- package/src/commands/git.ts +6 -6
- package/src/commands/index.ts +1 -0
- package/src/commands/layers.ts +64 -37
- package/src/commands/new.ts +5 -4
- package/src/commands/pageInput.ts +103 -0
- package/src/commands/root.ts +59 -0
- package/src/commands/sync.ts +7 -6
- package/src/index.ts +3 -18
- package/src/internal/NodeLayers.ts +1 -2
- package/src/internal/adfMetadata.ts +145 -0
- package/src/internal/cleanMarkdown.ts +15 -0
- package/src/internal/frontmatter.ts +45 -8
- package/src/internal/gitCommands.ts +23 -17
- package/src/internal/hashUtils.ts +2 -2
- package/src/internal/oauthServer.ts +84 -105
- package/src/internal/pathUtils.ts +1 -1
- package/src/internal/process.ts +15 -0
- package/src/internal/stdio.ts +22 -0
- package/src/internal/tokenStorage.ts +39 -29
- package/src/internal/userCache.ts +2 -2
- package/test/AdfPlaceholders.test.ts +508 -0
- package/test/AdfSchemaValidator.test.ts +34 -0
- package/test/AdfWalker.test.ts +676 -0
- package/test/AtlaskitTransformers.test.ts +25 -0
- package/test/Brand.test.ts +11 -11
- package/test/GitService.test.ts +6 -2
- package/test/MarkdownConverter.test.ts +121 -105
- package/test/RoundTrip.test.ts +521 -0
- package/test/Schemas.test.ts +40 -40
- package/test/adfMetadata.test.ts +110 -0
- package/test/cleanMarkdown.test.ts +36 -0
- package/test/commandHarness.test.ts +79 -0
- package/test/commandHarness.ts +147 -0
- package/test/fetch.test.ts +61 -0
- package/test/frontmatter.test.ts +41 -0
- package/test/integration.test.ts +569 -156
- package/test/layers.test.ts +12 -0
- package/test/oauthServer.test.ts +4 -5
- package/test/pageInput.test.ts +83 -0
- package/test/tokenStorage.test.ts +17 -17
- package/dist/SchemaConverterError.d.ts +0 -108
- package/dist/SchemaConverterError.d.ts.map +0 -1
- package/dist/SchemaConverterError.js +0 -84
- package/dist/SchemaConverterError.js.map +0 -1
- package/dist/ast/BlockNode.d.ts +0 -453
- package/dist/ast/BlockNode.d.ts.map +0 -1
- package/dist/ast/BlockNode.js +0 -310
- package/dist/ast/BlockNode.js.map +0 -1
- package/dist/ast/Document.d.ts +0 -216
- package/dist/ast/Document.d.ts.map +0 -1
- package/dist/ast/Document.js +0 -69
- package/dist/ast/Document.js.map +0 -1
- package/dist/ast/InlineNode.d.ts +0 -477
- package/dist/ast/InlineNode.d.ts.map +0 -1
- package/dist/ast/InlineNode.js +0 -263
- package/dist/ast/InlineNode.js.map +0 -1
- package/dist/ast/MacroNode.d.ts +0 -267
- package/dist/ast/MacroNode.d.ts.map +0 -1
- package/dist/ast/MacroNode.js +0 -164
- package/dist/ast/MacroNode.js.map +0 -1
- package/dist/ast/index.d.ts +0 -10
- package/dist/ast/index.d.ts.map +0 -1
- package/dist/ast/index.js +0 -14
- package/dist/ast/index.js.map +0 -1
- package/dist/parsers/ConfluenceParser.d.ts +0 -26
- package/dist/parsers/ConfluenceParser.d.ts.map +0 -1
- package/dist/parsers/ConfluenceParser.js +0 -797
- package/dist/parsers/ConfluenceParser.js.map +0 -1
- package/dist/parsers/MarkdownParser.d.ts +0 -26
- package/dist/parsers/MarkdownParser.d.ts.map +0 -1
- package/dist/parsers/MarkdownParser.js +0 -982
- package/dist/parsers/MarkdownParser.js.map +0 -1
- package/dist/parsers/index.d.ts +0 -8
- package/dist/parsers/index.d.ts.map +0 -1
- package/dist/parsers/index.js +0 -8
- package/dist/parsers/index.js.map +0 -1
- package/dist/schemas/ConfluenceSchema.d.ts +0 -21
- package/dist/schemas/ConfluenceSchema.d.ts.map +0 -1
- package/dist/schemas/ConfluenceSchema.js +0 -38
- package/dist/schemas/ConfluenceSchema.js.map +0 -1
- package/dist/schemas/ConversionSchema.d.ts +0 -35
- package/dist/schemas/ConversionSchema.d.ts.map +0 -1
- package/dist/schemas/ConversionSchema.js +0 -208
- package/dist/schemas/ConversionSchema.js.map +0 -1
- package/dist/schemas/MarkdownSchema.d.ts +0 -21
- package/dist/schemas/MarkdownSchema.d.ts.map +0 -1
- package/dist/schemas/MarkdownSchema.js +0 -38
- package/dist/schemas/MarkdownSchema.js.map +0 -1
- package/dist/schemas/hast/HastFromHtml.d.ts +0 -27
- package/dist/schemas/hast/HastFromHtml.d.ts.map +0 -1
- package/dist/schemas/hast/HastFromHtml.js +0 -107
- package/dist/schemas/hast/HastFromHtml.js.map +0 -1
- package/dist/schemas/hast/HastSchema.d.ts +0 -195
- package/dist/schemas/hast/HastSchema.d.ts.map +0 -1
- package/dist/schemas/hast/HastSchema.js +0 -183
- package/dist/schemas/hast/HastSchema.js.map +0 -1
- package/dist/schemas/hast/index.d.ts +0 -9
- package/dist/schemas/hast/index.d.ts.map +0 -1
- package/dist/schemas/hast/index.js +0 -3
- package/dist/schemas/hast/index.js.map +0 -1
- package/dist/schemas/index.d.ts +0 -14
- package/dist/schemas/index.d.ts.map +0 -1
- package/dist/schemas/index.js +0 -16
- package/dist/schemas/index.js.map +0 -1
- package/dist/schemas/mdast/MdastFromMarkdown.d.ts +0 -30
- package/dist/schemas/mdast/MdastFromMarkdown.d.ts.map +0 -1
- package/dist/schemas/mdast/MdastFromMarkdown.js +0 -79
- package/dist/schemas/mdast/MdastFromMarkdown.js.map +0 -1
- package/dist/schemas/mdast/MdastSchema.d.ts +0 -385
- package/dist/schemas/mdast/MdastSchema.d.ts.map +0 -1
- package/dist/schemas/mdast/MdastSchema.js +0 -266
- package/dist/schemas/mdast/MdastSchema.js.map +0 -1
- package/dist/schemas/mdast/index.d.ts +0 -10
- package/dist/schemas/mdast/index.d.ts.map +0 -1
- package/dist/schemas/mdast/index.js +0 -4
- package/dist/schemas/mdast/index.js.map +0 -1
- package/dist/schemas/mdast/mdastToString.d.ts +0 -13
- package/dist/schemas/mdast/mdastToString.d.ts.map +0 -1
- package/dist/schemas/mdast/mdastToString.js +0 -85
- package/dist/schemas/mdast/mdastToString.js.map +0 -1
- package/dist/schemas/nodes/block/BlockSchema.d.ts +0 -43
- package/dist/schemas/nodes/block/BlockSchema.d.ts.map +0 -1
- package/dist/schemas/nodes/block/BlockSchema.js +0 -634
- package/dist/schemas/nodes/block/BlockSchema.js.map +0 -1
- package/dist/schemas/nodes/block/index.d.ts +0 -7
- package/dist/schemas/nodes/block/index.d.ts.map +0 -1
- package/dist/schemas/nodes/block/index.js +0 -7
- package/dist/schemas/nodes/block/index.js.map +0 -1
- package/dist/schemas/nodes/index.d.ts +0 -9
- package/dist/schemas/nodes/index.d.ts.map +0 -1
- package/dist/schemas/nodes/index.js +0 -12
- package/dist/schemas/nodes/index.js.map +0 -1
- package/dist/schemas/nodes/inline/InlineSchema.d.ts +0 -48
- package/dist/schemas/nodes/inline/InlineSchema.d.ts.map +0 -1
- package/dist/schemas/nodes/inline/InlineSchema.js +0 -436
- package/dist/schemas/nodes/inline/InlineSchema.js.map +0 -1
- package/dist/schemas/nodes/inline/index.d.ts +0 -7
- package/dist/schemas/nodes/inline/index.d.ts.map +0 -1
- package/dist/schemas/nodes/inline/index.js +0 -7
- package/dist/schemas/nodes/inline/index.js.map +0 -1
- package/dist/schemas/nodes/macro/MacroSchema.d.ts +0 -27
- package/dist/schemas/nodes/macro/MacroSchema.d.ts.map +0 -1
- package/dist/schemas/nodes/macro/MacroSchema.js +0 -162
- package/dist/schemas/nodes/macro/MacroSchema.js.map +0 -1
- package/dist/schemas/nodes/macro/index.d.ts +0 -7
- package/dist/schemas/nodes/macro/index.d.ts.map +0 -1
- package/dist/schemas/nodes/macro/index.js +0 -7
- package/dist/schemas/nodes/macro/index.js.map +0 -1
- package/dist/schemas/preprocessing/ConfluencePreprocessor.d.ts +0 -24
- package/dist/schemas/preprocessing/ConfluencePreprocessor.d.ts.map +0 -1
- package/dist/schemas/preprocessing/ConfluencePreprocessor.js +0 -359
- package/dist/schemas/preprocessing/ConfluencePreprocessor.js.map +0 -1
- package/dist/schemas/preprocessing/index.d.ts +0 -8
- package/dist/schemas/preprocessing/index.d.ts.map +0 -1
- package/dist/schemas/preprocessing/index.js +0 -2
- package/dist/schemas/preprocessing/index.js.map +0 -1
- package/dist/serializers/ConfluenceSerializer.d.ts +0 -30
- package/dist/serializers/ConfluenceSerializer.d.ts.map +0 -1
- package/dist/serializers/ConfluenceSerializer.js +0 -560
- package/dist/serializers/ConfluenceSerializer.js.map +0 -1
- package/dist/serializers/MarkdownSerializer.d.ts +0 -34
- package/dist/serializers/MarkdownSerializer.d.ts.map +0 -1
- package/dist/serializers/MarkdownSerializer.js +0 -395
- package/dist/serializers/MarkdownSerializer.js.map +0 -1
- package/dist/serializers/index.d.ts +0 -8
- package/dist/serializers/index.d.ts.map +0 -1
- package/dist/serializers/index.js +0 -8
- package/dist/serializers/index.js.map +0 -1
- package/src/SchemaConverterError.ts +0 -108
- package/src/ast/BlockNode.ts +0 -469
- package/src/ast/Document.ts +0 -90
- package/src/ast/InlineNode.ts +0 -323
- package/src/ast/MacroNode.ts +0 -245
- package/src/ast/index.ts +0 -83
- package/src/parsers/ConfluenceParser.ts +0 -956
- package/src/parsers/MarkdownParser.ts +0 -1338
- package/src/parsers/index.ts +0 -8
- package/src/schemas/ConfluenceSchema.ts +0 -56
- package/src/schemas/ConversionSchema.ts +0 -318
- package/src/schemas/MarkdownSchema.ts +0 -56
- package/src/schemas/hast/HastFromHtml.ts +0 -153
- package/src/schemas/hast/HastSchema.ts +0 -274
- package/src/schemas/hast/index.ts +0 -35
- package/src/schemas/index.ts +0 -20
- package/src/schemas/mdast/MdastFromMarkdown.ts +0 -118
- package/src/schemas/mdast/MdastSchema.ts +0 -566
- package/src/schemas/mdast/index.ts +0 -59
- package/src/schemas/mdast/mdastToString.ts +0 -102
- package/src/schemas/nodes/block/BlockSchema.ts +0 -773
- package/src/schemas/nodes/block/index.ts +0 -13
- package/src/schemas/nodes/index.ts +0 -20
- package/src/schemas/nodes/inline/InlineSchema.ts +0 -523
- package/src/schemas/nodes/inline/index.ts +0 -14
- package/src/schemas/nodes/macro/MacroSchema.ts +0 -226
- package/src/schemas/nodes/macro/index.ts +0 -6
- package/src/schemas/preprocessing/ConfluencePreprocessor.ts +0 -455
- package/src/schemas/preprocessing/index.ts +0 -8
- package/src/serializers/ConfluenceSerializer.ts +0 -737
- package/src/serializers/MarkdownSerializer.ts +0 -543
- package/src/serializers/index.ts +0 -8
- package/test/ast/BlockNode.test.ts +0 -265
- package/test/ast/Document.test.ts +0 -126
- package/test/ast/InlineNode.test.ts +0 -161
- package/test/fixtures/integration-test.html.fixture +0 -103
- package/test/fixtures/integration-test.md.expected +0 -257
- package/test/parsers/ConfluenceParser.test.ts +0 -452
- package/test/schemas/ConfluencePreprocessor.test.ts +0 -180
- package/test/schemas/ConversionSchema.test.ts +0 -159
- package/test/schemas/HastSchema.test.ts +0 -138
- package/test/schemas/MdastSchema.test.ts +0 -145
- package/test/schemas/nodes/block/BlockSchema.test.ts +0 -173
- package/test/schemas/nodes/inline/InlineSchema.test.ts +0 -198
- package/test/schemas/nodes/macro/MacroSchema.test.ts +0 -142
package/dist/SyncEngine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SyncEngine.d.ts","sourceRoot":"","sources":["../src/SyncEngine.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"SyncEngine.d.ts","sourceRoot":"","sources":["../src/SyncEngine.ts"],"names":[],"mappings":"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"}
|
package/dist/SyncEngine.js
CHANGED
|
@@ -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.
|
|
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
|
|
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.
|
|
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
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
const contentHash = yield*
|
|
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?.
|
|
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
|
-
|
|
337
|
+
atlas_doc_format: {
|
|
275
338
|
value: bodyContent,
|
|
276
|
-
representation: "
|
|
339
|
+
representation: "atlas_doc_format"
|
|
277
340
|
}
|
|
278
341
|
}
|
|
279
342
|
};
|
|
280
|
-
const { frontMatter,
|
|
343
|
+
const { frontMatter, prepared } = yield* versionToMarkdown(filePath, pageId, versionContent, versionInfo.page?.title ?? fullPage.title, effectiveParentId, page.position);
|
|
281
344
|
// Write file
|
|
282
|
-
yield*
|
|
283
|
-
// Save source
|
|
284
|
-
if (config.saveSource && versionContent.body?.
|
|
285
|
-
const sourceFilePath = filePath.replace(/\.md$/, ".
|
|
286
|
-
yield* localFs.writeFile(sourceFilePath, versionContent.body.
|
|
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
|
|
312
|
-
let
|
|
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
|
-
|
|
384
|
+
rawMarkdown = rawMarkdown.trim() + "\n\n## Child Pages\n\n" + childLinks + "\n";
|
|
324
385
|
}
|
|
325
|
-
const
|
|
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*
|
|
342
|
-
// Save source
|
|
343
|
-
if (config.saveSource &&
|
|
344
|
-
const sourceFilePath = filePath.replace(/\.md$/, ".
|
|
345
|
-
yield* localFs.writeFile(sourceFilePath,
|
|
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
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
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
|
|
409
|
-
|
|
410
|
-
|
|
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
|
|
421
|
-
const
|
|
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: "
|
|
429
|
-
value:
|
|
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.
|
|
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
|
|
440
|
-
const
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
const canonicalHash = yield*
|
|
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*
|
|
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
|
|
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: "
|
|
477
|
-
value:
|
|
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
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
const canonicalHash = yield*
|
|
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*
|
|
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
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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
|
-
|
|
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
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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.
|
|
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.
|
|
694
|
+
}), Effect.catchIf(() => true, () => Effect.succeed(null)));
|
|
619
695
|
if (pageIdFromOrigin) {
|
|
620
|
-
yield* client.deletePage(PageId(pageIdFromOrigin)).pipe(Effect.tap(() => Effect.sync(() => deleted++)), Effect.
|
|
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.
|
|
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.
|
|
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.
|
|
669
|
-
if (remotePage
|
|
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.
|
|
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) {
|