@knpkv/confluence-to-markdown 0.2.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 (74) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +62 -0
  3. package/dist/Brand.d.ts +77 -0
  4. package/dist/Brand.d.ts.map +1 -0
  5. package/dist/Brand.js +44 -0
  6. package/dist/Brand.js.map +1 -0
  7. package/dist/ConfluenceClient.d.ts +140 -0
  8. package/dist/ConfluenceClient.d.ts.map +1 -0
  9. package/dist/ConfluenceClient.js +195 -0
  10. package/dist/ConfluenceClient.js.map +1 -0
  11. package/dist/ConfluenceConfig.d.ts +83 -0
  12. package/dist/ConfluenceConfig.d.ts.map +1 -0
  13. package/dist/ConfluenceConfig.js +122 -0
  14. package/dist/ConfluenceConfig.js.map +1 -0
  15. package/dist/ConfluenceError.d.ts +178 -0
  16. package/dist/ConfluenceError.d.ts.map +1 -0
  17. package/dist/ConfluenceError.js +131 -0
  18. package/dist/ConfluenceError.js.map +1 -0
  19. package/dist/LocalFileSystem.d.ts +85 -0
  20. package/dist/LocalFileSystem.d.ts.map +1 -0
  21. package/dist/LocalFileSystem.js +101 -0
  22. package/dist/LocalFileSystem.js.map +1 -0
  23. package/dist/MarkdownConverter.d.ts +50 -0
  24. package/dist/MarkdownConverter.d.ts.map +1 -0
  25. package/dist/MarkdownConverter.js +151 -0
  26. package/dist/MarkdownConverter.js.map +1 -0
  27. package/dist/Schemas.d.ts +225 -0
  28. package/dist/Schemas.d.ts.map +1 -0
  29. package/dist/Schemas.js +164 -0
  30. package/dist/Schemas.js.map +1 -0
  31. package/dist/SyncEngine.d.ts +132 -0
  32. package/dist/SyncEngine.d.ts.map +1 -0
  33. package/dist/SyncEngine.js +267 -0
  34. package/dist/SyncEngine.js.map +1 -0
  35. package/dist/bin.d.ts +3 -0
  36. package/dist/bin.d.ts.map +1 -0
  37. package/dist/bin.js +163 -0
  38. package/dist/bin.js.map +1 -0
  39. package/dist/index.d.ts +16 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +16 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/internal/frontmatter.d.ts +38 -0
  44. package/dist/internal/frontmatter.d.ts.map +1 -0
  45. package/dist/internal/frontmatter.js +69 -0
  46. package/dist/internal/frontmatter.js.map +1 -0
  47. package/dist/internal/hashUtils.d.ts +11 -0
  48. package/dist/internal/hashUtils.d.ts.map +1 -0
  49. package/dist/internal/hashUtils.js +17 -0
  50. package/dist/internal/hashUtils.js.map +1 -0
  51. package/dist/internal/pathUtils.d.ts +41 -0
  52. package/dist/internal/pathUtils.d.ts.map +1 -0
  53. package/dist/internal/pathUtils.js +69 -0
  54. package/dist/internal/pathUtils.js.map +1 -0
  55. package/package.json +113 -0
  56. package/src/Brand.ts +104 -0
  57. package/src/ConfluenceClient.ts +387 -0
  58. package/src/ConfluenceConfig.ts +184 -0
  59. package/src/ConfluenceError.ts +193 -0
  60. package/src/LocalFileSystem.ts +225 -0
  61. package/src/MarkdownConverter.ts +187 -0
  62. package/src/Schemas.ts +235 -0
  63. package/src/SyncEngine.ts +429 -0
  64. package/src/bin.ts +269 -0
  65. package/src/index.ts +35 -0
  66. package/src/internal/frontmatter.ts +98 -0
  67. package/src/internal/hashUtils.ts +19 -0
  68. package/src/internal/pathUtils.ts +77 -0
  69. package/test/Brand.test.ts +72 -0
  70. package/test/MarkdownConverter.test.ts +108 -0
  71. package/test/Schemas.test.ts +99 -0
  72. package/tsconfig.json +32 -0
  73. package/vitest.config.integration.ts +12 -0
  74. package/vitest.config.ts +13 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * HTML to Markdown conversion service using unified/remark/rehype.
