@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
package/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # @knpkv/confluence-to-markdown
2
+
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#14](https://github.com/knpkv/npm/pull/14) [`ddb73a3`](https://github.com/knpkv/npm/commit/ddb73a3b2633ec2e531ba2ff3f3a3b55fbadef3a) Thanks @konopkov! - Initial release of confluence-to-markdown package
8
+ - CLI with init/pull/push/sync/status commands
9
+ - Effect-TS based Confluence REST API v2 client
10
+ - Bidirectional markdown sync with frontmatter
11
+ - HTML to GFM conversion via rehype/remark
12
+ - Interactive prompts for missing CLI args
package/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # @knpkv/confluence-to-markdown
2
+
3
+ > **Warning**
4
+ > This package is experimental and in early development. Code is primarily AI-generated and not yet publicly published. For preview, use snapshot releases.
5
+
6
+ Sync Confluence Cloud pages to local GitHub Flavored Markdown files.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @knpkv/confluence-to-markdown effect
12
+ ```
13
+
14
+ ## CLI Usage
15
+
16
+ ```bash
17
+ # Initialize configuration
18
+ confluence init --root-page-id 123456 --base-url https://yoursite.atlassian.net
19
+
20
+ # Pull pages from Confluence
21
+ confluence pull
22
+
23
+ # Push local changes to Confluence
24
+ confluence push
25
+
26
+ # Bidirectional sync
27
+ confluence sync
28
+
29
+ # Check sync status
30
+ confluence status
31
+ ```
32
+
33
+ ## Configuration
34
+
35
+ Create `.confluence.json` in your project root:
36
+
37
+ ```json
38
+ {
39
+ "rootPageId": "123456",
40
+ "baseUrl": "https://yoursite.atlassian.net",
41
+ "spaceKey": "DEV",
42
+ "docsPath": ".docs/confluence"
43
+ }
44
+ ```
45
+
46
+ ## Environment Variables
47
+
48
+ ```bash
49
+ export CONFLUENCE_API_KEY=your-api-token
50
+ export CONFLUENCE_EMAIL=your-email@example.com
51
+ ```
52
+
53
+ ## Known Limitations
54
+
55
+ - **Page creation**: Creating new pages from local markdown is not yet implemented
56
+ - **Conflict detection**: Bidirectional sync does not detect conflicts (last write wins)
57
+ - **Attachments**: Image and file attachments are not synced
58
+ - **Comments**: Page comments are not preserved
59
+
60
+ ## License
61
+
62
+ MIT
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Branded types for type-safe Confluence identifiers.
3
+ *
4
+ * @module
5
+ */
6
+ import * as Brand from "effect/Brand";
7
+ import * as Schema from "effect/Schema";
8
+ /**
9
+ * Branded type for Confluence page IDs.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { PageId } from "@knpkv/confluence-to-markdown/Brand"
14
+ *
15
+ * const id = PageId("12345") // Valid
16
+ * const invalid = PageId("") // Throws BrandErrors
17
+ * ```
18
+ *
19
+ * @category Brand
20
+ */
21
+ export type PageId = string & Brand.Brand<"PageId">;
22
+ /**
23
+ * Refined brand constructor for PageId.
24
+ *
25
+ * @category Brand
26
+ */
27
+ export declare const PageId: Brand.Brand.Constructor<PageId>;
28
+ /**
29
+ * Schema for PageId validation and parsing.
30
+ *
31
+ * @category Schema
32
+ */
33
+ export declare const PageIdSchema: Schema.brand<Schema.filter<typeof Schema.String>, "PageId">;
34
+ /**
35
+ * Branded type for Confluence space keys.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * import { SpaceKey } from "@knpkv/confluence-to-markdown/Brand"
40
+ *
41
+ * const key = SpaceKey("DOCS") // Valid
42
+ * ```
43
+ *
44
+ * @category Brand
45
+ */
46
+ export type SpaceKey = string & Brand.Brand<"SpaceKey">;
47
+ /**
48
+ * Refined brand constructor for SpaceKey.
49
+ *
50
+ * @category Brand
51
+ */
52
+ export declare const SpaceKey: Brand.Brand.Constructor<SpaceKey>;
53
+ /**
54
+ * Schema for SpaceKey validation.
55
+ *
56
+ * @category Schema
57
+ */
58
+ export declare const SpaceKeySchema: Schema.brand<Schema.filter<Schema.filter<typeof Schema.String>>, "SpaceKey">;
59
+ /**
60
+ * Branded type for content hash (SHA256).
61
+ *
62
+ * @category Brand
63
+ */
64
+ export type ContentHash = string & Brand.Brand<"ContentHash">;
65
+ /**
66
+ * Refined brand constructor for ContentHash.
67
+ *
68
+ * @category Brand
69
+ */
70
+ export declare const ContentHash: Brand.Brand.Constructor<ContentHash>;
71
+ /**
72
+ * Schema for ContentHash validation.
73
+ *
74
+ * @category Schema
75
+ */
76
+ export declare const ContentHashSchema: Schema.brand<Schema.filter<typeof Schema.String>, "ContentHash">;
77
+ //# sourceMappingURL=Brand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Brand.d.ts","sourceRoot":"","sources":["../src/Brand.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;AAEnD;;;;GAIG;AACH,eAAO,MAAM,MAAM,iCAGlB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,6DAGxB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;AAEvD;;;;GAIG;AACH,eAAO,MAAM,QAAQ,mCAGpB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,8EAI1B,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;AAE7D;;;;GAIG;AACH,eAAO,MAAM,WAAW,sCAGvB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,kEAG7B,CAAA"}
package/dist/Brand.js ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Branded types for type-safe Confluence identifiers.
3
+ *
4
+ * @module
5
+ */
6
+ import * as Brand from "effect/Brand";
7
+ import * as Schema from "effect/Schema";
8
+ /**
9
+ * Refined brand constructor for PageId.
10
+ *
11
+ * @category Brand
12
+ */
13
+ export const PageId = Brand.refined((s) => typeof s === "string" && s.length > 0, (s) => Brand.error(`Invalid page ID: "${s}" (must be non-empty string)`));
14
+ /**
15
+ * Schema for PageId validation and parsing.
16
+ *
17
+ * @category Schema
18
+ */
19
+ export const PageIdSchema = Schema.String.pipe(Schema.nonEmptyString(), Schema.brand("PageId"));
20
+ /**
21
+ * Refined brand constructor for SpaceKey.
22
+ *
23
+ * @category Brand
24
+ */
25
+ export const SpaceKey = Brand.refined((s) => typeof s === "string" && s.length > 0 && /^[A-Z0-9]+$/.test(s), (s) => Brand.error(`Invalid space key: "${s}" (must be uppercase alphanumeric)`));
26
+ /**
27
+ * Schema for SpaceKey validation.
28
+ *
29
+ * @category Schema
30
+ */
31
+ export const SpaceKeySchema = Schema.String.pipe(Schema.nonEmptyString(), Schema.pattern(/^[A-Z0-9]+$/), Schema.brand("SpaceKey"));
32
+ /**
33
+ * Refined brand constructor for ContentHash.
34
+ *
35
+ * @category Brand
36
+ */
37
+ export const ContentHash = Brand.refined((s) => typeof s === "string" && /^[a-f0-9]{64}$/.test(s), (s) => Brand.error(`Invalid content hash: "${s}" (must be 64-char hex string)`));
38
+ /**
39
+ * Schema for ContentHash validation.
40
+ *
41
+ * @category Schema
42
+ */
43
+ export const ContentHashSchema = Schema.String.pipe(Schema.pattern(/^[a-f0-9]{64}$/), Schema.brand("ContentHash"));
44
+ //# sourceMappingURL=Brand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Brand.js","sourceRoot":"","sources":["../src/Brand.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAiBvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CACjC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EACzD,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,qBAAqB,CAAC,8BAA8B,CAAC,CACzE,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAC5C,MAAM,CAAC,cAAc,EAAE,EACvB,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CACvB,CAAA;AAgBD;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CACnC,CAAC,CAAC,EAAiB,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EACpF,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,oCAAoC,CAAC,CACjF,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAC9C,MAAM,CAAC,cAAc,EAAE,EACvB,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAC7B,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CACzB,CAAA;AASD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CACtC,CAAC,CAAC,EAAoB,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAC1E,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,0BAA0B,CAAC,gCAAgC,CAAC,CAChF,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CACjD,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAChC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAC5B,CAAA"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Confluence REST API v2 client service.
3
+ *
4
+ * @module
5
+ */
6
+ import * as HttpClient from "@effect/platform/HttpClient";
7
+ import * as Context from "effect/Context";
8
+ import * as Effect from "effect/Effect";
9
+ import * as Layer from "effect/Layer";
10
+ import type { PageId } from "./Brand.js";
11
+ import { ApiError, RateLimitError } from "./ConfluenceError.js";
12
+ import type { PageChildrenResponse, PageListItem, PageResponse } from "./Schemas.js";
13
+ /**
14
+ * Request to create a new page.
15
+ *
16
+ * @category Types
17
+ */
18
+ export interface CreatePageRequest {
19
+ readonly spaceId: string;
20
+ readonly title: string;
21
+ readonly parentId?: string;
22
+ readonly body: {
23
+ readonly representation: "storage";
24
+ readonly value: string;
25
+ };
26
+ }
27
+ /**
28
+ * Request to update an existing page.
29
+ *
30
+ * @category Types
31
+ */
32
+ export interface UpdatePageRequest {
33
+ readonly id: string;
34
+ readonly title: string;
35
+ readonly status?: "current" | "draft";
36
+ readonly version: {
37
+ readonly number: number;
38
+ readonly message?: string;
39
+ };
40
+ readonly body: {
41
+ readonly representation: "storage";
42
+ readonly value: string;
43
+ };
44
+ }
45
+ declare const ConfluenceClient_base: Context.TagClass<ConfluenceClient, "@knpkv/confluence-to-markdown/ConfluenceClient", {
46
+ /**
47
+ * Get a page by ID.
48
+ */
49
+ readonly getPage: (id: PageId) => Effect.Effect<PageResponse, ApiError | RateLimitError>;
50
+ /**
51
+ * Get children of a page.
52
+ */
53
+ readonly getChildren: (id: PageId) => Effect.Effect<PageChildrenResponse, ApiError | RateLimitError>;
54
+ /**
55
+ * Get all children recursively (handles pagination).
56
+ */
57
+ readonly getAllChildren: (id: PageId) => Effect.Effect<ReadonlyArray<PageListItem>, ApiError | RateLimitError>;
58
+ /**
59
+ * Create a new page.
60
+ */
61
+ readonly createPage: (request: CreatePageRequest) => Effect.Effect<PageResponse, ApiError | RateLimitError>;
62
+ /**
63
+ * Update an existing page.
64
+ */
65
+ readonly updatePage: (request: UpdatePageRequest) => Effect.Effect<PageResponse, ApiError | RateLimitError>;
66
+ /**
67
+ * Delete a page.
68
+ */
69
+ readonly deletePage: (id: PageId) => Effect.Effect<void, ApiError | RateLimitError>;
70
+ }>;
71
+ /**
72
+ * Confluence REST API v2 client service.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * import { ConfluenceClient } from "@knpkv/confluence-to-markdown/ConfluenceClient"
77
+ * import { Effect } from "effect"
78
+ *
79
+ * const program = Effect.gen(function* () {
80
+ * const client = yield* ConfluenceClient
81
+ * const page = yield* client.getPage("12345")
82
+ * console.log(page.title)
83
+ * })
84
+ * ```
85
+ *
86
+ * @category Client
87
+ */
88
+ export declare class ConfluenceClient extends ConfluenceClient_base {
89
+ }
90
+ /**
91
+ * Configuration for the Confluence client.
92
+ *
93
+ * @category Config
94
+ */
95
+ export interface ConfluenceClientConfig {
96
+ readonly baseUrl: string;
97
+ readonly auth: {
98
+ readonly type: "token";
99
+ readonly email: string;
100
+ readonly token: string;
101
+ } | {
102
+ readonly type: "oauth2";
103
+ readonly accessToken: string;
104
+ };
105
+ }
106
+ /**
107
+ * Layer that provides ConfluenceClient with direct configuration.
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * import { ConfluenceClient } from "@knpkv/confluence-to-markdown/ConfluenceClient"
112
+ * import { NodeHttpClient } from "@effect/platform-node"
113
+ * import { Effect } from "effect"
114
+ *
115
+ * const program = Effect.gen(function* () {
116
+ * const client = yield* ConfluenceClient
117
+ * const page = yield* client.getPage("12345")
118
+ * console.log(page.title)
119
+ * })
120
+ *
121
+ * Effect.runPromise(
122
+ * program.pipe(
123
+ * Effect.provide(ConfluenceClient.layer({
124
+ * baseUrl: "https://yoursite.atlassian.net",
125
+ * auth: {
126
+ * type: "token",
127
+ * email: "you@example.com",
128
+ * token: process.env.CONFLUENCE_API_KEY
129
+ * }
130
+ * })),
131
+ * Effect.provide(NodeHttpClient.layer)
132
+ * )
133
+ * )
134
+ * ```
135
+ *
136
+ * @category Layers
137
+ */
138
+ export declare const layer: (config: ConfluenceClientConfig) => Layer.Layer<ConfluenceClient, never, HttpClient.HttpClient>;
139
+ export {};
140
+ //# sourceMappingURL=ConfluenceClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfluenceClient.d.ts","sourceRoot":"","sources":["../src/ConfluenceClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Confluence REST API v2 client service.
3
+ *
4
+ * @module
5
+ */
6
+ import * as HttpClient from "@effect/platform/HttpClient";
7
+ import * as HttpClientRequest from "@effect/platform/HttpClientRequest";
8
+ import * as Context from "effect/Context";
9
+ import * as Effect from "effect/Effect";
10
+ import * as Layer from "effect/Layer";
11
+ import * as Schedule from "effect/Schedule";
12
+ import * as Schema from "effect/Schema";
13
+ import { ApiError, RateLimitError } from "./ConfluenceError.js";
14
+ import { PageChildrenResponseSchema, PageResponseSchema } from "./Schemas.js";
15
+ /**
16
+ * Confluence REST API v2 client service.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { ConfluenceClient } from "@knpkv/confluence-to-markdown/ConfluenceClient"
21
+ * import { Effect } from "effect"
22
+ *
23
+ * const program = Effect.gen(function* () {
24
+ * const client = yield* ConfluenceClient
25
+ * const page = yield* client.getPage("12345")
26
+ * console.log(page.title)
27
+ * })
28
+ * ```
29
+ *
30
+ * @category Client
31
+ */
32
+ export class ConfluenceClient extends Context.Tag("@knpkv/confluence-to-markdown/ConfluenceClient")() {
33
+ }
34
+ /**
35
+ * Rate limit retry schedule with exponential backoff.
36
+ */
37
+ const rateLimitSchedule = Schedule.exponential("1 second").pipe(Schedule.union(Schedule.spaced("30 seconds")), Schedule.whileInput((error) => error._tag === "RateLimitError"), Schedule.intersect(Schedule.recurs(3)));
38
+ /**
39
+ * Create the Confluence client service.
40
+ */
41
+ const make = (config) => Effect.gen(function* () {
42
+ const httpClient = yield* HttpClient.HttpClient;
43
+ const authHeader = config.auth.type === "token"
44
+ ? `Basic ${Buffer.from(`${config.auth.email}:${config.auth.token}`).toString("base64")}`
45
+ : `Bearer ${config.auth.accessToken}`;
46
+ const baseRequest = HttpClientRequest.get(`${config.baseUrl}/wiki/api/v2`).pipe(HttpClientRequest.setHeader("Authorization", authHeader), HttpClientRequest.setHeader("Accept", "application/json"), HttpClientRequest.setHeader("Content-Type", "application/json"));
47
+ const request = (method, path, body) => Effect.gen(function* () {
48
+ let req = baseRequest.pipe(HttpClientRequest.setMethod(method), HttpClientRequest.setUrl(`${config.baseUrl}/wiki/api/v2${path}`));
49
+ if (body !== undefined) {
50
+ req = HttpClientRequest.bodyJson(req, body).pipe(Effect.catchAll(() => Effect.succeed(req)), Effect.runSync);
51
+ }
52
+ const response = yield* httpClient.execute(req).pipe(Effect.mapError((error) => new ApiError({
53
+ status: 0,
54
+ message: `Request failed: ${error.message}`,
55
+ endpoint: path
56
+ })));
57
+ if (response.status === 429) {
58
+ const retryAfterHeader = response.headers["retry-after"];
59
+ const retryAfter = retryAfterHeader ? parseInt(retryAfterHeader, 10) : undefined;
60
+ return yield* Effect.fail(retryAfter !== undefined
61
+ ? new RateLimitError({ retryAfter })
62
+ : new RateLimitError({}));
63
+ }
64
+ if (response.status >= 400) {
65
+ const text = yield* response.text.pipe(Effect.catchAll(() => Effect.succeed("")));
66
+ return yield* Effect.fail(new ApiError({
67
+ status: response.status,
68
+ message: text || `HTTP ${response.status}`,
69
+ endpoint: path
70
+ }));
71
+ }
72
+ if (method === "DELETE" && response.status === 204) {
73
+ return undefined;
74
+ }
75
+ const json = yield* response.json.pipe(Effect.mapError((error) => new ApiError({
76
+ status: response.status,
77
+ message: `Failed to parse response: ${error}`,
78
+ endpoint: path
79
+ })));
80
+ return json;
81
+ }).pipe(Effect.retry(rateLimitSchedule));
82
+ const getPage = (id) => Effect.gen(function* () {
83
+ const raw = yield* request("GET", `/pages/${id}?body-format=storage`);
84
+ return yield* Schema.decodeUnknown(PageResponseSchema)(raw).pipe(Effect.mapError((error) => new ApiError({
85
+ status: 0,
86
+ message: `Invalid response schema: ${error.message}`,
87
+ endpoint: `/pages/${id}`,
88
+ pageId: id
89
+ })));
90
+ });
91
+ const getChildren = (id) => Effect.gen(function* () {
92
+ const raw = yield* request("GET", `/pages/${id}/children?body-format=storage`);
93
+ return yield* Schema.decodeUnknown(PageChildrenResponseSchema)(raw).pipe(Effect.mapError((error) => new ApiError({
94
+ status: 0,
95
+ message: `Invalid response schema: ${error.message}`,
96
+ endpoint: `/pages/${id}/children`,
97
+ pageId: id
98
+ })));
99
+ });
100
+ const getAllChildren = (id) => Effect.gen(function* () {
101
+ const allChildren = [];
102
+ let cursor;
103
+ let iterations = 0;
104
+ const maxIterations = 100; // Prevent unbounded pagination
105
+ do {
106
+ if (iterations >= maxIterations) {
107
+ return yield* Effect.fail(new ApiError({
108
+ status: 0,
109
+ message: `Pagination limit exceeded: more than ${maxIterations} pages of children`,
110
+ endpoint: `/pages/${id}/children`,
111
+ pageId: id
112
+ }));
113
+ }
114
+ const path = cursor
115
+ ? `/pages/${id}/children?body-format=storage&cursor=${cursor}`
116
+ : `/pages/${id}/children?body-format=storage`;
117
+ const raw = yield* request("GET", path);
118
+ const response = yield* Schema.decodeUnknown(PageChildrenResponseSchema)(raw).pipe(Effect.mapError((error) => new ApiError({
119
+ status: 0,
120
+ message: `Invalid response schema: ${error.message}`,
121
+ endpoint: path,
122
+ pageId: id
123
+ })));
124
+ for (const child of response.results) {
125
+ allChildren.push(child);
126
+ }
127
+ // Extract cursor from next link if present
128
+ cursor = response._links?.next
129
+ ? new URL(response._links.next, config.baseUrl).searchParams.get("cursor") ?? undefined
130
+ : undefined;
131
+ iterations++;
132
+ } while (cursor);
133
+ return allChildren;
134
+ });
135
+ const createPage = (req) => Effect.gen(function* () {
136
+ const raw = yield* request("POST", "/pages", req);
137
+ return yield* Schema.decodeUnknown(PageResponseSchema)(raw).pipe(Effect.mapError((error) => new ApiError({
138
+ status: 0,
139
+ message: `Invalid response schema: ${error.message}`,
140
+ endpoint: "/pages"
141
+ })));
142
+ });
143
+ const updatePage = (req) => Effect.gen(function* () {
144
+ const raw = yield* request("PUT", `/pages/${req.id}`, req);
145
+ return yield* Schema.decodeUnknown(PageResponseSchema)(raw).pipe(Effect.mapError((error) => new ApiError({
146
+ status: 0,
147
+ message: `Invalid response schema: ${error.message}`,
148
+ endpoint: `/pages/${req.id}`,
149
+ pageId: req.id
150
+ })));
151
+ });
152
+ const deletePage = (id) => request("DELETE", `/pages/${id}`);
153
+ return ConfluenceClient.of({
154
+ getPage,
155
+ getChildren,
156
+ getAllChildren,
157
+ createPage,
158
+ updatePage,
159
+ deletePage
160
+ });
161
+ });
162
+ /**
163
+ * Layer that provides ConfluenceClient with direct configuration.
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * import { ConfluenceClient } from "@knpkv/confluence-to-markdown/ConfluenceClient"
168
+ * import { NodeHttpClient } from "@effect/platform-node"
169
+ * import { Effect } from "effect"
170
+ *
171
+ * const program = Effect.gen(function* () {
172
+ * const client = yield* ConfluenceClient
173
+ * const page = yield* client.getPage("12345")
174
+ * console.log(page.title)
175
+ * })
176
+ *
177
+ * Effect.runPromise(
178
+ * program.pipe(
179
+ * Effect.provide(ConfluenceClient.layer({
180
+ * baseUrl: "https://yoursite.atlassian.net",
181
+ * auth: {
182
+ * type: "token",
183
+ * email: "you@example.com",
184
+ * token: process.env.CONFLUENCE_API_KEY
185
+ * }
186
+ * })),
187
+ * Effect.provide(NodeHttpClient.layer)
188
+ * )
189
+ * )
190
+ * ```
191
+ *
192
+ * @category Layers
193
+ */
194
+ export const layer = (config) => Layer.effect(ConfluenceClient, make(config));
195
+ //# sourceMappingURL=ConfluenceClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfluenceClient.js","sourceRoot":"","sources":["../src/ConfluenceClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Configuration service for Confluence sync.
3
+ *
4
+ * @module
5
+ */
6
+ import * as FileSystem from "@effect/platform/FileSystem";
7
+ import * as Path from "@effect/platform/Path";
8
+ import * as Context from "effect/Context";
9
+ import * as Effect from "effect/Effect";
10
+ import * as Layer from "effect/Layer";
11
+ import type { PageId } from "./Brand.js";
12
+ import { ConfigNotFoundError, ConfigParseError } from "./ConfluenceError.js";
13
+ import type { ConfluenceConfigFile } from "./Schemas.js";
14
+ declare const ConfluenceConfig_base: Context.TagClass<ConfluenceConfig, "@knpkv/confluence-to-markdown/ConfluenceConfig", {
15
+ /** Root page ID to sync from */
16
+ readonly rootPageId: PageId;
17
+ /** Confluence Cloud base URL */
18
+ readonly baseUrl: string;
19
+ /** Optional space key */
20
+ readonly spaceKey?: string;
21
+ /** Local docs path */
22
+ readonly docsPath: string;
23
+ /** Glob patterns to exclude */
24
+ readonly excludePatterns: ReadonlyArray<string>;
25
+ }>;
26
+ /**
27
+ * Configuration service for Confluence operations.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * import { ConfluenceConfig } from "@knpkv/confluence-to-markdown/ConfluenceConfig"
32
+ * import { Effect } from "effect"
33
+ *
34
+ * const program = Effect.gen(function* () {
35
+ * const config = yield* ConfluenceConfig
36
+ * console.log(config.rootPageId)
37
+ * console.log(config.baseUrl)
38
+ * })
39
+ * ```
40
+ *
41
+ * @category Config
42
+ */
43
+ export declare class ConfluenceConfig extends ConfluenceConfig_base {
44
+ }
45
+ /**
46
+ * Layer that provides ConfluenceConfig from a config file.
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { ConfluenceConfig } from "@knpkv/confluence-to-markdown/ConfluenceConfig"
51
+ * import { NodeFileSystem } from "@effect/platform-node"
52
+ * import { Effect } from "effect"
53
+ *
54
+ * const program = Effect.gen(function* () {
55
+ * const config = yield* ConfluenceConfig
56
+ * console.log(config.rootPageId)
57
+ * })
58
+ *
59
+ * Effect.runPromise(
60
+ * program.pipe(
61
+ * Effect.provide(ConfluenceConfig.layer()),
62
+ * Effect.provide(NodeFileSystem.layer)
63
+ * )
64
+ * )
65
+ * ```
66
+ *
67
+ * @category Layers
68
+ */
69
+ export declare const layer: (configPath?: string) => Layer.Layer<ConfluenceConfig, ConfigNotFoundError | ConfigParseError, FileSystem.FileSystem | Path.Path>;
70
+ /**
71
+ * Layer that provides ConfluenceConfig with direct values.
72
+ *
73
+ * @category Layers
74
+ */
75
+ export declare const layerFromValues: (config: ConfluenceConfigFile) => Layer.Layer<ConfluenceConfig>;
76
+ /**
77
+ * Create a new config file.
78
+ *
79
+ * @category Utilities
80
+ */
81
+ export declare const createConfigFile: (rootPageId: string, baseUrl: string, configPath?: string) => Effect.Effect<string, ConfigParseError, FileSystem.FileSystem | Path.Path>;
82
+ export {};
83
+ //# sourceMappingURL=ConfluenceConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfluenceConfig.d.ts","sourceRoot":"","sources":["../src/ConfluenceConfig.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,UAAU,MAAM,6BAA6B,CAAA;AACzD,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAA;AAC7C,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAC5E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;;IAyBpD,gCAAgC;yBACX,MAAM;IAC3B,gCAAgC;sBACd,MAAM;IACxB,yBAAyB;wBACL,MAAM;IAC1B,sBAAsB;uBACH,MAAM;IACzB,+BAA+B;8BACL,aAAa,CAAC,MAAM,CAAC;;AA/BnD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAiB,SAAQ,qBAgBnC;CAAG;AAqCN;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,KAAK,GAChB,aAAa,MAAM,KAClB,KAAK,CAAC,KAAK,CAAC,gBAAgB,EAAE,mBAAmB,GAAG,gBAAgB,EAAE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAgBvG,CAAA;AAEH;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,QAAQ,oBAAoB,KAC3B,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAU5B,CAAA;AAEH;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAC3B,YAAY,MAAM,EAClB,SAAS,MAAM,EACf,aAAa,MAAM,KAClB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAyBxE,CAAA"}