guide迁移到 Node.js 中的 RTC

本文介绍了一个应用程序示例,该应用程序允许将非实时协作中创建的用户和文档迁移到实时协作。

# 依赖项

此示例使用以下依赖项

  • axios
  • body-parser
  • cors
  • express

它还使用 Node.js 的核心依赖项:pathfs

# 示例

以下示例允许您上传一个 编辑器捆绑包,创建一个 用户将文档导入实时协作

以下示例将涵盖

  • 将编辑器捆绑包上传到 CKEditor 云服务
  • 创建实时协作用户
  • 映射文档及其所有数据(来自非实时协作),并将其导入 CKEditor 云服务

以下是一个简单的 Express.js 应用程序示例。

请记住提供正确的 API 密钥并生成适当的 请求签名

// mapDocumentData.js

/**
 * Maps all data for the document to the structure and assigns data missing in non-RTC 
 * according to the CKEditor Cloud Services' requirements.
 * 
 * @param {Object} [documentData] The whole data of the document with all its resources saved from the non Real-time Collaboration.
 * @param {String} [documentData.documentId] The ID of the document to import
 * @param {String} [documentData.bundleVersion] The version of the bundled editor to use for the document
 * @param {String} [documentData.editorData] The content of the document in HTML or Markdown
 * @param {Array.<Object>} [documentData.commentThreadsData]
 * @param {Array.<Object>} [documentData.suggestionsData]
 * @param {Array.<Object>} [documentData.revisionsData]
 * @param {String} [suggestionAuthorID] the ID of the user to assign for suggestions that don't have an author assigned to them
 * @returns {Object}
 */
function mapDocumentData( documentData = {}, suggestionAuthorID ) {
    const threads = [];
    const comments = [];

    const {
        commentThreadsData = [],
        suggestionsData = [],
        revisionsData = [],
        documentId,
        bundleVersion,
        editorData
    } = documentData;

    commentThreadsData.forEach( commentThread => {
        const hasMatchingSuggestion = suggestionsData.some( suggestion => suggestion.id === commentThread.id );

        threads.push( {
            id: commentThread.threadId,
            context: commentThread.context,
            resolved_at: commentThread.resolvedAt,
            resolved_by: commentThread.resolvedBy,
            attributes: commentThread.attributes,
            author_id: commentThread.authorId
        } );

        comments.push(
            ...commentThread.comments.map( comment => ( {
                id: comment.commentId,
                thread_id: commentThread.threadId,
                content: comment.content,
                attributes: comment.attributes,
                user: { id: comment.authorId },
                created_at: comment.created_at,
                type: hasMatchingSuggestion ? 2 : 1
            } ) )
        );
    } );

    const revisions = [];
    let version = 1;

    revisionsData.forEach( ( revision, index ) => {
        if ( revision.toVersion > version ) {
            version = revision.toVersion;
        }

        revisions.push( {
            revision_id: revision.id,
            request_id: index,
            name: revision.name,
            creator_id: revision.authorId,
            authors_ids: revision.authors_ids,
            diff_data: JSON.stringify( revision.diffData ),
            created_at: revision.createdAt,
            attributes: revision.attributes,
            from_version: revision.fromVersion,
            to_version: revision.toVersion
        } )
    } );

    const suggestions = suggestionsData.map( suggestion => ( {
        id: suggestion.id,
        type: suggestion.type,
        author_id: suggestion.authorId ?? suggestionAuthorID,
        created_at: suggestion.createdAt,
        has_comments: suggestion.hasComments,
        data: suggestion.data,
        attributes: suggestion.attributes,
    } ) )

    const importBody = {
        id: documentId,
        content: {
            bundle_version: bundleVersion,
            data: editorData,
            version: version ?? undefined
        },
        comments,
        suggestions,
        revisions,
        threads
    };

    return importBody;
}
// index.js
const path = require( 'path' );
const fs = require( 'fs' );
const express = require( 'express' );
const axios = require( 'axios' );
const cors = require( 'cors' );
const bodyParser = require( 'body-parser' );
const generateSignature = require( './utils/generateSignature' ); // See: https://ckeditor.npmjs.net.cn/docs/cs/latest/examples/security/request-signature-nodejs.html.
const mapDocumentData = require( './utils/mapDocumentData' );
const editorBundle = fs.readFileSync( path.resolve( '../client/build/ckeditor.js' ) ); // It should be your bundled editor.

const app = express();
const port = 8000; // The default application port.
const apiSecret = 'SECRET'; // Do not forget to hide this value in a safe place e.g. a .env file!
const organizationId = 'organizationId'; // Type your organization ID here.
const environmentId = 'environmentId'; // Type your environment ID here.
// If you use On-Premises application you can adjust baseApiUrl accordingly with your application URL.
const baseApiUrl = `https://${ organizationId }.cke-cs.com/api/v5/${ environmentId }`;

