main

mattermost/focalboard

Last updated at: 29/12/2023 09:38

archive.ts

TLDR

This file archive.ts contains a class ArchiveUtils with two static methods: buildBlockArchive and parseBlockArchive. These methods are used to build and parse archive files respectively. The archive files contain boards and blocks data in JSON format.

Methods

buildBlockArchive

This method takes two parameters, boards and blocks, which are arrays of Board and Block objects respectively. It constructs an archive file by serializing the boards and blocks data into JSON strings and concatenating them with a header. The header contains the version number and the current timestamp. The method then returns the content of the archive file.

parseBlockArchive

This method takes a contents parameter, which is the content of an archive file. It parses the archive file by splitting the content into lines and extracting the header information. The method then iterates through the lines, parses each line as a JSON object, and appends the block data to an array. Finally, it returns the array of Block objects extracted from the archive file.

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Block} from '../../webapp/src/blocks/block'
import {Board} from '../../webapp/src/blocks/board'

interface ArchiveHeader {
    version: number
    date: number
}

// This schema allows the expansion of additional line types in the future
interface ArchiveLine {
    type: string,
    data: unknown,
}

interface BlockArchiveLine extends ArchiveLine {
    type: 'block',
    data: Block
}

interface BoardArchiveLine extends ArchiveLine {
    type: 'board',
    data: Board
}

class ArchiveUtils {
    static buildBlockArchive(boards: readonly Board[], blocks: readonly Block[]): string {
        const header: ArchiveHeader = {
            version: 1,
            date: Date.now(),
        }

        const headerString = JSON.stringify(header)
        let content = headerString + '\n'

        for (const board of boards) {
            const line: BoardArchiveLine = {
                type: 'board',
                data: board,
            }
            const lineString = JSON.stringify(line)
            content += lineString
            content += '\n'
        }

        for (const block of blocks) {
            const line: BlockArchiveLine = {
                type: 'block',
                data: block,
            }
            const lineString = JSON.stringify(line)
            content += lineString
            content += '\n'
        }

        return content
    }

    static parseBlockArchive(contents: string): Block[] {
        const blocks: Block[] = []
        const allLineStrings = contents.split('\n')
        if (allLineStrings.length >= 2) {
            const headerString = allLineStrings[0]
            const header = JSON.parse(headerString) as ArchiveHeader
            if (header.date && header.version >= 1) {
                const lineStrings = allLineStrings.slice(1)
                let lineNum = 2
                for (const lineString of lineStrings) {
                    if (!lineString) {
                        // Ignore empty lines, e.g. last line
                        continue
                    }
                    const line = JSON.parse(lineString) as ArchiveLine
                    if (!line || !line.type || !line.data) {
                        throw new Error(`ERROR parsing line ${lineNum}`)
                    }
                    switch (line.type) {
                    case 'block': {
                        const blockLine = line as BlockArchiveLine
                        const block = blockLine.data
                        blocks.push(block)
                        break
                    }
                    }

                    lineNum += 1
                }
            } else {
                throw new Error('ERROR parsing header')
            }
        }

        return blocks
    }
}

export {ArchiveHeader, ArchiveLine, BlockArchiveLine, ArchiveUtils}