aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/shared/model-builder.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/models/shared/model-builder.ts')
-rw-r--r--server/models/shared/model-builder.ts101
1 files changed, 101 insertions, 0 deletions
diff --git a/server/models/shared/model-builder.ts b/server/models/shared/model-builder.ts
new file mode 100644
index 000000000..c015ca4f5
--- /dev/null
+++ b/server/models/shared/model-builder.ts
@@ -0,0 +1,101 @@
1import { isPlainObject } from 'lodash'
2import { Model as SequelizeModel, Sequelize } from 'sequelize'
3import { logger } from '@server/helpers/logger'
4
5export class ModelBuilder <T extends SequelizeModel> {
6 private readonly modelRegistry = new Map<string, T>()
7
8 constructor (private readonly sequelize: Sequelize) {
9
10 }
11
12 createModels (jsonArray: any[], baseModelName: string): T[] {
13 const result: T[] = []
14
15 for (const json of jsonArray) {
16 const { created, model } = this.createModel(json, baseModelName, json.id + '.' + baseModelName)
17
18 if (created) result.push(model)
19 }
20
21 return result
22 }
23
24 private createModel (json: any, modelName: string, keyPath: string) {
25 if (!json.id) return { created: false, model: null }
26
27 const { created, model } = this.createOrFindModel(json, modelName, keyPath)
28
29 for (const key of Object.keys(json)) {
30 const value = json[key]
31 if (!value) continue
32
33 // Child model
34 if (isPlainObject(value)) {
35 const { created, model: subModel } = this.createModel(value, key, keyPath + '.' + json.id + '.' + key)
36 if (!created || !subModel) continue
37
38 const Model = this.findModelBuilder(modelName)
39 const association = Model.associations[key]
40
41 if (!association) {
42 logger.error('Cannot find association %s of model %s', key, modelName, { associations: Object.keys(Model.associations) })
43 continue
44 }
45
46 if (association.isMultiAssociation) {
47 if (!Array.isArray(model[key])) model[key] = []
48
49 model[key].push(subModel)
50 } else {
51 model[key] = subModel
52 }
53 }
54 }
55
56 return { created, model }
57 }
58
59 private createOrFindModel (json: any, modelName: string, keyPath: string) {
60 const registryKey = this.getModelRegistryKey(json, keyPath)
61 if (this.modelRegistry.has(registryKey)) {
62 return {
63 created: false,
64 model: this.modelRegistry.get(registryKey)
65 }
66 }
67
68 const Model = this.findModelBuilder(modelName)
69
70 if (!Model) {
71 logger.error(
72 'Cannot build model %s that does not exist', this.buildSequelizeModelName(modelName),
73 { existing: this.sequelize.modelManager.all.map(m => m.name) }
74 )
75 return undefined
76 }
77
78 // FIXME: typings
79 const model = new (Model as any)(json)
80 this.modelRegistry.set(registryKey, model)
81
82 return { created: true, model }
83 }
84
85 private findModelBuilder (modelName: string) {
86 return this.sequelize.modelManager.getModel(this.buildSequelizeModelName(modelName))
87 }
88
89 private buildSequelizeModelName (modelName: string) {
90 if (modelName === 'Avatars') return 'ActorImageModel'
91 if (modelName === 'ActorFollowing') return 'ActorModel'
92 if (modelName === 'ActorFollower') return 'ActorModel'
93 if (modelName === 'FlaggedAccount') return 'AccountModel'
94
95 return modelName + 'Model'
96 }
97
98 private getModelRegistryKey (json: any, keyPath: string) {
99 return keyPath + json.id
100 }
101}