app.use( bodyParser.urlencoded( { extended: true } ) );
app.use( bodyParser.json() );
app.use( cors() );

// This function will be responsible for sending requests to CKEditor Cloud Services API.
async function sendRequest( method, url, body ) {
    const CSTimestamp = Date.now();
    const payload = {
        method,
        url,
        mode: 'no-cors',
        headers: {
            'Content-Type': 'application/json',
            'X-CS-Signature': generateSignature( apiSecret, method, url, CSTimestamp, body ),
            'X-CS-Timestamp': CSTimestamp
        }
    };

    if ( method.toUpperCase() !== 'GET' ) {
        payload.data = body;
    }

    try {
        const { status, data } = await axios( payload );

        return { status, data };
    } catch ( { response } ) {
        const { status, data } = response;

        return { status, data };
    }
}

// Upload the editor bundle. Note that you will need to upload your editor again if you change the bundle.
app.post( '/upload-editor', async ( req, res ) => {
    const { bundleVersion } = req.body;

    const { status, data } = await sendRequest( 'POST', `${ baseApiUrl }/editors`, {
        bundle: editorBundle.toString(),
        config: {
            cloudServices: {
                bundleVersion // This value should be unique per environment.
            }
        }
    } );

    return res.json( { status, data } );
} );

// Create a user for Real-time Collaboration.
app.post( '/create-user', async ( req, res ) => {
    const { email, id, name } = req.body;

    const { status, data } = await sendRequest( 'POST', `${ baseApiUrl }/users`, {
        id,
        email,
        name
    } );

    return res.json( { status, data } );
} );

// Import a document to the CKEditor Cloud Services.
app.post( '/import-document', async ( req, res ) => {
    const { 
        documentData,
        suggestionAuthorId
    } = req.body;

    const importBody = mapDocumentData( documentData, suggestionAuthorId );

    const { status, data } = await sendRequest( 'POST', `${ baseApiUrl }/documents`, importBody );

    return res.json( { status, data } );
} );

app.listen( port, () => console.log( `The application is listening on port ${ port }!` ) );

# 使用

运行

node index.js

通过向此应用程序发送 HTTP 请求,您现在可以执行操作并与 CKEditor 云服务通信。请参阅以下示例

  1. 上传编辑器捆绑包。
try {
    const response = await fetch( 'https://127.0.0.1:8000/upload-editor', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify( { bundleVersion: '1.0.0' } )
    } );

    const data = await response.json();

    console.log( 'Result of uploading editor:', data );
} catch ( error ) {
    console.log( 'Error occurred when uploading editor:', error );
}
  1. 创建用户。
try {
    const response = await fetch( 'https://127.0.0.1:8000/create-user', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify( { 
            id: 'user-1',
            email: 'example@example.com',
            name: 'Example user'
        } )
    } );

    const data = await response.json();

    console.log( 'Result of uploading user:', data );
} catch ( error ) {
    console.log( 'Error occurred when uploading user:', error );
}
  1. 将文档导入 CKEditor 云服务。对于 documentData,您可以使用从服务器获取的数据,或者使用以下示例。