3
+ *
4
+ * @module
5
+ */
6
+ import * as Context from "effect/Context";
7
+ import * as Effect from "effect/Effect";
8
+ import * as Layer from "effect/Layer";
9
+ import { ConversionError } from "./ConfluenceError.js";
10
+ declare const MarkdownConverter_base: Context.TagClass<MarkdownConverter, "@knpkv/confluence-to-markdown/MarkdownConverter", {
11
+ /**
12
+ * Convert Confluence storage format (HTML) to GitHub Flavored Markdown.
13
+ */
14
+ readonly htmlToMarkdown: (html: string) => Effect.Effect<string, ConversionError>;
15
+ /**
16
+ * Convert GitHub Flavored Markdown to HTML (Confluence storage format).
17
+ */
18
+ readonly markdownToHtml: (markdown: string) => Effect.Effect<string, ConversionError>;
19
+ }>;
20
+ /**
21
+ * Markdown conversion service for HTML <-> GFM conversion.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * import { MarkdownConverter } from "@knpkv/confluence-to-markdown/MarkdownConverter"
26
+ * import { Effect } from "effect"
27
+ *
28
+ * const program = Effect.gen(function* () {
29
+ * const converter = yield* MarkdownConverter
30
+ * const md = yield* converter.htmlToMarkdown("<h1>Hello</h1><p>World</p>")
31
+ * console.log(md) // # Hello\n\nWorld
32
+ * })
33
+ *
34
+ * Effect.runPromise(
35
+ * program.pipe(Effect.provide(MarkdownConverter.layer))
36
+ * )
37
+ * ```
38
+ *
39
+ * @category Conversion
40
+ */
41
+ export declare class MarkdownConverter extends MarkdownConverter_base {
42
+ }
43
+ /**
44
+ * Layer that provides the MarkdownConverter service.
45
+ *
46
+ * @category Layers
47
+ */
48
+ export declare const layer: Layer.Layer<MarkdownConverter>;
49
+ export {};
50
+ //# sourceMappingURL=MarkdownConverter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownConverter.d.ts","sourceRoot":"","sources":["../src/MarkdownConverter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AASrC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;;IA4BlD;;OAEG;6BACsB,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;IAEjF;;OAEG;6BACsB,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;;AAlCzF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,iBAAkB,SAAQ,sBAepC;CAAG;AAuGN;;;;GAIG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAwBhD,CAAA"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * HTML to Markdown conversion service using unified/remark/rehype.
3
+ *
4
+ * @module
5
+ */
6
+ import * as Context from "effect/Context";
7
+ import * as Effect from "effect/Effect";
8
+ import * as Layer from "effect/Layer";
9
+ import rehypeParse from "rehype-parse";
10
+ import rehypeRemark from "rehype-remark";
11
+ import rehypeStringify from "rehype-stringify";
12
+ import remarkGfm from "remark-gfm";
13
+ import remarkParse from "remark-parse";
14
+ import remarkRehype from "remark-rehype";
15
+ import remarkStringify from "remark-stringify";
16
+ import { unified } from "unified";
17
+ import { ConversionError } from "./ConfluenceError.js";
18
+ /**
19
+ * Markdown conversion service for HTML <-> GFM conversion.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * import { MarkdownConverter } from "@knpkv/confluence-to-markdown/MarkdownConverter"
24
+ * import { Effect } from "effect"
25
+ *
26
+ * const program = Effect.gen(function* () {
27
+ * const converter = yield* MarkdownConverter
28
+ * const md = yield* converter.htmlToMarkdown("<h1>Hello</h1><p>World</p>")
29
+ * console.log(md) // # Hello\n\nWorld
30
+ * })
31
+ *
32
+ * Effect.runPromise(
33
+ * program.pipe(Effect.provide(MarkdownConverter.layer))
34
+ * )
35
+ * ```
36
+ *
37
+ * @category Conversion
38
+ */
39
+ export class MarkdownConverter extends Context.Tag("@knpkv/confluence-to-markdown/MarkdownConverter")() {
40
+ }
41
+ /** Maximum HTML input size (1MB) to prevent ReDoS attacks */
42
+ const MAX_HTML_SIZE = 1024 * 1024;
43
+ /**
44
+ * Strip Confluence-specific macros while preserving text content.
45
+ * Uses iterative approach to avoid ReDoS with nested content.
46
+ */
47
+ const stripConfluenceMacros = (html) => Effect.gen(function* () {
48
+ // Limit input size to prevent ReDoS
49
+ if (html.length > MAX_HTML_SIZE) {
50
+ return yield* Effect.fail(new ConversionError({
51
+ direction: "htmlToMarkdown",
52
+ cause: `HTML input too large: ${html.length} bytes (max ${MAX_HTML_SIZE})`
53
+ }));
54
+ }
55
+ let result = html;
56
+ // Process structured macros iteratively to handle nesting safely
57
+ let iterations = 0;
58
+ const maxIterations = 100; // Prevent infinite loops
59
+ while (iterations < maxIterations) {
60
+ const macroStart = result.indexOf("<ac:structured-macro");
61
+ if (macroStart === -1)
62
+ break;
63
+ // Find matching closing tag by counting nesting
64
+ let depth = 1;
65
+ let pos = macroStart + 20; // Skip past opening tag start
66
+ let endPos = -1;
67
+ while (pos < result.length && depth > 0) {
68
+ if (result.slice(pos, pos + 20) === "<ac:structured-macro") {
69
+ depth++;
70
+ pos += 20;
71
+ }
72
+ else if (result.slice(pos, pos + 21) === "</ac:structured-macro") {
73
+ depth--;
74
+ if (depth === 0) {
75
+ endPos = result.indexOf(">", pos) + 1;
76
+ }
77
+ pos += 21;
78
+ }
79
+ else {
80
+ pos++;
81
+ }
82
+ }
83
+ if (endPos === -1)
84
+ break; // Malformed HTML, stop processing
85
+ const macroContent = result.slice(macroStart, endPos);
86
+ // Extract content from macro
87
+ let replacement = "";
88
+ const plainBodyStart = macroContent.indexOf("<ac:plain-text-body><![CDATA[");
89
+ const plainBodyEnd = macroContent.indexOf("]]></ac:plain-text-body>");
90
+ if (plainBodyStart !== -1 && plainBodyEnd !== -1) {
91
+ const content = macroContent.slice(plainBodyStart + 29, plainBodyEnd);
92
+ replacement = `<pre><code>${content}</code></pre>`;
93
+ }
94
+ else {
95
+ const richBodyStart = macroContent.indexOf("<ac:rich-text-body>");
96
+ const richBodyEnd = macroContent.indexOf("</ac:rich-text-body>");
97
+ if (richBodyStart !== -1 && richBodyEnd !== -1) {
98
+ replacement = macroContent.slice(richBodyStart + 19, richBodyEnd);
99
+ }
100
+ }
101
+ result = result.slice(0, macroStart) + replacement + result.slice(endPos);
102
+ iterations++;
103
+ }
104
+ // Remove remaining simple tags with non-greedy bounded patterns
105
+ result = result
106
+ .replace(/<ac:parameter[^>]{0,1000}>[^<]{0,10000}<\/ac:parameter>/gi, "")
107
+ .replace(/<\/?ac:[a-z-]{1,50}[^>]{0,1000}>/gi, "")
108
+ .replace(/<\/?ri:[a-z-]{1,50}[^>]{0,1000}\/?>/gi, "");
109
+ return result;
110
+ });
111
+ /**
112
+ * Create the markdown converter processor for HTML -> Markdown.
113
+ */
114
+ const createHtmlToMdProcessor = () => unified()
115
+ .use(rehypeParse, { fragment: true })
116
+ .use(rehypeRemark)
117
+ .use(remarkGfm)
118
+ .use(remarkStringify);
119
+ /**
120
+ * Create the markdown converter processor for Markdown -> HTML.
121
+ */
122
+ const createMdToHtmlProcessor = () => unified()
123
+ .use(remarkParse)
124
+ .use(remarkGfm)
125
+ .use(remarkRehype)
126
+ .use(rehypeStringify);
127
+ /**
128
+ * Layer that provides the MarkdownConverter service.
129
+ *
130
+ * @category Layers
131
+ */
132
+ export const layer = Layer.succeed(MarkdownConverter, MarkdownConverter.of({
133
+ htmlToMarkdown: (html) => Effect.gen(function* () {
134
+ const cleaned = yield* stripConfluenceMacros(html);
135
+ return yield* Effect.try({
136
+ try: () => {
137
+ const result = createHtmlToMdProcessor().processSync(cleaned);
138
+ return String(result).trim();
139
+ },
140
+ catch: (cause) => new ConversionError({ direction: "htmlToMarkdown", cause })
141
+ });
142
+ }),
143
+ markdownToHtml: (markdown) => Effect.try({
144
+ try: () => {
145
+ const result = createMdToHtmlProcessor().processSync(markdown);
146
+ return String(result).trim();
147
+ },
148
+ catch: (cause) => new ConversionError({ direction: "markdownToHtml", cause })
149
+ })
150
+ }));
151
+ //# sourceMappingURL=MarkdownConverter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownConverter.js","sourceRoot":"","sources":["../src/MarkdownConverter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Schema definitions for configuration and data structures.
3
+ *
4
+ * @module
5
+ */
6
+ import * as Schema from "effect/Schema";
7
+ /**
8
+ * Schema for .confluence.json configuration file.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { ConfluenceConfigFileSchema } from "@knpkv/confluence-to-markdown/Schemas"
13
+ * import * as Schema from "effect/Schema"
14
+ *
15
+ * const config = Schema.decodeUnknownSync(ConfluenceConfigFileSchema)({
16
+ * rootPageId: "12345",
17
+ * baseUrl: "https://mysite.atlassian.net"
18
+ * })
19
+ * ```
20
+ *
21
+ * @category Schema
22
+ */
23
+ export declare const ConfluenceConfigFileSchema: Schema.Struct<{
24
+ /** Root page ID to sync from */
25
+ rootPageId: Schema.brand<Schema.filter<typeof Schema.String>, "PageId">;
26
+ /** Confluence Cloud base URL */
27
+ baseUrl: Schema.filter<typeof Schema.String>;
28
+ /** Optional space key */
29
+ spaceKey: Schema.optional<Schema.brand<Schema.filter<Schema.filter<typeof Schema.String>>, "SpaceKey">>;
30
+ /** Local docs path (default: .docs/confluence) */
31
+ docsPath: Schema.optionalWith<typeof Schema.String, {
32
+ default: () => string;
33
+ }>;
34
+ /** Glob patterns to exclude from sync */
35
+ excludePatterns: Schema.optionalWith<Schema.Array$<typeof Schema.String>, {
36
+ default: () => never[];
37
+ }>;
38
+ }>;
39
+ /**
40
+ * Type for .confluence.json configuration file.
41
+ *
42
+ * @category Types
43
+ */
44
+ export type ConfluenceConfigFile = Schema.Schema.Type<typeof ConfluenceConfigFileSchema>;
45
+ /**
46
+ * Schema for page front-matter in markdown files.
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { PageFrontMatterSchema } from "@knpkv/confluence-to-markdown/Schemas"
51
+ * import * as Schema from "effect/Schema"
52
+ *
53
+ * const frontMatter = Schema.decodeUnknownSync(PageFrontMatterSchema)({
54
+ * pageId: "12345",
55
+ * version: 3,
56
+ * title: "My Page",
57
+ * updated: "2025-01-15T10:30:00Z",
58
+ * contentHash: "a".repeat(64)
59
+ * })
60
+ * ```
61
+ *
62
+ * @category Schema
63
+ */
64
+ export declare const PageFrontMatterSchema: Schema.Struct<{
65
+ /** Confluence page ID */
66
+ pageId: Schema.brand<Schema.filter<typeof Schema.String>, "PageId">;
67
+ /** Page version number */
68
+ version: Schema.filter<Schema.filter<typeof Schema.Number>>;
69
+ /** Page title */
70
+ title: Schema.filter<typeof Schema.String>;
71
+ /** Last updated timestamp (ISO8601) */
72
+ updated: typeof Schema.DateFromString;
73
+ /** Parent page ID (optional) */
74
+ parentId: Schema.optional<Schema.brand<Schema.filter<typeof Schema.String>, "PageId">>;
75
+ /** Position among siblings (optional) */
76
+ position: Schema.optional<typeof Schema.Number>;
77
+ /** SHA256 hash of content for change detection */
78
+ contentHash: Schema.brand<Schema.filter<typeof Schema.String>, "ContentHash">;
79
+ }>;
80
+ /**
81
+ * Type for page front-matter.
82
+ *
83
+ * @category Types
84
+ */
85
+ export type PageFrontMatter = Schema.Schema.Type<typeof PageFrontMatterSchema>;
86
+ /**
87
+ * Schema for new page front-matter (no pageId yet).
88
+ *
89
+ * @category Schema
90
+ */
91
+ export declare const NewPageFrontMatterSchema: Schema.Struct<{
92
+ /** Page title */
93
+ title: Schema.filter<typeof Schema.String>;
94
+ /** Parent page ID (optional, determined by directory structure) */
95
+ parentId: Schema.optional<Schema.brand<Schema.filter<typeof Schema.String>, "PageId">>;
96
+ }>;
97
+ /**
98
+ * Type for new page front-matter.
99
+ *
100
+ * @category Types
101
+ */
102
+ export type NewPageFrontMatter = Schema.Schema.Type<typeof NewPageFrontMatterSchema>;
103
+ /**
104
+ * Schema for sync state file (.sync-state.json).
105
+ *
106
+ * @category Schema
107
+ */
108
+ export declare const SyncStateSchema: Schema.Struct<{
109
+ /** Last sync timestamp */
110
+ lastSync: typeof Schema.DateFromString;
111
+ /** Map of page ID to sync info */
112
+ pages: Schema.Record$<typeof Schema.String, Schema.Struct<{
113
+ /** Local file path */
114
+ localPath: typeof Schema.String;
115
+ /** Last synced version */
116
+ version: typeof Schema.Number;
117
+ /** Content hash at last sync */
118
+ contentHash: Schema.brand<Schema.filter<typeof Schema.String>, "ContentHash">;
119
+ }>>;
120
+ }>;
121
+ /**
122
+ * Type for sync state.
123
+ *
124
+ * @category Types
125
+ */
126
+ export type SyncState = Schema.Schema.Type<typeof SyncStateSchema>;
127
+ /**
128
+ * Schema for Confluence page API response (full, from getPage).
129
+ *
130
+ * @category Schema
131
+ */
132
+ export declare const PageResponseSchema: Schema.Struct<{
133
+ id: typeof Schema.String;
134
+ title: typeof Schema.String;
135
+ status: Schema.optional<typeof Schema.String>;
136
+ version: Schema.Struct<{
137
+ number: typeof Schema.Number;
138
+ createdAt: Schema.optional<typeof Schema.String>;
139
+ }>;
140
+ body: Schema.optional<Schema.Struct<{
141
+ storage: Schema.optional<Schema.Struct<{
142
+ value: typeof Schema.String;
143
+ representation: Schema.optional<typeof Schema.String>;
144
+ }>>;
145
+ }>>;
146
+ parentId: Schema.optional<typeof Schema.String>;
147
+ position: Schema.optional<typeof Schema.Number>;
148
+ _links: Schema.optional<Schema.Struct<{
149
+ webui: Schema.optional<typeof Schema.String>;
150
+ }>>;
151
+ }>;
152
+ /**
153
+ * Type for page API response.
154
+ *
155
+ * @category Types
156
+ */
157
+ export type PageResponse = Schema.Schema.Type<typeof PageResponseSchema>;
158
+ /**
159
+ * Schema for page list item (children list, version optional).
160
+ *
161
+ * @category Schema
162
+ */
163
+ export declare const PageListItemSchema: Schema.Struct<{
164
+ id: typeof Schema.String;
165
+ title: typeof Schema.String;
166
+ status: Schema.optional<typeof Schema.String>;
167
+ version: Schema.optional<Schema.Struct<{
168
+ number: typeof Schema.Number;
169
+ createdAt: Schema.optional<typeof Schema.String>;
170
+ }>>;
171
+ body: Schema.optional<Schema.Struct<{
172
+ storage: Schema.optional<Schema.Struct<{
173
+ value: typeof Schema.String;
174
+ representation: Schema.optional<typeof Schema.String>;
175
+ }>>;
176
+ }>>;
177
+ parentId: Schema.optional<typeof Schema.String>;
178
+ position: Schema.optional<typeof Schema.Number>;
179
+ _links: Schema.optional<Schema.Struct<{
180
+ webui: Schema.optional<typeof Schema.String>;
181
+ }>>;
182
+ }>;
183
+ /**
184
+ * Type for page list item.
185
+ *
186
+ * @category Types
187
+ */
188
+ export type PageListItem = Schema.Schema.Type<typeof PageListItemSchema>;
189
+ /**
190
+ * Schema for page children API response.
191
+ *
192
+ * @category Schema
193
+ */
194
+ export declare const PageChildrenResponseSchema: Schema.Struct<{
195
+ results: Schema.Array$<Schema.Struct<{
196
+ id: typeof Schema.String;
197
+ title: typeof Schema.String;
198
+ status: Schema.optional<typeof Schema.String>;
199
+ version: Schema.optional<Schema.Struct<{
200
+ number: typeof Schema.Number;
201
+ createdAt: Schema.optional<typeof Schema.String>;
202
+ }>>;
203
+ body: Schema.optional<Schema.Struct<{
204
+ storage: Schema.optional<Schema.Struct<{
205
+ value: typeof Schema.String;
206
+ representation: Schema.optional<typeof Schema.String>;
207
+ }>>;
208
+ }>>;
209
+ parentId: Schema.optional<typeof Schema.String>;
210
+ position: Schema.optional<typeof Schema.Number>;
211
+ _links: Schema.optional<Schema.Struct<{
212
+ webui: Schema.optional<typeof Schema.String>;
213
+ }>>;
214
+ }>>;
215
+ _links: Schema.optional<Schema.Struct<{
216
+ next: Schema.optional<typeof Schema.String>;
217
+ }>>;
218
+ }>;
219
+ /**
220
+ * Type for page children response.
221
+ *
222
+ * @category Types
223
+ */
224
+ export type PageChildrenResponse = Schema.Schema.Type<typeof PageChildrenResponseSchema>;
225
+ //# sourceMappingURL=Schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Schemas.d.ts","sourceRoot":"","sources":["../src/Schemas.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,0BAA0B;IACrC,gCAAgC;;IAEhC,gCAAgC;;IAIhC,yBAAyB;;IAEzB,kDAAkD;;;;IAElD,yCAAyC;;;;EAEzC,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,0BAA0B,CAAC,CAAA;AAExF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,qBAAqB;IAChC,yBAAyB;;IAEzB,0BAA0B;;IAE1B,iBAAiB;;IAEjB,uCAAuC;;IAEvC,gCAAgC;;IAEhC,yCAAyC;;IAEzC,kDAAkD;;EAElD,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAE9E;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;IACnC,iBAAiB;;IAEjB,mEAAmE;;EAEnE,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAEpF;;;;GAIG;AACH,eAAO,MAAM,eAAe;IAC1B,0BAA0B;;IAE1B,kCAAkC;;QAI9B,sBAAsB;;QAEtB,0BAA0B;;QAE1B,gCAAgC;;;EAIpC,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,eAAe,CAAC,CAAA;AAElE;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;EAyB7B,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAExE;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;EAyB7B,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAExE;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;EAOrC,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,0BAA0B,CAAC,CAAA"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Schema definitions for configuration and data structures.
3
+ *
4
+ * @module
5
+ */
6
+ import * as Schema from "effect/Schema";
7
+ import { ContentHashSchema, PageIdSchema, SpaceKeySchema } from "./Brand.js";
8
+ /**
9
+ * Schema for .confluence.json configuration file.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { ConfluenceConfigFileSchema } from "@knpkv/confluence-to-markdown/Schemas"
14
+ * import * as Schema from "effect/Schema"
15
+ *
16
+ * const config = Schema.decodeUnknownSync(ConfluenceConfigFileSchema)({
17
+ * rootPageId: "12345",
18
+ * baseUrl: "https://mysite.atlassian.net"
19
+ * })
20
+ * ```
21
+ *
22
+ * @category Schema
23
+ */
24
+ export const ConfluenceConfigFileSchema = Schema.Struct({
25
+ /** Root page ID to sync from */
26
+ rootPageId: PageIdSchema,
27
+ /** Confluence Cloud base URL */
28
+ baseUrl: Schema.String.pipe(Schema.pattern(/^https:\/\/[a-z0-9-]+\.atlassian\.net$/)),
29
+ /** Optional space key */
30
+ spaceKey: Schema.optional(SpaceKeySchema),
31
+ /** Local docs path (default: .docs/confluence) */
32
+ docsPath: Schema.optionalWith(Schema.String, { default: () => ".docs/confluence" }),
33
+ /** Glob patterns to exclude from sync */
34
+ excludePatterns: Schema.optionalWith(Schema.Array(Schema.String), { default: () => [] })
35
+ });
36
+ /**
37
+ * Schema for page front-matter in markdown files.
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * import { PageFrontMatterSchema } from "@knpkv/confluence-to-markdown/Schemas"
42
+ * import * as Schema from "effect/Schema"
43
+ *
44
+ * const frontMatter = Schema.decodeUnknownSync(PageFrontMatterSchema)({
45
+ * pageId: "12345",
46
+ * version: 3,
47
+ * title: "My Page",
48
+ * updated: "2025-01-15T10:30:00Z",
49
+ * contentHash: "a".repeat(64)
50
+ * })
51
+ * ```
52
+ *
53
+ * @category Schema
54
+ */
55
+ export const PageFrontMatterSchema = Schema.Struct({
56
+ /** Confluence page ID */
57
+ pageId: PageIdSchema,
58
+ /** Page version number */
59
+ version: Schema.Number.pipe(Schema.int(), Schema.positive()),
60
+ /** Page title */
61
+ title: Schema.String.pipe(Schema.nonEmptyString()),
62
+ /** Last updated timestamp (ISO8601) */
63
+ updated: Schema.DateFromString,
64
+ /** Parent page ID (optional) */
65
+ parentId: Schema.optional(PageIdSchema),
66
+ /** Position among siblings (optional) */
67
+ position: Schema.optional(Schema.Number),
68
+ /** SHA256 hash of content for change detection */
69
+ contentHash: ContentHashSchema
70
+ });
71
+ /**
72
+ * Schema for new page front-matter (no pageId yet).
73
+ *
74
+ * @category Schema
75
+ */
76
+ export const NewPageFrontMatterSchema = Schema.Struct({
77
+ /** Page title */
78
+ title: Schema.String.pipe(Schema.nonEmptyString()),
79
+ /** Parent page ID (optional, determined by directory structure) */
80
+ parentId: Schema.optional(PageIdSchema)
81
+ });
82
+ /**
83
+ * Schema for sync state file (.sync-state.json).
84
+ *
85
+ * @category Schema
86
+ */
87
+ export const SyncStateSchema = Schema.Struct({
88
+ /** Last sync timestamp */
89
+ lastSync: Schema.DateFromString,
90
+ /** Map of page ID to sync info */
91
+ pages: Schema.Record({
92
+ key: Schema.String,
93
+ value: Schema.Struct({
94
+ /** Local file path */
95
+ localPath: Schema.String,
96
+ /** Last synced version */
97
+ version: Schema.Number,
98
+ /** Content hash at last sync */
99
+ contentHash: ContentHashSchema
100
+ })
101
+ })
102
+ });
103
+ /**
104
+ * Schema for Confluence page API response (full, from getPage).
105
+ *
106
+ * @category Schema
107
+ */
108
+ export const PageResponseSchema = Schema.Struct({
109
+ id: Schema.String,
110
+ title: Schema.String,
111
+ status: Schema.optional(Schema.String),
112
+ version: Schema.Struct({
113
+ number: Schema.Number,
114
+ createdAt: Schema.optional(Schema.String)
115
+ }),
116
+ body: Schema.optional(Schema.Struct({
117
+ storage: Schema.optional(Schema.Struct({
118
+ value: Schema.String,
119
+ representation: Schema.optional(Schema.String)
120
+ }))
121
+ })),
122
+ parentId: Schema.optional(Schema.String),
123
+ position: Schema.optional(Schema.Number),
124
+ _links: Schema.optional(Schema.Struct({
125
+ webui: Schema.optional(Schema.String)
126
+ }))
127
+ });
128
+ /**
129
+ * Schema for page list item (children list, version optional).
130
+ *
131
+ * @category Schema
132
+ */
133
+ export const PageListItemSchema = Schema.Struct({
134
+ id: Schema.String,
135
+ title: Schema.String,
136
+ status: Schema.optional(Schema.String),
137
+ version: Schema.optional(Schema.Struct({
138
+ number: Schema.Number,
139
+ createdAt: Schema.optional(Schema.String)
140
+ })),
141
+ body: Schema.optional(Schema.Struct({
142
+ storage: Schema.optional(Schema.Struct({
143
+ value: Schema.String,
144
+ representation: Schema.optional(Schema.String)
145
+ }))
146
+ })),
147
+ parentId: Schema.optional(Schema.String),
148
+ position: Schema.optional(Schema.Number),
149
+ _links: Schema.optional(Schema.Struct({
150
+ webui: Schema.optional(Schema.String)
151
+ }))
152
+ });
153
+ /**
154
+ * Schema for page children API response.
155
+ *
156
+ * @category Schema
157
+ */
158
+ export const PageChildrenResponseSchema = Schema.Struct({
159
+ results: Schema.Array(PageListItemSchema),
160
+ _links: Schema.optional(Schema.Struct({
161
+ next: Schema.optional(Schema.String)
162
+ }))
163
+ });
164
+ //# sourceMappingURL=Schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Schemas.js","sourceRoot":"","sources":["../src/Schemas.ts"],"names":[],"mappings":"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"}