models.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. const ObjectID = require("mongodb").ObjectID;
  2. const {connect} = require('mm')
  3. module.exports = async (dbName='hipstagram') => {
  4. const {Savable, slice} = await connect(dbName)
  5. async function getModels({id}){
  6. const SlicedSavable = slice([id, 'user'])
  7. class User extends SlicedSavable {
  8. constructor(...params){
  9. super(...params)
  10. //TODO: calc likes count by getter (no two-way relation for this to avoid overflow on many Kilos of likes
  11. //cached like count, which incremented and decremented
  12. //
  13. //following and followers array
  14. }
  15. static get relations(){ //don't needed due to ___owner in most cases
  16. return {
  17. avatar : "userAvatar",
  18. incomings: "to",
  19. followers: ["following"],
  20. following: ["followers"],
  21. }
  22. }
  23. static get guestRelations(){
  24. return ["followers"]
  25. }
  26. }
  27. SlicedSavable.addClass(User)
  28. class OwnerSlicedSavable extends SlicedSavable {
  29. get owner(){
  30. if (!this.___owner) return this.___owner
  31. return SlicedSavable.m.User.findOne({_id: ObjectID(this.___owner)})
  32. }
  33. }
  34. class Like extends OwnerSlicedSavable {
  35. constructor(...params){
  36. super(...params)
  37. //TODO:
  38. //entity
  39. //entityLikesCount?
  40. }
  41. static get relations(){
  42. return {
  43. }
  44. }
  45. static get defaultPermissions(){
  46. return {
  47. //savable refs, objectid's, words like 'tags' or 'roles'
  48. read: ['owner', 'user'],
  49. write: ['owner'],
  50. create: ['user'],
  51. delete: ['owner'],
  52. /*permission
  53. * TODO: permissions for read and write permissions
  54. *
  55. */
  56. }
  57. }
  58. }
  59. SlicedSavable.addClass(Like)
  60. class Post extends OwnerSlicedSavable {
  61. constructor(...params){
  62. super(...params)
  63. //TODO: calc likes count by getter (no two-way relation for this to avoid overflow on many Kilos of likes
  64. //cached like count, which incremented and decremented
  65. //
  66. }
  67. get likes(){
  68. return (async () => {
  69. let result = []
  70. for (let like of SlicedSavable.m.Like.find({'post._id': this._id}, {limit: [100], sort: ['_id', 1]})){
  71. try {await like; result.push(like) } catch(e) {}
  72. }
  73. return result;
  74. })()
  75. }
  76. static get relations(){
  77. return {
  78. images: ["posts"],
  79. comments: "post",
  80. directs: "post",
  81. collections: ["posts"]
  82. }
  83. }
  84. static get guestRelations(){
  85. return ["comments", "directs"]
  86. }
  87. static get defaultPermissions(){
  88. return {
  89. //savable refs, objectid's, words like 'tags' or 'roles'
  90. read: ['owner', 'user'],
  91. write: ['owner'],
  92. create: ['user'],
  93. delete: ['owner', 'admin'],
  94. /*permission
  95. * TODO: permissions for read and write permissions
  96. *
  97. */
  98. }
  99. }
  100. }
  101. SlicedSavable.addClass(Post)
  102. class Image extends OwnerSlicedSavable {
  103. constructor(...params){
  104. super(...params)
  105. }
  106. static async fromFileData(fileData){
  107. let image = new Image({})
  108. image.fileData = fileData
  109. image.url = `images/${fileData.filename}`
  110. image.originalFileName = fileData.originalname
  111. await image.save()
  112. return image;
  113. }
  114. async save(...params){
  115. if (this.userAvatar){
  116. if (this.userAvatar._id.toString() !== id){
  117. throw new ReferenceError(`You can't set ava for other user`)
  118. }
  119. }
  120. return await super.save(...params)
  121. }
  122. static get relations(){
  123. return {
  124. userAvatar: "avatar", //if it is ava
  125. posts: ["images"], //if in post: m2m with posts
  126. directs: "image", //if in direct: m2o with directs
  127. }
  128. }
  129. }
  130. SlicedSavable.addClass(Image)
  131. class Comment extends OwnerSlicedSavable {
  132. constructor(...params){
  133. super(...params)
  134. //TODO: calc likes count by getter (no two-way relation for this to avoid overflow on many Kilos of likes
  135. //cached like count, which incremented and decremented
  136. }
  137. static get relations(){
  138. return {
  139. post: ["comments"],
  140. answers: "answerTo",
  141. answerTo: ["answers"],
  142. }
  143. }
  144. static get guestRelations(){
  145. return ["answers"]
  146. }
  147. }
  148. SlicedSavable.addClass(Comment)
  149. class Direct extends OwnerSlicedSavable {
  150. constructor(...params){
  151. super(...params)
  152. }
  153. static get relations(){
  154. return {
  155. to: ["incomings"],
  156. image: ["directs"],
  157. likes: "entity",
  158. }
  159. }
  160. static get guestRelations(){
  161. return ["to", "likes"]
  162. }
  163. }
  164. SlicedSavable.addClass(Direct)
  165. class Collection extends OwnerSlicedSavable {
  166. constructor(...params){
  167. super(...params)
  168. }
  169. static get relations(){
  170. return {
  171. posts: "collections"
  172. }
  173. }
  174. }
  175. SlicedSavable.addClass(Collection)
  176. const thisUser = await Savable.m.User.findOne({_id: ObjectID(id)})
  177. return {models: {
  178. SlicedSavable, ...SlicedSavable.classes
  179. },
  180. thisUser}
  181. }
  182. return {
  183. Savable,
  184. slice,
  185. getModels
  186. }
  187. }