单击查看示例数据。
{
    "documentId": "document-1",
    "bundleVersion": "1.0.0",
    "editorData": "<h2 style=\"text-align:center;\">NON-DISCLOSURE AGREEMENT (NDA)</h2><p>&nbsp;</p><p>This Nondisclosure Agreement or (\"Agreement\") has been entered into on the <suggestion-start name=\"deletion:ea6c5028e3c0efaf0b9a23d227d89696c:user-1\"></suggestion-start>the <suggestion-end name=\"deletion:ea6c5028e3c0efaf0b9a23d227d89696c:user-1\"></suggestion-end>date of 10.05.2021 and is by and between:</p><p><strong>Party Disclosing Information:</strong> James Lahey with a mailing address of <comment-start name=\"eca0c3e71883a578ee37bdc0e510a41a8:49cf1\"></comment-start>3 Maple Rd. Spryfield B3P 1H8<comment-end name=\"eca0c3e71883a578ee37bdc0e510a41a8:49cf1\"></comment-end> &nbsp;(\"Disclosing Party\").</p><p><strong>Party Receiving Information:</strong> &nbsp;Richard Lafleur with a mailing address of &nbsp;1 Bonnyville Dr. Spryfield B3P 1H8 (\"Receiving Party\"). For the purpose of preventing the unauthorized disclosure of Confidential Information as defined below. The parties agree to enter into a confidential relationship concerning the disclosure of certain <suggestion-start name=\"insertion:e64910f0cd32232aac1cce1c6b5b565b6:user-1\"></suggestion-start>proprietary<suggestion-end name=\"insertion:e64910f0cd32232aac1cce1c6b5b565b6:user-1\"></suggestion-end><suggestion-start name=\"deletion:e513f8e2e4eca79825823ff00294f3716:user-1\"></suggestion-start>business<suggestion-end name=\"deletion:e513f8e2e4eca79825823ff00294f3716:user-1\"></suggestion-end> property and confidential information (\"Confidential Information\").</p><p>&nbsp;</p><h2>1. Definition of Confidential Information</h2><p>For purposes of this Agreement, \"Confidential Information\" shall include all information or material that has or could have commercial value or other utility in the business in which the Disclosing Party is engaged. If Confidential Information is in written form, the Disclosing Party shall label or stamp the materials with the word \"Confidential\" or some similar warning. If Confidential Information is transmitted orally, the Disclosing Party shall promptly provide a writing indicating that such oral communication constituted Confidential Information.</p><h2>2. Exclusions from Confidential Information</h2><p>Receiving Party's obligations under this Agreement do not extend to information that is:(a) publicly known at the time of disclosure or subsequently becomes publicly known through no fault of the Receiving Party; (b) discovered or created by the Receiving Party before disclosure by Disclosing Party; (c) learned by the Receiving Party through legitimate means other than from the Disclosing Party or Disclosing Party's representatives; or (d) is disclosed by Receiving Party with Disclosing Party's prior written approval.</p><h2>3. Obligations of Receiving Party</h2><p>Receiving Party shall hold and maintain the Confidential Information in strictest confidence for the sole and exclusive benefit of the Disclosing Party. Receiving Party shall carefully restrict access to Confidential Information to employees, contractors and third parties as is reasonably required and shall require those persons to sign nondisclosure restrictions at least as protective as those in this Agreement. Receiving Party shall not, without the prior written approval of Disclosing Party, use for Receiving Party's benefit, publish, copy, or otherwise disclose to others, or permit the use by others for their benefit or to the detriment of Disclosing Party, any Confidential Information. Receiving Party shall return to Disclosing Party any and all records, notes, and other written, printed, or tangible materials in its possession pertaining to Confidential Information immediately if Disclosing Party requests it in writing.</p><h2>4. Time Periods</h2><p>The nondisclosure provisions of this Agreement shall survive the termination of this Agreement and Receiving Party's duty to hold Confidential Information in confidence shall remain in effect until the Confidential Information no longer qualifies as a trade secret or until Disclosing Party sends Receiving Party written notice releasing Receiving Party from this Agreement, whichever occurs first.</p><h2>5. Relationships</h2><p>Nothing contained in this Agreement shall be deemed to constitute either party a partner, joint venture or employee of the other party for any purpose.</p><h2>6. Severability</h2><p>If a court finds any provision of this Agreement invalid or unenforceable, the remainder of this Agreement shall be interpreted so as best to affect the intent of the parties.</p><h2>7. Integration</h2><p>This Agreement expresses the complete understanding of the parties with respect to the subject matter and supersedes all prior proposals, agreements, representations, and understandings. This Agreement may not be amended except in writing signed by both parties.</p><h2>8. Waiver</h2><p>The failure to exercise any right provided in this Agreement shall not be a waiver of prior or subsequent rights.</p><h2>9. Notice of Immunity</h2><p>Employee is provided notice that an individual shall not be held criminally or civilly liable under any federal or state trade secret law for the disclosure of a trade secret that is made <comment-start name=\"e5964fb81e95e0cd712ecf95fafad425f:57cf0\"></comment-start>(i)<comment-end name=\"e5964fb81e95e0cd712ecf95fafad425f:57cf0\"></comment-end> in confidence to a federal, state, or local government official, either directly or indirectly, or to an attorney; and (ii) solely for the purpose of reporting or investigating a suspected violation of law; or is made in a complaint or other document filed in a lawsuit or other proceeding, if such filing is made under seal. An individual who files a lawsuit for retaliation by an employer for reporting a suspected violation of law may disclose the trade secret to the attorney of the individual and use the trade secret information in the court proceeding, if the individual (i) files any document containing the trade secret under seal; and (ii) does not disclose the trade secret, except pursuant to court order. This Agreement and each party's obligations shall be binding on the representatives, assigns and successors of such party. Each party has signed this Agreement through its authorized representative.</p><p>&nbsp;</p><p>&nbsp;</p><p><strong>DISCLOSING PARTY Signature:</strong> _____________________________________________________</p><p><strong>Typed or Printed Name:</strong> James Lahey</p><p><strong>Date:</strong> 10.05.2021</p><p>&nbsp;</p><p><strong>RECEIVING PARTY Signature:</strong> _____________________________________________________</p><p><strong>Typed or Printed Name:</strong> Richard Lafleur</p><p><strong>Date:</strong> 10.05.2021</p>",
    "commentThreadsData": [
        {
            "threadId": "eca0c3e71883a578ee37bdc0e510a41a8",
            "context": {
            "type": "text",
            "value": "3 Maple Rd. Spryfield B3P 1H8"
            },
            "authorId": "user-1",
            "resolvedAt": null,
            "resolvedBy": null,
            "comments": [
                {
                    "commentId": "e949f2f153f07ddc9b5f161062d4a1ad9",
                    "content": "<p>This might be Mr. Lafleur's address. Can we double-check the addresses?</p>",
                    "createdAt": "2023-08-24T09:35:17.338Z",
                    "authorId": "user-1",
                    "attributes": {}
                }
            ],
            "attributes": {}
        },
        {
            "threadId": "e5964fb81e95e0cd712ecf95fafad425f",
            "context": {
            "type": "text",
            "value": "(i)"
            },
            "authorId": "user-1",
            "resolvedAt": null,
            "resolvedBy": null,
            "comments": [
                {
                    "commentId": "edadb356033be84bb93085092e4d8b15b",
                    "content": "<p>Maybe we should change this listing to be consistent with the one from section 2</p>",
                    "createdAt": "2023-08-24T09:37:11.805Z",
                    "authorId": "user-1",
                    "attributes": {}
                }
            ],
            "attributes": {}
        }
    ],
    "suggestionsData": [
        {
            "id": "ea6c5028e3c0efaf0b9a23d227d89696c",
            "type": "deletion",
            "createdAt": "2023-08-24T09:31:40.515Z",
            "hasComments": false,
            "data": null,
            "attributes": {}
        },
        {
            "id": "e513f8e2e4eca79825823ff00294f3716",
            "type": "deletion",
            "createdAt": "2023-08-24T09:32:02.186Z",
            "hasComments": false,
            "data": null,
            "attributes": {}
        },
        {
            "id": "e64910f0cd32232aac1cce1c6b5b565b6",
            "type": "insertion",
            "createdAt": "2023-08-24T09:32:02.186Z",
            "hasComments": false,
            "data": null,
            "attributes": {}
        }
    ],
    "revisionsData": [
        {
            "id": "initial",
            "name": "Empty document",
            "creatorId": "user-1",
            "authorsIds": [],
            "diffData": {
                "main": {
                    "insertions": "[{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]}]",
                    "deletions": "[{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]}]",
                    "attachChange": null,
                    "attributesBefore": {},
                    "attributesAfter": {}
                }
            },
            "createdAt": "2023-08-24T09:28:43.499Z",
            "attributes": {},
            "fromVersion": 2,
            "toVersion": 2
        },
        {
            "id": "ed433b9857b18e2ece0ca0b19a0288ba5",
            "name": "revision-1",
            "creatorId": "user-1",
            "authorsIds": [
            "user-1"
            ],
            "diffData": {
                "main": {
                    "insertions": "[{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[[\"data-revision-start-before\",\"insertion:user-1:0\"],[\"style\",\"text-align:center;\"]],\"children\":[\"NON-DISCLOSURE AGREEMENT (NDA)\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"This Nondisclosure Agreement or (\\\"Agreement\\\") has been entered into on the \",{\"type\":\"u\",\"name\":\"suggestion-start\",\"attributes\":[[\"name\",\"deletion:ea6c5028e3c0efaf0b9a23d227d89696c:user-1\"]],\"children\":[]},\"the \",{\"type\":\"u\",\"name\":\"suggestion-end\",\"attributes\":[[\"name\",\"deletion:ea6c5028e3c0efaf0b9a23d227d89696c:user-1\"]],\"children\":[]},\"date of 10.05.2021 and is by and between:\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Party Disclosing Information:\"]},\" James Lahey with a mailing address of 3 Maple Rd. Spryfield B3P 1H8    (\\\"Disclosing Party\\\").\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Party Receiving Information:\"]},\"    Richard Lafleur with a mailing address of    1 Bonnyville Dr. Spryfield B3P 1H8 (\\\"Receiving Party\\\"). For the purpose of preventing the unauthorized disclosure of Confidential Information as defined below. The parties agree to enter into a confidential relationship concerning the disclosure of certain \",{\"type\":\"u\",\"name\":\"suggestion-start\",\"attributes\":[[\"name\",\"insertion:e64910f0cd32232aac1cce1c6b5b565b6:user-1\"]],\"children\":[]},\"proprietary\",{\"type\":\"u\",\"name\":\"suggestion-end\",\"attributes\":[[\"name\",\"insertion:e64910f0cd32232aac1cce1c6b5b565b6:user-1\"]],\"children\":[]},{\"type\":\"u\",\"name\":\"suggestion-start\",\"attributes\":[[\"name\",\"deletion:e513f8e2e4eca79825823ff00294f3716:user-1\"]],\"children\":[]},\"business\",{\"type\":\"u\",\"name\":\"suggestion-end\",\"attributes\":[[\"name\",\"deletion:e513f8e2e4eca79825823ff00294f3716:user-1\"]],\"children\":[]},\" property and confidential information (\\\"Confidential Information\\\").\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"1. Definition of Confidential Information\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"For purposes of this Agreement, \\\"Confidential Information\\\" shall include all information or material that has or could have commercial value or other utility in the business in which the Disclosing Party is engaged. If Confidential Information is in written form, the Disclosing Party shall label or stamp the materials with the word \\\"Confidential\\\" or some similar warning. If Confidential Information is transmitted orally, the Disclosing Party shall promptly provide a writing indicating that such oral communication constituted Confidential Information.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"2. Exclusions from Confidential Information\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Receiving Party's obligations under this Agreement do not extend to information that is:(a) publicly known at the time of disclosure or subsequently becomes publicly known through no fault of the Receiving Party; (b) discovered or created by the Receiving Party before disclosure by Disclosing Party; (c) learned by the Receiving Party through legitimate means other than from the Disclosing Party or Disclosing Party's representatives; or (d) is disclosed by Receiving Party with Disclosing Party's prior written approval.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"3. Obligations of Receiving Party\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Receiving Party shall hold and maintain the Confidential Information in strictest confidence for the sole and exclusive benefit of the Disclosing Party. Receiving Party shall carefully restrict access to Confidential Information to employees, contractors and third parties as is reasonably required and shall require those persons to sign nondisclosure restrictions at least as protective as those in this Agreement. Receiving Party shall not, without the prior written approval of Disclosing Party, use for Receiving Party's benefit, publish, copy, or otherwise disclose to others, or permit the use by others for their benefit or to the detriment of Disclosing Party, any Confidential Information. Receiving Party shall return to Disclosing Party any and all records, notes, and other written, printed, or tangible materials in its possession pertaining to Confidential Information immediately if Disclosing Party requests it in writing.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"4. Time Periods\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"The nondisclosure provisions of this Agreement shall survive the termination of this Agreement and Receiving Party's duty to hold Confidential Information in confidence shall remain in effect until the Confidential Information no longer qualifies as a trade secret or until Disclosing Party sends Receiving Party written notice releasing Receiving Party from this Agreement, whichever occurs first.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"5. Relationships\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Nothing contained in this Agreement shall be deemed to constitute either party a partner, joint venture or employee of the other party for any purpose.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"6. Severability\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"If a court finds any provision of this Agreement invalid or unenforceable, the remainder of this Agreement shall be interpreted so as best to affect the intent of the parties.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"7. Integration\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"This Agreement expresses the complete understanding of the parties with respect to the subject matter and supersedes all prior proposals, agreements, representations, and understandings. This Agreement may not be amended except in writing signed by both parties.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"8. Waiver\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"The failure to exercise any right provided in this Agreement shall not be a waiver of prior or subsequent rights.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"9. Notice of Immunity\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Employee is provided notice that an individual shall not be held criminally or civilly liable under any federal or state trade secret law for the disclosure of a trade secret that is made (i) in confidence to a federal, state, or local government official, either directly or indirectly, or to an attorney; and (ii) solely for the purpose of reporting or investigating a suspected violation of law; or is made in a complaint or other document filed in a lawsuit or other proceeding, if such filing is made under seal. An individual who files a lawsuit for retaliation by an employer for reporting a suspected violation of law may disclose the trade secret to the attorney of the individual and use the trade secret information in the court proceeding, if the individual (i) files any document containing the trade secret under seal; and (ii) does not disclose the trade secret, except pursuant to court order. This Agreement and each party's obligations shall be binding on the representatives, assigns and successors of such party. Each party has signed this Agreement through its authorized representative.\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"DISCLOSING PARTY Signature:\"]},\" _____________________________________________________\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Typed or Printed Name:\"]},\" James Lahey\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Date:\"]},\" 10.05.2021\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"RECEIVING PARTY Signature:\"]},\" _____________________________________________________\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Typed or Printed Name:\"]},\" Richard Lafleur\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[[\"data-revision-end-after\",\"insertion:user-1:0\"]],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Date:\"]},\" 10.05.2021\"]}]",
                    "deletions": "[{\"type\":\"c\",\"name\":\"p\",\"attributes\":[[\"data-revision-end-after\",\"deletion:user-1:0\"],[\"data-revision-start-before\",\"deletion:user-1:0\"]],\"children\":[]}]",
                    "attachChange": null,
                    "attributesBefore": {},
                    "attributesAfter": {}
                }
            },
            "createdAt": "2023-08-24T09:33:51.568Z",
            "attributes": {},
            "fromVersion": 2,
            "toVersion": 14
        },
        {
            "id": "e6a32e19aceae7a67bb9861a0b887611b",
            "name": "",
            "creatorId": null,
            "authorsIds": [
            "user-1"
            ],
            "diffData": {
                "main": {
                    "insertions": "[{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[[\"style\",\"text-align:center;\"]],\"children\":[\"NON-DISCLOSURE AGREEMENT (NDA)\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"This Nondisclosure Agreement or (\\\"Agreement\\\") has been entered into on the \",{\"type\":\"u\",\"name\":\"suggestion-start\",\"attributes\":[[\"name\",\"deletion:ea6c5028e3c0efaf0b9a23d227d89696c:user-1\"]],\"children\":[]},\"the \",{\"type\":\"u\",\"name\":\"suggestion-end\",\"attributes\":[[\"name\",\"deletion:ea6c5028e3c0efaf0b9a23d227d89696c:user-1\"]],\"children\":[]},\"date of 10.05.2021 and is by and between:\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Party Disclosing Information:\"]},\" James Lahey with a mailing address of \",{\"type\":\"u\",\"name\":\"comment-start\",\"attributes\":[[\"name\",\"eca0c3e71883a578ee37bdc0e510a41a8:49cf1\"]],\"children\":[]},\"3 Maple Rd. Spryfield B3P 1H8\",{\"type\":\"u\",\"name\":\"comment-end\",\"attributes\":[[\"name\",\"eca0c3e71883a578ee37bdc0e510a41a8:49cf1\"]],\"children\":[]},\"    (\\\"Disclosing Party\\\").\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Party Receiving Information:\"]},\"    Richard Lafleur with a mailing address of    1 Bonnyville Dr. Spryfield B3P 1H8 (\\\"Receiving Party\\\"). For the purpose of preventing the unauthorized disclosure of Confidential Information as defined below. The parties agree to enter into a confidential relationship concerning the disclosure of certain \",{\"type\":\"u\",\"name\":\"suggestion-start\",\"attributes\":[[\"name\",\"insertion:e64910f0cd32232aac1cce1c6b5b565b6:user-1\"]],\"children\":[]},\"proprietary\",{\"type\":\"u\",\"name\":\"suggestion-end\",\"attributes\":[[\"name\",\"insertion:e64910f0cd32232aac1cce1c6b5b565b6:user-1\"]],\"children\":[]},{\"type\":\"u\",\"name\":\"suggestion-start\",\"attributes\":[[\"name\",\"deletion:e513f8e2e4eca79825823ff00294f3716:user-1\"]],\"children\":[]},\"business\",{\"type\":\"u\",\"name\":\"suggestion-end\",\"attributes\":[[\"name\",\"deletion:e513f8e2e4eca79825823ff00294f3716:user-1\"]],\"children\":[]},\" property and confidential information (\\\"Confidential Information\\\").\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"1. Definition of Confidential Information\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"For purposes of this Agreement, \\\"Confidential Information\\\" shall include all information or material that has or could have commercial value or other utility in the business in which the Disclosing Party is engaged. If Confidential Information is in written form, the Disclosing Party shall label or stamp the materials with the word \\\"Confidential\\\" or some similar warning. If Confidential Information is transmitted orally, the Disclosing Party shall promptly provide a writing indicating that such oral communication constituted Confidential Information.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"2. Exclusions from Confidential Information\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Receiving Party's obligations under this Agreement do not extend to information that is:(a) publicly known at the time of disclosure or subsequently becomes publicly known through no fault of the Receiving Party; (b) discovered or created by the Receiving Party before disclosure by Disclosing Party; (c) learned by the Receiving Party through legitimate means other than from the Disclosing Party or Disclosing Party's representatives; or (d) is disclosed by Receiving Party with Disclosing Party's prior written approval.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"3. Obligations of Receiving Party\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Receiving Party shall hold and maintain the Confidential Information in strictest confidence for the sole and exclusive benefit of the Disclosing Party. Receiving Party shall carefully restrict access to Confidential Information to employees, contractors and third parties as is reasonably required and shall require those persons to sign nondisclosure restrictions at least as protective as those in this Agreement. Receiving Party shall not, without the prior written approval of Disclosing Party, use for Receiving Party's benefit, publish, copy, or otherwise disclose to others, or permit the use by others for their benefit or to the detriment of Disclosing Party, any Confidential Information. Receiving Party shall return to Disclosing Party any and all records, notes, and other written, printed, or tangible materials in its possession pertaining to Confidential Information immediately if Disclosing Party requests it in writing.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"4. Time Periods\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"The nondisclosure provisions of this Agreement shall survive the termination of this Agreement and Receiving Party's duty to hold Confidential Information in confidence shall remain in effect until the Confidential Information no longer qualifies as a trade secret or until Disclosing Party sends Receiving Party written notice releasing Receiving Party from this Agreement, whichever occurs first.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"5. Relationships\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Nothing contained in this Agreement shall be deemed to constitute either party a partner, joint venture or employee of the other party for any purpose.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"6. Severability\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"If a court finds any provision of this Agreement invalid or unenforceable, the remainder of this Agreement shall be interpreted so as best to affect the intent of the parties.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"7. Integration\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"This Agreement expresses the complete understanding of the parties with respect to the subject matter and supersedes all prior proposals, agreements, representations, and understandings. This Agreement may not be amended except in writing signed by both parties.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"8. Waiver\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"The failure to exercise any right provided in this Agreement shall not be a waiver of prior or subsequent rights.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"9. Notice of Immunity\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Employee is provided notice that an individual shall not be held criminally or civilly liable under any federal or state trade secret law for the disclosure of a trade secret that is made \",{\"type\":\"u\",\"name\":\"comment-start\",\"attributes\":[[\"name\",\"e5964fb81e95e0cd712ecf95fafad425f:57cf0\"]],\"children\":[]},\"(i)\",{\"type\":\"u\",\"name\":\"comment-end\",\"attributes\":[[\"name\",\"e5964fb81e95e0cd712ecf95fafad425f:57cf0\"]],\"children\":[]},\" in confidence to a federal, state, or local government official, either directly or indirectly, or to an attorney; and (ii) solely for the purpose of reporting or investigating a suspected violation of law; or is made in a complaint or other document filed in a lawsuit or other proceeding, if such filing is made under seal. An individual who files a lawsuit for retaliation by an employer for reporting a suspected violation of law may disclose the trade secret to the attorney of the individual and use the trade secret information in the court proceeding, if the individual (i) files any document containing the trade secret under seal; and (ii) does not disclose the trade secret, except pursuant to court order. This Agreement and each party's obligations shall be binding on the representatives, assigns and successors of such party. Each party has signed this Agreement through its authorized representative.\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"DISCLOSING PARTY Signature:\"]},\" _____________________________________________________\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Typed or Printed Name:\"]},\" James Lahey\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Date:\"]},\" 10.05.2021\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"RECEIVING PARTY Signature:\"]},\" _____________________________________________________\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Typed or Printed Name:\"]},\" Richard Lafleur\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Date:\"]},\" 10.05.2021\"]}]",
                    "deletions": "[{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[[\"style\",\"text-align:center;\"]],\"children\":[\"NON-DISCLOSURE AGREEMENT (NDA)\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"This Nondisclosure Agreement or (\\\"Agreement\\\") has been entered into on the \",{\"type\":\"u\",\"name\":\"suggestion-start\",\"attributes\":[[\"name\",\"deletion:ea6c5028e3c0efaf0b9a23d227d89696c:user-1\"]],\"children\":[]},\"the \",{\"type\":\"u\",\"name\":\"suggestion-end\",\"attributes\":[[\"name\",\"deletion:ea6c5028e3c0efaf0b9a23d227d89696c:user-1\"]],\"children\":[]},\"date of 10.05.2021 and is by and between:\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Party Disclosing Information:\"]},\" James Lahey with a mailing address of 3 Maple Rd. Spryfield B3P 1H8    (\\\"Disclosing Party\\\").\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Party Receiving Information:\"]},\"    Richard Lafleur with a mailing address of    1 Bonnyville Dr. Spryfield B3P 1H8 (\\\"Receiving Party\\\"). For the purpose of preventing the unauthorized disclosure of Confidential Information as defined below. The parties agree to enter into a confidential relationship concerning the disclosure of certain \",{\"type\":\"u\",\"name\":\"suggestion-start\",\"attributes\":[[\"name\",\"insertion:e64910f0cd32232aac1cce1c6b5b565b6:user-1\"]],\"children\":[]},\"proprietary\",{\"type\":\"u\",\"name\":\"suggestion-end\",\"attributes\":[[\"name\",\"insertion:e64910f0cd32232aac1cce1c6b5b565b6:user-1\"]],\"children\":[]},{\"type\":\"u\",\"name\":\"suggestion-start\",\"attributes\":[[\"name\",\"deletion:e513f8e2e4eca79825823ff00294f3716:user-1\"]],\"children\":[]},\"business\",{\"type\":\"u\",\"name\":\"suggestion-end\",\"attributes\":[[\"name\",\"deletion:e513f8e2e4eca79825823ff00294f3716:user-1\"]],\"children\":[]},\" property and confidential information (\\\"Confidential Information\\\").\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"1. Definition of Confidential Information\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"For purposes of this Agreement, \\\"Confidential Information\\\" shall include all information or material that has or could have commercial value or other utility in the business in which the Disclosing Party is engaged. If Confidential Information is in written form, the Disclosing Party shall label or stamp the materials with the word \\\"Confidential\\\" or some similar warning. If Confidential Information is transmitted orally, the Disclosing Party shall promptly provide a writing indicating that such oral communication constituted Confidential Information.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"2. Exclusions from Confidential Information\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Receiving Party's obligations under this Agreement do not extend to information that is:(a) publicly known at the time of disclosure or subsequently becomes publicly known through no fault of the Receiving Party; (b) discovered or created by the Receiving Party before disclosure by Disclosing Party; (c) learned by the Receiving Party through legitimate means other than from the Disclosing Party or Disclosing Party's representatives; or (d) is disclosed by Receiving Party with Disclosing Party's prior written approval.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"3. Obligations of Receiving Party\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Receiving Party shall hold and maintain the Confidential Information in strictest confidence for the sole and exclusive benefit of the Disclosing Party. Receiving Party shall carefully restrict access to Confidential Information to employees, contractors and third parties as is reasonably required and shall require those persons to sign nondisclosure restrictions at least as protective as those in this Agreement. Receiving Party shall not, without the prior written approval of Disclosing Party, use for Receiving Party's benefit, publish, copy, or otherwise disclose to others, or permit the use by others for their benefit or to the detriment of Disclosing Party, any Confidential Information. Receiving Party shall return to Disclosing Party any and all records, notes, and other written, printed, or tangible materials in its possession pertaining to Confidential Information immediately if Disclosing Party requests it in writing.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"4. Time Periods\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"The nondisclosure provisions of this Agreement shall survive the termination of this Agreement and Receiving Party's duty to hold Confidential Information in confidence shall remain in effect until the Confidential Information no longer qualifies as a trade secret or until Disclosing Party sends Receiving Party written notice releasing Receiving Party from this Agreement, whichever occurs first.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"5. Relationships\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Nothing contained in this Agreement shall be deemed to constitute either party a partner, joint venture or employee of the other party for any purpose.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"6. Severability\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"If a court finds any provision of this Agreement invalid or unenforceable, the remainder of this Agreement shall be interpreted so as best to affect the intent of the parties.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"7. Integration\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"This Agreement expresses the complete understanding of the parties with respect to the subject matter and supersedes all prior proposals, agreements, representations, and understandings. This Agreement may not be amended except in writing signed by both parties.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"8. Waiver\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"The failure to exercise any right provided in this Agreement shall not be a waiver of prior or subsequent rights.\"]},{\"type\":\"c\",\"name\":\"h2\",\"attributes\":[],\"children\":[\"9. Notice of Immunity\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[\"Employee is provided notice that an individual shall not be held criminally or civilly liable under any federal or state trade secret law for the disclosure of a trade secret that is made (i) in confidence to a federal, state, or local government official, either directly or indirectly, or to an attorney; and (ii) solely for the purpose of reporting or investigating a suspected violation of law; or is made in a complaint or other document filed in a lawsuit or other proceeding, if such filing is made under seal. An individual who files a lawsuit for retaliation by an employer for reporting a suspected violation of law may disclose the trade secret to the attorney of the individual and use the trade secret information in the court proceeding, if the individual (i) files any document containing the trade secret under seal; and (ii) does not disclose the trade secret, except pursuant to court order. This Agreement and each party's obligations shall be binding on the representatives, assigns and successors of such party. Each party has signed this Agreement through its authorized representative.\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"DISCLOSING PARTY Signature:\"]},\" _____________________________________________________\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Typed or Printed Name:\"]},\" James Lahey\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Date:\"]},\" 10.05.2021\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"RECEIVING PARTY Signature:\"]},\" _____________________________________________________\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Typed or Printed Name:\"]},\" Richard Lafleur\"]},{\"type\":\"c\",\"name\":\"p\",\"attributes\":[],\"children\":[{\"type\":\"a\",\"name\":\"strong\",\"attributes\":[],\"children\":[\"Date:\"]},\" 10.05.2021\"]}]",
                    "attachChange": null,
                    "attributesBefore": {},
                    "attributesAfter": {}
                }
            },
            "createdAt": "2023-08-24T09:37:39.710Z",
            "attributes": {},
            "fromVersion": 14,
            "toVersion": 16
        }
    ]
}

try {
    const response = await fetch( 'https://127.0.0.1:8000/import-document', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify( {
            documentData,
            suggestionAuthorId: 'user-1'
        } )
    } );

    const data = await response.json();

    console.log( 'Result of importing the document:', data );
} catch ( error ) {
    console.log( 'Error occurred during importing the document:', error );
}