refactor(dev-only): import tools (#2121)
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import { WebApplicationInterface } from '@standardnotes/services'
|
||||
import { SimplenoteConverter } from './SimplenoteConverter'
|
||||
import data from './testData'
|
||||
|
||||
describe('SimplenoteConverter', () => {
|
||||
let application: WebApplicationInterface
|
||||
|
||||
beforeEach(() => {
|
||||
application = {
|
||||
generateUUID: jest.fn().mockReturnValue('uuid'),
|
||||
} as any
|
||||
})
|
||||
|
||||
it('should parse', () => {
|
||||
const converter = new SimplenoteConverter(application)
|
||||
|
||||
const result = converter.parse(data)
|
||||
|
||||
expect(result).not.toBeNull()
|
||||
expect(result?.length).toBe(3)
|
||||
|
||||
expect(result?.[0].created_at).toBeInstanceOf(Date)
|
||||
expect(result?.[0].updated_at).toBeInstanceOf(Date)
|
||||
expect(result?.[0].uuid).not.toBeNull()
|
||||
expect(result?.[0].content_type).toBe('Note')
|
||||
expect(result?.[0].content.title).toBe('Testing 1')
|
||||
expect(result?.[0].content.text).toBe("This is the 1st note's content.")
|
||||
expect(result?.[0].content.trashed).toBe(false)
|
||||
|
||||
expect(result?.[1].created_at).toBeInstanceOf(Date)
|
||||
expect(result?.[1].updated_at).toBeInstanceOf(Date)
|
||||
expect(result?.[1].uuid).not.toBeNull()
|
||||
expect(result?.[1].content_type).toBe('Note')
|
||||
expect(result?.[1].content.title).toBe('Testing 2')
|
||||
expect(result?.[1].content.text).toBe("This is the 2nd note's content.")
|
||||
expect(result?.[1].content.trashed).toBe(false)
|
||||
|
||||
expect(result?.[2].created_at).toBeInstanceOf(Date)
|
||||
expect(result?.[2].updated_at).toBeInstanceOf(Date)
|
||||
expect(result?.[2].uuid).not.toBeNull()
|
||||
expect(result?.[2].content_type).toBe('Note')
|
||||
expect(result?.[2].content.title).not.toBeFalsy()
|
||||
expect(result?.[2].content.text).toBe('Welcome to Simplenote!')
|
||||
expect(result?.[2].content.trashed).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,78 @@
|
||||
import { DecryptedTransferPayload, NoteContent } from '@standardnotes/models'
|
||||
import { ContentType } from '@standardnotes/common'
|
||||
import { readFileAsText } from '../Utils'
|
||||
import { WebApplicationInterface } from '@standardnotes/services'
|
||||
import { Importer } from '../Importer'
|
||||
|
||||
type SimplenoteItem = {
|
||||
creationDate: string
|
||||
lastModified: string
|
||||
content: string
|
||||
}
|
||||
|
||||
type SimplenoteData = {
|
||||
activeNotes: SimplenoteItem[]
|
||||
trashedNotes: SimplenoteItem[]
|
||||
}
|
||||
|
||||
export class SimplenoteConverter extends Importer {
|
||||
constructor(protected override application: WebApplicationInterface) {
|
||||
super(application)
|
||||
}
|
||||
|
||||
createNoteFromItem(item: SimplenoteItem, trashed: boolean): DecryptedTransferPayload<NoteContent> {
|
||||
const createdAtDate = new Date(item.creationDate)
|
||||
const updatedAtDate = new Date(item.lastModified)
|
||||
|
||||
const splitItemContent = item.content.split('\r\n')
|
||||
const hasTitleAndContent = splitItemContent.length === 2
|
||||
const title =
|
||||
hasTitleAndContent && splitItemContent[0].length ? splitItemContent[0] : createdAtDate.toLocaleString()
|
||||
const content = hasTitleAndContent && splitItemContent[1].length ? splitItemContent[1] : item.content
|
||||
|
||||
return {
|
||||
created_at: createdAtDate,
|
||||
created_at_timestamp: createdAtDate.getTime(),
|
||||
updated_at: updatedAtDate,
|
||||
updated_at_timestamp: updatedAtDate.getTime(),
|
||||
uuid: this.application.generateUUID(),
|
||||
content_type: ContentType.Note,
|
||||
content: {
|
||||
title,
|
||||
text: content,
|
||||
references: [],
|
||||
trashed,
|
||||
appData: {
|
||||
'org.standardnotes.sn': {
|
||||
client_updated_at: updatedAtDate,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async convertSimplenoteBackupFileToNotes(file: File): Promise<DecryptedTransferPayload<NoteContent>[]> {
|
||||
const content = await readFileAsText(file)
|
||||
|
||||
const notes = this.parse(content)
|
||||
|
||||
if (!notes) {
|
||||
throw new Error('Could not parse notes')
|
||||
}
|
||||
|
||||
return notes
|
||||
}
|
||||
|
||||
parse(data: string) {
|
||||
try {
|
||||
const parsed = JSON.parse(data) as SimplenoteData
|
||||
const activeNotes = parsed.activeNotes.reverse().map((item) => this.createNoteFromItem(item, false))
|
||||
const trashedNotes = parsed.trashedNotes.reverse().map((item) => this.createNoteFromItem(item, true))
|
||||
|
||||
return [...activeNotes, ...trashedNotes]
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
const data = {
|
||||
activeNotes: [
|
||||
{
|
||||
id: '43349052-4efa-48c2-bdd6-8323124451b1',
|
||||
content: "Testing 2\r\nThis is the 2nd note's content.",
|
||||
creationDate: '2020-06-08T21:28:43.856Z',
|
||||
lastModified: '2021-04-16T06:21:53.124Z',
|
||||
},
|
||||
{
|
||||
id: '2a338440-4a24-4180-9805-1110d325642c',
|
||||
content: "Testing 1\r\nThis is the 1st note's content.",
|
||||
creationDate: '2020-06-08T21:28:38.241Z',
|
||||
lastModified: '2021-04-16T06:21:58.294Z',
|
||||
},
|
||||
],
|
||||
trashedNotes: [
|
||||
{
|
||||
id: 'agtzaW1wbGUtbm90ZXIRCxIETm90ZRiAgLCvy-3gCAw',
|
||||
content: 'Welcome to Simplenote!',
|
||||
creationDate: '2020-06-08T21:28:28.434Z',
|
||||
lastModified: '2021-04-16T06:20:14.143Z',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default JSON.stringify(data, null, 2)
|
||||
Reference in New Issue
Block a user