Skip to content

[Feature]: Confluence versions support #63

@stropho

Description

@stropho

Package

markdown-confluence-sync

Description

Hello everyone,
thanks for the effort. The features regarding the conversion markdown to confluence pages are great.
I've been trying it out for the last couple of days, and unfortunately I cannot use it as is. The main painful point is that some of the deprecated endpoints in use are not available in Atlassian Cloud anymore - namely ${this._config.url}/rest/api/content/${parentId}/child -

`${this._config.url}/rest/api/content/${parentId}/child`,

After a few tweaks, I made it work 🎉
diff --git a/node_modules/@telefonica/confluence-sync/dist/confluence/CustomConfluenceClient.js b/node_modules/@telefonica/confluence-sync/dist/confluence/CustomConfluenceClient.js
index a03b8f3..bb99509 100644
--- a/node_modules/@telefonica/confluence-sync/dist/confluence/CustomConfluenceClient.js
+++ b/node_modules/@telefonica/confluence-sync/dist/confluence/CustomConfluenceClient.js
@@ -16,6 +16,7 @@ const DeletePageError_1 = require("./errors/DeletePageError");
 const PageNotFoundError_1 = require("./errors/PageNotFoundError");
 const UpdatePageError_1 = require("./errors/UpdatePageError");
 const GET_CHILDREN_LIMIT = 100;
+const apiPrefix = "";
 const CustomConfluenceClient = class CustomConfluenceClient {
     _config;
     _client;
@@ -25,9 +26,12 @@ const CustomConfluenceClient = class CustomConfluenceClient {
         this._client = new confluence_js_1.ConfluenceClient({
             host: config.url,
             authentication: {
-                personalAccessToken: config.personalAccessToken,
+                basic: {
+                    email: '[email protected]',
+                    apiToken: 'token...',
+                }
             },
-            apiPrefix: "/rest/",
+            apiPrefix,
         });
         this._logger = config.logger;
     }
@@ -38,7 +42,8 @@ const CustomConfluenceClient = class CustomConfluenceClient {
     async _getChildPages(parentId, start = 0, otherChildren = []) {
         try {
             this._logger.silly(`Getting child pages of parent with id ${parentId}`);
-            const response = await axios_1.default.get(`${this._config.url}/rest/api/content/${parentId}/child`, {
+            // const response = await axios_1.default.get(`${this._config.url}/rest/api/content/${parentId}/child`, {
+            const response = await axios_1.default.get(`${this._config.url}/${apiPrefix ? apiPrefix + '/' : ''}wiki/api/v2/pages/${parentId}/descendants`, {
                 params: {
                     start,
                     limit: GET_CHILDREN_LIMIT,
@@ -46,11 +51,11 @@ const CustomConfluenceClient = class CustomConfluenceClient {
                 },
                 headers: {
                     accept: "application/json",
-                    Authorization: `Bearer ${this._config.personalAccessToken}`,
+                    Authorization: `Basic BASE64encoded-name-and-token`,
                 },
             });
             this._logger.silly(`Get child pages response of page ${parentId}, starting at ${start}: ${JSON.stringify(response.data, null, 2)}`);
-            const childrenResults = response.data.page?.results || [];
+            const childrenResults = response.data.results || [];
             const size = response.data.page?.size || 0;
             const allChildren = [
                 ...otherChildren,

Suggested Solution

So now I'm thinking how to make some changes, so it's easy enough to do, and maybe improve the code for better maintenance. Let's discuss some options. It would be great to possibly use some parts of the confluence-tools with more confluence versions.

Option 1 - Separate markdown-to-confluence-content

The easiest option I can think of is to have a standalone package to convert markdown to the content to be uploaded (html, images,..). Possibly with the ability to add more rehype and reflow transforms...

Pros:

  • anybody can generate the content, and upload it on his/her own.

Cons:

  • confluence-sync logic cannot be reused as it uses irrelevant (based on confluence version) REST endpoints

Option 2 - Endpoints Provider

Another approach could be to introduce an Endpoints Provider abstraction. This would allow the core logic to remain the same, but the actual REST endpoints used could be swapped (~injected) by the user depending on the Confluence version and the endpoints available. As long as there is a clearly defined interface, this could work nicely.

Example

getConfluenceConnector = () => {
  return {
    getDescendantPages: (params) => {/* ... */}
    updatePage: (params) => {/* ... */}
    // ...
    // attachments ...
  }
}

Pros:

  • support for multiple Confluence versions without duplicating logic.
  • user can define such logic on their own
  • possible to use additional authentication mechanisms.
  • confluence-sync could still be used

Cons:

  • probably not straight forward to add such configuration to text based configs like yaml or json.

Option 3 - More Configuration Options

..to support multiple confluence version..
No. That just crossed my mind. It's a nightmare to have too many configuration options. Both UX and maintenance.


Feel free to add more ideas to the discussions. I'm willing to contribute with some PRs.
Once again, great tools you have here :-)

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

Labels

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions