Write migration script to fix up old contract/post/comment text
This commit is contained in:
parent
5cda037f6b
commit
99978118a5
113
functions/src/scripts/migrate-rich-text.ts
Normal file
113
functions/src/scripts/migrate-rich-text.ts
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
// We have three kinds of rich text:
|
||||||
|
// - Contract descriptions.
|
||||||
|
// - Comment text.
|
||||||
|
// - Post contents.
|
||||||
|
// These are stored in two different ways:
|
||||||
|
// - As plaintext strings.
|
||||||
|
// - As structured ProseMirror JSON in Firestore.
|
||||||
|
// We want to make all of these into:
|
||||||
|
// - Strings containing serialized ProseMirror JSON.
|
||||||
|
|
||||||
|
import * as admin from 'firebase-admin'
|
||||||
|
import { FieldValue } from 'firebase-admin/firestore'
|
||||||
|
import { initAdmin } from './script-init'
|
||||||
|
import { log, writeAsync } from '../utils'
|
||||||
|
import { filterDefined } from '../../../common/util/array'
|
||||||
|
import { plainTextToProseMirror } from '../../../common/util/parse'
|
||||||
|
|
||||||
|
initAdmin()
|
||||||
|
const firestore = admin.firestore()
|
||||||
|
|
||||||
|
const isValidJSON = (s: string) => {
|
||||||
|
try {
|
||||||
|
JSON.parse(s)
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const migrateContractDescriptions = async () => {
|
||||||
|
const contractQ = await firestore.collection('contracts').get()
|
||||||
|
console.log(`Loaded ${contractQ.size} contracts.`)
|
||||||
|
const updates = filterDefined(
|
||||||
|
contractQ.docs.map((doc) => {
|
||||||
|
const fields: { [k: string]: unknown } = {}
|
||||||
|
const oldDescription = doc.get('description')
|
||||||
|
if (typeof oldDescription === 'string') {
|
||||||
|
if (isValidJSON(oldDescription)) {
|
||||||
|
// this one is already good
|
||||||
|
return null
|
||||||
|
} else {
|
||||||
|
fields.description = JSON.stringify(
|
||||||
|
plainTextToProseMirror(oldDescription)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if (oldDescription != null) {
|
||||||
|
// already JSON, just need to serialize into string
|
||||||
|
fields.description = JSON.stringify(oldDescription)
|
||||||
|
} else {
|
||||||
|
throw new Error('Content had null description for some reason.')
|
||||||
|
}
|
||||||
|
return { doc: doc.ref, fields }
|
||||||
|
})
|
||||||
|
)
|
||||||
|
log(`Found ${updates.length} contracts with old format descriptions.`)
|
||||||
|
await writeAsync(firestore, updates)
|
||||||
|
}
|
||||||
|
|
||||||
|
const migrateCommentContents = async () => {
|
||||||
|
const commentQ = await firestore.collectionGroup('comments').get()
|
||||||
|
console.log(`Loaded ${commentQ.size} comments.`)
|
||||||
|
const updates = filterDefined(
|
||||||
|
commentQ.docs.map((doc) => {
|
||||||
|
const fields: { [k: string]: unknown } = {}
|
||||||
|
const oldText = doc.get('text')
|
||||||
|
const oldContent = doc.get('content')
|
||||||
|
if (typeof oldContent === 'string') {
|
||||||
|
// this one is already good
|
||||||
|
return null
|
||||||
|
} else if (oldContent != null) {
|
||||||
|
// already JSON, just need to serialize into string
|
||||||
|
fields.content = JSON.stringify(oldContent)
|
||||||
|
} else if (oldText != null) {
|
||||||
|
fields.text = FieldValue.delete()
|
||||||
|
fields.content = JSON.stringify(plainTextToProseMirror(oldText))
|
||||||
|
} else {
|
||||||
|
throw new Error('Comment mysteriously had neither text nor content.')
|
||||||
|
}
|
||||||
|
return { doc: doc.ref, fields }
|
||||||
|
})
|
||||||
|
)
|
||||||
|
log(`Found ${updates.length} comments with old format content.`)
|
||||||
|
await writeAsync(firestore, updates)
|
||||||
|
}
|
||||||
|
|
||||||
|
const migratePostContents = async () => {
|
||||||
|
const postQ = await firestore.collection('posts').get()
|
||||||
|
console.log(`Loaded ${postQ.size} posts.`)
|
||||||
|
const updates = filterDefined(
|
||||||
|
postQ.docs.map((doc) => {
|
||||||
|
const fields: { [k: string]: unknown } = {}
|
||||||
|
const oldContent = doc.get('content')
|
||||||
|
if (typeof oldContent === 'string') {
|
||||||
|
// this one is already good
|
||||||
|
return null
|
||||||
|
} else if (oldContent != null) {
|
||||||
|
// already JSON, just need to serialize into string
|
||||||
|
fields.content = JSON.stringify(oldContent)
|
||||||
|
} else {
|
||||||
|
throw new Error('Post had null content for some reason.')
|
||||||
|
}
|
||||||
|
return { doc: doc.ref, fields }
|
||||||
|
})
|
||||||
|
)
|
||||||
|
log(`Found ${updates.length} posts with old format content.`)
|
||||||
|
await writeAsync(firestore, updates)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
migrateContractDescriptions()
|
||||||
|
migrateCommentContents()
|
||||||
|
migratePostContents()
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user