@nlabs/metropolisjs 0.1.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/.github/copilot-instructions.md +167 -0
  2. package/AGENTS.md +13 -0
  3. package/CHANGELOG.md +112 -0
  4. package/GRAPHQL_VALIDATION_RESULTS.md +158 -0
  5. package/PERMISSION_GRAPHQL_INTEGRATION.md +293 -0
  6. package/PERMISSION_IMPLEMENTATION_SUMMARY.md +243 -0
  7. package/README.md +1123 -112
  8. package/SIGNIN_GRAPHQL_VALIDATION.md +125 -0
  9. package/VAULT_GRAPHQL_API_FINDINGS.md +312 -0
  10. package/docs/ACTIONS.md +63 -0
  11. package/docs/COLLECTIONS.md +1038 -0
  12. package/docs/CONNECTIONS.md +1367 -0
  13. package/docs/CRUD_INTEGRATION.md +702 -0
  14. package/examples/connections-usage.tsx +909 -0
  15. package/examples/content-actions-usage.ts +144 -0
  16. package/examples/crud-usage.tsx +847 -0
  17. package/examples/extensibility-usage.tsx +889 -0
  18. package/examples/i18n-import-examples.ts +86 -0
  19. package/examples/i18n-namespace-usage.ts +118 -0
  20. package/examples/i18next-singleton-demo.ts +187 -0
  21. package/examples/permission-system-usage.tsx +415 -0
  22. package/examples/project-details.tsx +397 -0
  23. package/examples/shared-i18n-usage.tsx +203 -0
  24. package/examples/signup-error-handling.ts +100 -0
  25. package/examples/translation-types.ts +86 -0
  26. package/examples/translation-usage.tsx +336 -0
  27. package/index.js +1 -0
  28. package/jest.config.mjs +28 -0
  29. package/lex.config.mjs +11 -2
  30. package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts +22 -0
  31. package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts.map +1 -0
  32. package/lib/__tests__/e2e/helpers/testGraphQLServer.js +197 -0
  33. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts +3 -0
  34. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts.map +1 -0
  35. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.js +52 -0
  36. package/lib/actions/appActions/appActions.d.ts +29 -0
  37. package/lib/actions/appActions/appActions.d.ts.map +1 -0
  38. package/lib/actions/appActions/appActions.js +159 -0
  39. package/lib/actions/connectionActions/connectionActions.d.ts +19 -0
  40. package/lib/actions/connectionActions/connectionActions.d.ts.map +1 -0
  41. package/lib/actions/connectionActions/connectionActions.js +131 -0
  42. package/lib/actions/contentActions/contentActions.d.ts +34 -0
  43. package/lib/actions/contentActions/contentActions.d.ts.map +1 -0
  44. package/lib/actions/contentActions/contentActions.js +314 -0
  45. package/lib/actions/conversationActions/conversationActions.d.ts +30 -0
  46. package/lib/actions/conversationActions/conversationActions.d.ts.map +1 -0
  47. package/lib/actions/conversationActions/conversationActions.js +225 -0
  48. package/lib/actions/eventActions/eventActions.d.ts +27 -7
  49. package/lib/actions/eventActions/eventActions.d.ts.map +1 -0
  50. package/lib/actions/eventActions/eventActions.js +436 -2
  51. package/lib/actions/groupActions/groupActions.d.ts +30 -0
  52. package/lib/actions/groupActions/groupActions.d.ts.map +1 -0
  53. package/lib/actions/groupActions/groupActions.js +229 -0
  54. package/lib/actions/imageActions/imageActions.d.ts +16 -10
  55. package/lib/actions/imageActions/imageActions.d.ts.map +1 -0
  56. package/lib/actions/imageActions/imageActions.js +593 -2
  57. package/lib/actions/index.d.ts +21 -9
  58. package/lib/actions/index.d.ts.map +1 -0
  59. package/lib/actions/index.js +22 -2
  60. package/lib/actions/locationActions/locationActions.d.ts +11 -9
  61. package/lib/actions/locationActions/locationActions.d.ts.map +1 -0
  62. package/lib/actions/locationActions/locationActions.js +388 -2
  63. package/lib/actions/messageActions/messageActions.d.ts +16 -32
  64. package/lib/actions/messageActions/messageActions.d.ts.map +1 -0
  65. package/lib/actions/messageActions/messageActions.js +235 -2
  66. package/lib/actions/permissionActions/permissionActions.d.ts +34 -0
  67. package/lib/actions/permissionActions/permissionActions.d.ts.map +1 -0
  68. package/lib/actions/permissionActions/permissionActions.js +330 -0
  69. package/lib/actions/personaActions/personaActions.d.ts +65 -0
  70. package/lib/actions/personaActions/personaActions.d.ts.map +1 -0
  71. package/lib/actions/personaActions/personaActions.js +572 -0
  72. package/lib/actions/postActions/postActions.d.ts +12 -32
  73. package/lib/actions/postActions/postActions.d.ts.map +1 -0
  74. package/lib/actions/postActions/postActions.js +447 -2
  75. package/lib/actions/reactionActions/reactionActions.d.ts +13 -27
  76. package/lib/actions/reactionActions/reactionActions.d.ts.map +1 -0
  77. package/lib/actions/reactionActions/reactionActions.js +413 -2
  78. package/lib/actions/sseActions/sseActions.d.ts +1 -0
  79. package/lib/actions/sseActions/sseActions.d.ts.map +1 -0
  80. package/lib/actions/sseActions/sseActions.js +148 -2
  81. package/lib/actions/subscriptionActions/subscriptionActions.d.ts +24 -0
  82. package/lib/actions/subscriptionActions/subscriptionActions.d.ts.map +1 -0
  83. package/lib/actions/subscriptionActions/subscriptionActions.js +329 -0
  84. package/lib/actions/tagActions/tagActions.d.ts +13 -31
  85. package/lib/actions/tagActions/tagActions.d.ts.map +1 -0
  86. package/lib/actions/tagActions/tagActions.js +347 -2
  87. package/lib/actions/translationActions/translationActions.d.ts +38 -0
  88. package/lib/actions/translationActions/translationActions.d.ts.map +1 -0
  89. package/lib/actions/translationActions/translationActions.js +189 -0
  90. package/lib/actions/userActions/userActions.d.ts +44 -95
  91. package/lib/actions/userActions/userActions.d.ts.map +1 -0
  92. package/lib/actions/userActions/userActions.js +870 -2
  93. package/lib/actions/videoActions/videoActions.d.ts +41 -0
  94. package/lib/actions/videoActions/videoActions.d.ts.map +1 -0
  95. package/lib/actions/videoActions/videoActions.js +532 -0
  96. package/lib/actions/websocketActions/websocketActions.d.ts +20 -21
  97. package/lib/actions/websocketActions/websocketActions.d.ts.map +1 -0
  98. package/lib/actions/websocketActions/websocketActions.js +377 -2
  99. package/lib/adapters/appAdapter/appAdapter.d.ts +8 -0
  100. package/lib/adapters/appAdapter/appAdapter.d.ts.map +1 -0
  101. package/lib/adapters/appAdapter/appAdapter.js +90 -0
  102. package/lib/adapters/arangoAdapter/arangoAdapter.d.ts +3 -2
  103. package/lib/adapters/arangoAdapter/arangoAdapter.d.ts.map +1 -0
  104. package/lib/adapters/arangoAdapter/arangoAdapter.js +75 -2
  105. package/lib/adapters/contentAdapter/contentAdapter.d.ts +3 -2
  106. package/lib/adapters/contentAdapter/contentAdapter.d.ts.map +1 -0
  107. package/lib/adapters/contentAdapter/contentAdapter.js +107 -2
  108. package/lib/adapters/conversationAdapter/conversationAdapter.d.ts +3 -2
  109. package/lib/adapters/conversationAdapter/conversationAdapter.d.ts.map +1 -0
  110. package/lib/adapters/conversationAdapter/conversationAdapter.js +75 -2
  111. package/lib/adapters/eventAdapter/eventAdapter.d.ts +5 -2
  112. package/lib/adapters/eventAdapter/eventAdapter.d.ts.map +1 -0
  113. package/lib/adapters/eventAdapter/eventAdapter.js +162 -2
  114. package/lib/adapters/fileAdapter/fileAdapter.d.ts +3 -2
  115. package/lib/adapters/fileAdapter/fileAdapter.d.ts.map +1 -0
  116. package/lib/adapters/fileAdapter/fileAdapter.js +118 -2
  117. package/lib/adapters/groupAdapter/groupAdapter.d.ts +28 -0
  118. package/lib/adapters/groupAdapter/groupAdapter.d.ts.map +1 -0
  119. package/lib/adapters/groupAdapter/groupAdapter.js +66 -0
  120. package/lib/adapters/imageAdapter/imageAdapter.d.ts +9 -2
  121. package/lib/adapters/imageAdapter/imageAdapter.d.ts.map +1 -0
  122. package/lib/adapters/imageAdapter/imageAdapter.js +134 -2
  123. package/lib/adapters/index.d.ts +34 -16
  124. package/lib/adapters/index.d.ts.map +1 -0
  125. package/lib/adapters/index.js +19 -2
  126. package/lib/adapters/locationAdapter/locationAdapter.d.ts +3 -2
  127. package/lib/adapters/locationAdapter/locationAdapter.d.ts.map +1 -0
  128. package/lib/adapters/locationAdapter/locationAdapter.js +95 -2
  129. package/lib/adapters/messageAdapter/messageAdapter.d.ts +23 -19
  130. package/lib/adapters/messageAdapter/messageAdapter.d.ts.map +1 -0
  131. package/lib/adapters/messageAdapter/messageAdapter.js +82 -2
  132. package/lib/adapters/permissionAdapter/permissionAdapter.d.ts +41 -0
  133. package/lib/adapters/permissionAdapter/permissionAdapter.d.ts.map +1 -0
  134. package/lib/adapters/permissionAdapter/permissionAdapter.js +120 -0
  135. package/lib/adapters/personaAdapter/personaAdapter.d.ts +28 -2
  136. package/lib/adapters/personaAdapter/personaAdapter.d.ts.map +1 -0
  137. package/lib/adapters/personaAdapter/personaAdapter.js +161 -2
  138. package/lib/adapters/postAdapter/postAdapter.d.ts +3 -2
  139. package/lib/adapters/postAdapter/postAdapter.d.ts.map +1 -0
  140. package/lib/adapters/postAdapter/postAdapter.js +115 -2
  141. package/lib/adapters/reactionAdapter/reactionAdapter.d.ts +5 -2
  142. package/lib/adapters/reactionAdapter/reactionAdapter.d.ts.map +1 -0
  143. package/lib/adapters/reactionAdapter/reactionAdapter.js +81 -2
  144. package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts +3 -2
  145. package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts.map +1 -0
  146. package/lib/adapters/reaktorAdapter/reaktorAdapter.js +58 -2
  147. package/lib/adapters/sessionAdapter/sessionAdapter.d.ts +3 -2
  148. package/lib/adapters/sessionAdapter/sessionAdapter.d.ts.map +1 -0
  149. package/lib/adapters/sessionAdapter/sessionAdapter.js +80 -2
  150. package/lib/adapters/tagAdapter/tagAdapter.d.ts +3 -2
  151. package/lib/adapters/tagAdapter/tagAdapter.d.ts.map +1 -0
  152. package/lib/adapters/tagAdapter/tagAdapter.js +98 -2
  153. package/lib/adapters/translationAdapter/translationAdapter.d.ts +21 -0
  154. package/lib/adapters/translationAdapter/translationAdapter.d.ts.map +1 -0
  155. package/lib/adapters/translationAdapter/translationAdapter.js +55 -0
  156. package/lib/adapters/userAdapter/userAdapter.d.ts +18 -6
  157. package/lib/adapters/userAdapter/userAdapter.d.ts.map +1 -0
  158. package/lib/adapters/userAdapter/userAdapter.js +302 -2
  159. package/lib/adapters/videoAdapter/videoAdapter.d.ts +8 -0
  160. package/lib/adapters/videoAdapter/videoAdapter.d.ts.map +1 -0
  161. package/lib/adapters/videoAdapter/videoAdapter.js +194 -0
  162. package/lib/config/index.d.ts +19 -6
  163. package/lib/config/index.d.ts.map +1 -0
  164. package/lib/config/index.js +97 -2
  165. package/lib/constants/Collections.d.ts +44 -0
  166. package/lib/constants/Collections.d.ts.map +1 -0
  167. package/lib/constants/Collections.js +40 -0
  168. package/lib/constants/MetropolisConstants.d.ts +1 -0
  169. package/lib/constants/MetropolisConstants.d.ts.map +1 -0
  170. package/lib/constants/MetropolisConstants.js +15 -2
  171. package/lib/graphql/message.d.ts +1 -0
  172. package/lib/graphql/message.d.ts.map +1 -0
  173. package/lib/graphql/message.js +6 -4
  174. package/lib/graphql/notification.d.ts +1 -0
  175. package/lib/graphql/notification.d.ts.map +1 -0
  176. package/lib/graphql/notification.js +6 -4
  177. package/lib/graphql/session.d.ts +1 -0
  178. package/lib/graphql/session.d.ts.map +1 -0
  179. package/lib/graphql/session.js +4 -3
  180. package/lib/index.d.ts +45 -22
  181. package/lib/index.d.ts.map +1 -0
  182. package/lib/index.js +248 -2
  183. package/lib/stores/appStore.d.ts +1 -0
  184. package/lib/stores/appStore.d.ts.map +1 -0
  185. package/lib/stores/appStore.js +23 -2
  186. package/lib/stores/contentStore.d.ts +36 -0
  187. package/lib/stores/contentStore.d.ts.map +1 -0
  188. package/lib/stores/contentStore.js +139 -0
  189. package/lib/stores/conversationStore.d.ts +38 -0
  190. package/lib/stores/conversationStore.d.ts.map +1 -0
  191. package/lib/stores/conversationStore.js +117 -0
  192. package/lib/stores/eventStore.d.ts +4 -1
  193. package/lib/stores/eventStore.d.ts.map +1 -0
  194. package/lib/stores/eventStore.js +47 -2
  195. package/lib/stores/groupStore.d.ts +37 -0
  196. package/lib/stores/groupStore.d.ts.map +1 -0
  197. package/lib/stores/groupStore.js +68 -0
  198. package/lib/stores/imageStore.d.ts +6 -1
  199. package/lib/stores/imageStore.d.ts.map +1 -0
  200. package/lib/stores/imageStore.js +53 -2
  201. package/lib/stores/index.d.ts +20 -11
  202. package/lib/stores/index.d.ts.map +1 -0
  203. package/lib/stores/index.js +24 -2
  204. package/lib/stores/locationStore.d.ts +2 -1
  205. package/lib/stores/locationStore.d.ts.map +1 -0
  206. package/lib/stores/locationStore.js +42 -2
  207. package/lib/stores/messageStore.d.ts +19 -4
  208. package/lib/stores/messageStore.d.ts.map +1 -0
  209. package/lib/stores/messageStore.js +137 -2
  210. package/lib/stores/notificationStore.d.ts +33 -0
  211. package/lib/stores/notificationStore.d.ts.map +1 -0
  212. package/lib/stores/notificationStore.js +55 -0
  213. package/lib/stores/permissionStore.d.ts +37 -0
  214. package/lib/stores/permissionStore.d.ts.map +1 -0
  215. package/lib/stores/permissionStore.js +117 -0
  216. package/lib/stores/personaStore.d.ts +26 -0
  217. package/lib/stores/personaStore.d.ts.map +1 -0
  218. package/lib/stores/personaStore.js +118 -0
  219. package/lib/stores/postStore.d.ts +2 -1
  220. package/lib/stores/postStore.d.ts.map +1 -0
  221. package/lib/stores/postStore.js +53 -2
  222. package/lib/stores/reactionStore.d.ts +1 -0
  223. package/lib/stores/reactionStore.d.ts.map +1 -0
  224. package/lib/stores/reactionStore.js +28 -2
  225. package/lib/stores/subscriptionStore.d.ts +41 -0
  226. package/lib/stores/subscriptionStore.d.ts.map +1 -0
  227. package/lib/stores/subscriptionStore.js +85 -0
  228. package/lib/stores/tagStore.d.ts +8 -5
  229. package/lib/stores/tagStore.d.ts.map +1 -0
  230. package/lib/stores/tagStore.js +87 -2
  231. package/lib/stores/translationStore.d.ts +42 -0
  232. package/lib/stores/translationStore.d.ts.map +1 -0
  233. package/lib/stores/translationStore.js +122 -0
  234. package/lib/stores/userStore.d.ts +5 -4
  235. package/lib/stores/userStore.d.ts.map +1 -0
  236. package/lib/stores/userStore.js +319 -2
  237. package/lib/stores/videoStore.d.ts +39 -0
  238. package/lib/stores/videoStore.d.ts.map +1 -0
  239. package/lib/stores/videoStore.js +132 -0
  240. package/lib/stores/websocketStore.d.ts +1 -0
  241. package/lib/stores/websocketStore.d.ts.map +1 -0
  242. package/lib/stores/websocketStore.js +51 -2
  243. package/lib/types/apps.types.d.ts +17 -0
  244. package/lib/types/apps.types.d.ts.map +1 -0
  245. package/lib/types/apps.types.js +6 -0
  246. package/lib/types/common.types.d.ts +31 -0
  247. package/lib/types/common.types.d.ts.map +1 -0
  248. package/lib/types/common.types.js +6 -0
  249. package/lib/types/conversations.types.d.ts +17 -0
  250. package/lib/types/conversations.types.d.ts.map +1 -0
  251. package/lib/types/conversations.types.js +6 -0
  252. package/lib/types/edges.types.d.ts +38 -0
  253. package/lib/types/edges.types.d.ts.map +1 -0
  254. package/lib/types/edges.types.js +6 -0
  255. package/lib/types/groups.types.d.ts +19 -0
  256. package/lib/types/groups.types.d.ts.map +1 -0
  257. package/lib/types/groups.types.js +6 -0
  258. package/lib/types/index.d.ts +12 -0
  259. package/lib/types/index.d.ts.map +1 -0
  260. package/lib/types/index.js +12 -0
  261. package/lib/types/subscriptions.types.d.ts +32 -0
  262. package/lib/types/subscriptions.types.d.ts.map +1 -0
  263. package/lib/types/subscriptions.types.js +6 -0
  264. package/lib/types/videos.types.d.ts +61 -0
  265. package/lib/types/videos.types.d.ts.map +1 -0
  266. package/lib/types/videos.types.js +6 -0
  267. package/lib/utils/MetropolisProvider.d.ts +39 -15
  268. package/lib/utils/MetropolisProvider.d.ts.map +1 -0
  269. package/lib/utils/MetropolisProvider.js +31 -2
  270. package/lib/utils/actionFactory.d.ts +21 -19
  271. package/lib/utils/actionFactory.d.ts.map +1 -0
  272. package/lib/utils/actionFactory.js +95 -2
  273. package/lib/utils/api.d.ts +5 -4
  274. package/lib/utils/api.d.ts.map +1 -0
  275. package/lib/utils/api.js +252 -6
  276. package/lib/utils/app.d.ts +1 -0
  277. package/lib/utils/app.d.ts.map +1 -0
  278. package/lib/utils/app.js +15 -2
  279. package/lib/utils/baseActionFactory.d.ts +5 -23
  280. package/lib/utils/baseActionFactory.d.ts.map +1 -0
  281. package/lib/utils/baseActionFactory.js +72 -2
  282. package/lib/utils/configUtils.d.ts +11 -0
  283. package/lib/utils/configUtils.d.ts.map +1 -0
  284. package/lib/utils/configUtils.js +20 -0
  285. package/lib/utils/dateUtils.d.ts +1 -0
  286. package/lib/utils/dateUtils.d.ts.map +1 -0
  287. package/lib/utils/dateUtils.js +11 -2
  288. package/lib/utils/file.d.ts +3 -1
  289. package/lib/utils/file.d.ts.map +1 -0
  290. package/lib/utils/file.js +156 -2
  291. package/lib/utils/i18n.d.ts +7 -0
  292. package/lib/utils/i18n.d.ts.map +1 -0
  293. package/lib/utils/i18n.js +96 -0
  294. package/lib/utils/index.d.ts +20 -0
  295. package/lib/utils/index.d.ts.map +1 -0
  296. package/lib/utils/index.js +26 -0
  297. package/lib/utils/location.d.ts +4 -3
  298. package/lib/utils/location.d.ts.map +1 -0
  299. package/lib/utils/location.js +82 -2
  300. package/lib/utils/permissionUtils.d.ts +22 -0
  301. package/lib/utils/permissionUtils.d.ts.map +1 -0
  302. package/lib/utils/permissionUtils.js +72 -0
  303. package/lib/utils/requestCache.d.ts +8 -0
  304. package/lib/utils/requestCache.d.ts.map +1 -0
  305. package/lib/utils/requestCache.js +53 -0
  306. package/lib/utils/session.d.ts +14 -0
  307. package/lib/utils/session.d.ts.map +1 -0
  308. package/lib/utils/session.js +107 -0
  309. package/lib/utils/useConversationTyping.d.ts +26 -0
  310. package/lib/utils/useConversationTyping.d.ts.map +1 -0
  311. package/lib/utils/useConversationTyping.js +117 -0
  312. package/lib/utils/useMetropolis.d.ts +67 -12
  313. package/lib/utils/useMetropolis.d.ts.map +1 -0
  314. package/lib/utils/useMetropolis.js +311 -2
  315. package/lib/utils/useTranslations.d.ts +16 -0
  316. package/lib/utils/useTranslations.d.ts.map +1 -0
  317. package/lib/utils/useTranslations.js +105 -0
  318. package/lib/utils/validatorFactory.d.ts +3 -2
  319. package/lib/utils/validatorFactory.d.ts.map +1 -0
  320. package/lib/utils/validatorFactory.js +95 -2
  321. package/package.json +58 -17
  322. package/temp_signin.ts +73 -0
  323. package/lib/actions/profileActions/profileActions.d.ts +0 -50
  324. package/lib/actions/profileActions/profileActions.js +0 -2
  325. package/lib/adapters/profileAdapter/profileAdapter.d.ts +0 -32
  326. package/lib/adapters/profileAdapter/profileAdapter.js +0 -2
  327. package/lib/stores/profileStore.d.ts +0 -24
  328. package/lib/stores/profileStore.js +0 -2
  329. /package/{FACTORY_PATTERN_GUIDE.md → factoryPatternGuide.md} +0 -0
@@ -0,0 +1,1038 @@
1
+ # MetropolisJS Collections Reference
2
+
3
+ Comprehensive reference for all MetropolisJS collection types, including available fields, CRUD operations, and specific examples.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Collection Overview](#collection-overview)
8
+ - [Users](#users)
9
+ - [Posts](#posts)
10
+ - [Groups](#groups)
11
+ - [Messages](#messages)
12
+ - [Conversations](#conversations)
13
+ - [Videos](#videos)
14
+ - [Images](#images)
15
+ - [Files](#files)
16
+ - [Apps](#apps)
17
+ - [Personas](#personas)
18
+ - [Tags](#tags)
19
+ - [Content](#content)
20
+
21
+ ## Collection Overview
22
+
23
+ All collections in MetropolisJS share common patterns and base fields through the `BaseDocument` and `ExtensibleFields` interfaces.
24
+
25
+ ### Common Base Fields
26
+
27
+ All collection types include these base fields:
28
+
29
+ ```typescript
30
+ interface BaseDocument {
31
+ _id?: string; // ArangoDB internal ID (e.g., 'posts/123')
32
+ _key?: string; // ArangoDB key (e.g., '123')
33
+ _rev?: string; // ArangoDB revision
34
+ added?: number; // Creation timestamp (Unix epoch)
35
+ id?: string; // External ID reference
36
+ modified?: number; // Last modification timestamp
37
+ type?: string; // Item type/category
38
+ updated?: number; // Last update timestamp
39
+ }
40
+
41
+ interface ExtensibleFields {
42
+ [key: string]: any; // Custom fields for application-specific data
43
+ }
44
+ ```
45
+
46
+ ### Collections Constant
47
+
48
+ ```typescript
49
+ import {COLLECTIONS} from '@nlabs/metropolisjs';
50
+
51
+ const collections = {
52
+ APPS: 'apps',
53
+ CONVERSATIONS: 'conversations',
54
+ FILES: 'files',
55
+ GROUPS: 'groups',
56
+ IMAGES: 'images',
57
+ MESSAGES: 'messages',
58
+ POSTS: 'posts',
59
+ PERSONAS: 'personas',
60
+ TAGS: 'tags',
61
+ USERS: 'users',
62
+ VIDEOS: 'videos'
63
+ };
64
+ ```
65
+
66
+ ## Users
67
+
68
+ User accounts and authentication.
69
+
70
+ ### User Fields
71
+
72
+ ```typescript
73
+ interface UserType extends BaseDocument, ExtensibleFields {
74
+ birthdate?: number; // Birth date (Unix timestamp)
75
+ email?: string; // User email
76
+ imageUrl?: string; // Profile image URL
77
+ locale?: string; // User locale (e.g., 'en-US')
78
+ name?: string; // Display name
79
+ phoneNumber?: string; // Phone number
80
+ thumbUrl?: string; // Thumbnail image URL
81
+ userId?: string; // Unique user identifier
82
+ username?: string; // Unique username
83
+ }
84
+ ```
85
+
86
+ ### User Actions
87
+
88
+ ```typescript
89
+ import {createUserActions} from '@nlabs/metropolisjs';
90
+
91
+ const userActions = createUserActions(flux);
92
+
93
+ interface UserActions {
94
+ signIn: (credentials, expires?) => Promise<Session>;
95
+ signOut: () => Promise<boolean>;
96
+ signUp: (userData) => Promise<User>;
97
+ itemById: (userId, props?) => Promise<User>;
98
+ update: (userData, props?) => Promise<User>;
99
+ delete: (userId, props?) => Promise<User>;
100
+ refreshSession: () => Promise<Session>;
101
+ updateUserAdapter: (adapter) => void;
102
+ updateUserAdapterOptions: (options) => void;
103
+ }
104
+ ```
105
+
106
+ ### User Examples
107
+
108
+ ```typescript
109
+ // Sign up new user
110
+ const newUser = await userActions.signUp({
111
+ email: 'user@example.com',
112
+ password: 'securePassword123',
113
+ username: 'johndoe',
114
+ name: 'John Doe',
115
+ birthdate: Date.parse('1990-01-01')
116
+ });
117
+
118
+ // Sign in
119
+ const session = await userActions.signIn({
120
+ username: 'johndoe',
121
+ password: 'securePassword123'
122
+ }, 86400); // Expires in 24 hours
123
+
124
+ // Get user profile
125
+ const user = await userActions.itemById('user123', [
126
+ 'email',
127
+ 'imageUrl',
128
+ 'thumbUrl'
129
+ ]);
130
+
131
+ // Update profile
132
+ const updatedUser = await userActions.update({
133
+ userId: 'user123',
134
+ name: 'John Smith',
135
+ locale: 'en-US',
136
+ bio: 'Software developer' // Extensible field
137
+ });
138
+
139
+ // Refresh session
140
+ const refreshedSession = await userActions.refreshSession();
141
+
142
+ // Sign out
143
+ await userActions.signOut();
144
+ ```
145
+
146
+ ## Posts
147
+
148
+ User-generated content including text, events, and media.
149
+
150
+ ### Post Fields
151
+
152
+ ```typescript
153
+ interface PostType extends BaseDocument, ExtensibleFields {
154
+ content?: string; // Post content/body
155
+ endDate?: number; // Event end date (Unix timestamp)
156
+ files?: any[]; // Attached files
157
+ groupId?: string; // Parent group ID
158
+ latitude?: number; // Location latitude
159
+ location?: string; // Location name
160
+ longitude?: number; // Location longitude
161
+ name?: string; // Post title
162
+ parentId?: string; // Parent post ID (for comments)
163
+ postId?: string; // Unique post identifier
164
+ privacy?: string; // Privacy setting ('public', 'private', etc.)
165
+ startDate?: number; // Event start date (Unix timestamp)
166
+ tags?: any[]; // Associated tags
167
+ userId?: string; // Author user ID
168
+ }
169
+ ```
170
+
171
+ ### Post Actions
172
+
173
+ ```typescript
174
+ import {createPostActions} from '@nlabs/metropolisjs';
175
+
176
+ const postActions = createPostActions(flux);
177
+
178
+ interface PostActions {
179
+ add: (postData, props?) => Promise<Post>;
180
+ itemById: (postId, props?) => Promise<Post>;
181
+ listByLatest: (from?, to?, props?) => Promise<Post[]>;
182
+ listByLocation: (lat, lng, from?, to?, props?) => Promise<Post[]>;
183
+ listByReactions: (reactions, lat, lng, from?, to?, props?) => Promise<Post[]>;
184
+ listByTags: (tags, lat, lng, from?, to?, props?) => Promise<Post[]>;
185
+ delete: (postId, props?) => Promise<Post>;
186
+ update: (postData, props?) => Promise<Post>;
187
+ updatePostAdapter: (adapter) => void;
188
+ updatePostAdapterOptions: (options) => void;
189
+ }
190
+ ```
191
+
192
+ ### Post Examples
193
+
194
+ ```typescript
195
+ // Create text post
196
+ const textPost = await postActions.add({
197
+ name: 'Announcement',
198
+ content: 'Important update for everyone!',
199
+ type: 'text',
200
+ privacy: 'public'
201
+ });
202
+
203
+ // Create event post
204
+ const eventPost = await postActions.add({
205
+ name: 'Community Meetup',
206
+ content: 'Join us for our monthly meetup',
207
+ type: 'event',
208
+ startDate: Date.parse('2024-06-15T18:00:00'),
209
+ endDate: Date.parse('2024-06-15T21:00:00'),
210
+ location: 'San Francisco',
211
+ latitude: 37.7749,
212
+ longitude: -122.4194
213
+ });
214
+
215
+ // Create post with tags
216
+ const taggedPost = await postActions.add({
217
+ name: 'Tech News',
218
+ content: 'Latest developments in AI',
219
+ tags: [
220
+ {name: 'technology'},
221
+ {name: 'ai'},
222
+ {name: 'news'}
223
+ ]
224
+ });
225
+
226
+ // Get post with nested data
227
+ const post = await postActions.itemById('post123', [
228
+ 'tags {name, tagId}',
229
+ 'user {username, imageUrl, thumbUrl}',
230
+ 'files {fileId, fileName, fileType}',
231
+ 'viewCount',
232
+ 'likeCount'
233
+ ]);
234
+
235
+ // List recent posts
236
+ const recentPosts = await postActions.listByLatest(0, 20, [
237
+ 'name',
238
+ 'content',
239
+ 'user {username}',
240
+ 'viewCount'
241
+ ]);
242
+
243
+ // List posts by location
244
+ const nearbyPosts = await postActions.listByLocation(
245
+ 37.7749, // latitude
246
+ -122.4194, // longitude
247
+ 0, // from
248
+ 10, // to
249
+ ['name', 'location', 'distance']
250
+ );
251
+
252
+ // List popular posts by reactions
253
+ const popularPosts = await postActions.listByReactions(
254
+ ['like', 'view'], // reaction types
255
+ 37.7749,
256
+ -122.4194,
257
+ 0,
258
+ 20
259
+ );
260
+
261
+ // List posts by tags
262
+ const techPosts = await postActions.listByTags(
263
+ ['technology', 'programming'],
264
+ 37.7749,
265
+ -122.4194,
266
+ 0,
267
+ 20
268
+ );
269
+
270
+ // Update post
271
+ await postActions.update({
272
+ postId: 'post123',
273
+ content: 'Updated content',
274
+ edited: Date.now() // Extensible field
275
+ });
276
+
277
+ // Delete post
278
+ await postActions.delete('post123');
279
+ ```
280
+
281
+ ## Groups
282
+
283
+ Communities and organizational units.
284
+
285
+ ### Group Fields
286
+
287
+ ```typescript
288
+ interface GroupType extends BaseDocument, ExtensibleFields {
289
+ description?: string; // Group description
290
+ groupId?: string; // Unique group identifier
291
+ imageUrl?: string; // Group image URL
292
+ isPrivate?: boolean; // Privacy flag
293
+ memberCount?: number; // Number of members
294
+ name?: string; // Group name
295
+ ownerId?: string; // Owner user ID
296
+ settings?: Record<string, any>; // Group settings
297
+ tags?: any[]; // Associated tags
298
+ thumbUrl?: string; // Thumbnail image URL
299
+ userId?: string; // Associated user ID
300
+ }
301
+ ```
302
+
303
+ ### Group Actions
304
+
305
+ ```typescript
306
+ import {createGroupActions} from '@nlabs/metropolisjs';
307
+
308
+ const groupActions = createGroupActions(flux);
309
+
310
+ interface GroupActions {
311
+ add: (groupData, props?) => Promise<Group>;
312
+ itemById: (groupId, props?) => Promise<Group>;
313
+ listByLatest: (from?, to?, props?) => Promise<Group[]>;
314
+ delete: (groupId, props?) => Promise<Group>;
315
+ update: (groupData, props?) => Promise<Group>;
316
+ updateGroupAdapter: (adapter) => void;
317
+ updateGroupAdapterOptions: (options) => void;
318
+ }
319
+ ```
320
+
321
+ ### Group Examples
322
+
323
+ ```typescript
324
+ // Create public group
325
+ const publicGroup = await groupActions.add({
326
+ name: 'JavaScript Developers',
327
+ description: 'Community for JS developers',
328
+ type: 'community',
329
+ isPrivate: false,
330
+ settings: {
331
+ allowInvites: true,
332
+ requireApproval: false,
333
+ allowPublicPosts: true
334
+ }
335
+ });
336
+
337
+ // Create private group
338
+ const privateGroup = await groupActions.add({
339
+ name: 'Project Team',
340
+ description: 'Internal project team',
341
+ type: 'team',
342
+ isPrivate: true,
343
+ settings: {
344
+ allowInvites: false,
345
+ requireApproval: true
346
+ }
347
+ });
348
+
349
+ // Get group details
350
+ const group = await groupActions.itemById('group123', [
351
+ 'memberCount',
352
+ 'tags {name}',
353
+ 'settings'
354
+ ]);
355
+
356
+ // List groups
357
+ const groups = await groupActions.listByLatest(0, 20, [
358
+ 'name',
359
+ 'description',
360
+ 'memberCount',
361
+ 'isPrivate'
362
+ ]);
363
+
364
+ // Update group settings
365
+ await groupActions.update({
366
+ groupId: 'group123',
367
+ settings: {
368
+ allowInvites: true,
369
+ requireApproval: false,
370
+ maxMembers: 100
371
+ }
372
+ });
373
+
374
+ // Delete group
375
+ await groupActions.delete('group123');
376
+ ```
377
+
378
+ ## Messages
379
+
380
+ Direct messages and group chat messages.
381
+
382
+ ### Message Fields
383
+
384
+ ```typescript
385
+ interface MessageType extends BaseDocument, ExtensibleFields {
386
+ content?: string; // Message content
387
+ conversationId?: string; // Parent conversation ID
388
+ files?: any[]; // Attached files
389
+ messageId?: string; // Unique message identifier
390
+ metadata?: Record<string, any>; // Additional metadata
391
+ parentId?: string; // Parent message ID (for threads)
392
+ status?: string; // Message status
393
+ userId?: string; // Sender user ID
394
+ }
395
+ ```
396
+
397
+ ### Message Actions
398
+
399
+ ```typescript
400
+ import {createMessageActions} from '@nlabs/metropolisjs';
401
+
402
+ const messageActions = createMessageActions(flux);
403
+
404
+ interface MessageActions {
405
+ add: (messageData, props?) => Promise<Message>;
406
+ itemById: (messageId, props?) => Promise<Message>;
407
+ listByConversation: (conversationId, from?, to?, props?) => Promise<Message[]>;
408
+ delete: (messageId, props?) => Promise<Message>;
409
+ update: (messageData, props?) => Promise<Message>;
410
+ updateMessageAdapter: (adapter) => void;
411
+ updateMessageAdapterOptions: (options) => void;
412
+ }
413
+ ```
414
+
415
+ ### Message Examples
416
+
417
+ ```typescript
418
+ // Send message
419
+ const message = await messageActions.add({
420
+ conversationId: 'conv123',
421
+ content: 'Hello, how are you?',
422
+ type: 'text'
423
+ });
424
+
425
+ // Send message with attachments
426
+ const messageWithFiles = await messageActions.add({
427
+ conversationId: 'conv123',
428
+ content: 'Check out these files',
429
+ files: [
430
+ {fileId: 'file1', fileName: 'document.pdf'},
431
+ {fileId: 'file2', fileName: 'image.jpg'}
432
+ ]
433
+ });
434
+
435
+ // Get message
436
+ const msg = await messageActions.itemById('msg123', [
437
+ 'user {username, imageUrl}',
438
+ 'files {fileId, fileName, fileUrl}'
439
+ ]);
440
+
441
+ // List conversation messages
442
+ const messages = await messageActions.listByConversation(
443
+ 'conv123',
444
+ 0,
445
+ 50,
446
+ ['content', 'user {username}', 'added']
447
+ );
448
+
449
+ // Update message (edit)
450
+ await messageActions.update({
451
+ messageId: 'msg123',
452
+ content: 'Updated message content',
453
+ editedAt: Date.now() // Extensible field
454
+ });
455
+
456
+ // Delete message
457
+ await messageActions.delete('msg123');
458
+ ```
459
+
460
+ ## Conversations
461
+
462
+ Chat threads and message containers.
463
+
464
+ ### Conversation Fields
465
+
466
+ ```typescript
467
+ interface ConversationType extends BaseDocument, ExtensibleFields {
468
+ conversationId?: string; // Unique conversation identifier
469
+ isGroup?: boolean; // Group conversation flag
470
+ lastMessage?: string; // Last message preview
471
+ lastMessageTime?: number; // Last message timestamp
472
+ name?: string; // Conversation name
473
+ participants?: any[]; // Participant user IDs
474
+ settings?: Record<string, any>; // Conversation settings
475
+ }
476
+ ```
477
+
478
+ ### Conversation Actions
479
+
480
+ ```typescript
481
+ import {createConversationActions} from '@nlabs/metropolisjs';
482
+
483
+ const conversationActions = createConversationActions(flux);
484
+
485
+ interface ConversationActions {
486
+ add: (conversationData, props?) => Promise<Conversation>;
487
+ itemById: (conversationId, props?) => Promise<Conversation>;
488
+ listByUser: (userId, from?, to?, props?) => Promise<Conversation[]>;
489
+ delete: (conversationId, props?) => Promise<Conversation>;
490
+ update: (conversationData, props?) => Promise<Conversation>;
491
+ updateConversationAdapter: (adapter) => void;
492
+ updateConversationAdapterOptions: (options) => void;
493
+ }
494
+ ```
495
+
496
+ ### Conversation Examples
497
+
498
+ ```typescript
499
+ // Create direct conversation
500
+ const directConversation = await conversationActions.add({
501
+ participants: ['user1', 'user2'],
502
+ isGroup: false,
503
+ type: 'direct'
504
+ });
505
+
506
+ // Create group conversation
507
+ const groupConversation = await conversationActions.add({
508
+ name: 'Team Chat',
509
+ participants: ['user1', 'user2', 'user3'],
510
+ isGroup: true,
511
+ type: 'group',
512
+ settings: {
513
+ allowInvites: true,
514
+ muteNotifications: false
515
+ }
516
+ });
517
+
518
+ // Get conversation
519
+ const conversation = await conversationActions.itemById('conv123', [
520
+ 'participants {userId, username, imageUrl}',
521
+ 'lastMessage',
522
+ 'lastMessageTime'
523
+ ]);
524
+
525
+ // List user conversations
526
+ const conversations = await conversationActions.listByUser(
527
+ 'user123',
528
+ 0,
529
+ 20,
530
+ ['name', 'lastMessage', 'lastMessageTime']
531
+ );
532
+
533
+ // Update conversation settings
534
+ await conversationActions.update({
535
+ conversationId: 'conv123',
536
+ settings: {
537
+ muteNotifications: true
538
+ }
539
+ });
540
+
541
+ // Delete conversation
542
+ await conversationActions.delete('conv123');
543
+ ```
544
+
545
+ ## Videos
546
+
547
+ Video content and metadata.
548
+
549
+ ### Video Fields
550
+
551
+ ```typescript
552
+ interface VideoType extends BaseDocument, ExtensibleFields {
553
+ description?: string; // Video description
554
+ duration?: number; // Duration in seconds
555
+ format?: string; // Video format (mp4, webm, etc.)
556
+ height?: number; // Video height in pixels
557
+ name?: string; // Video title
558
+ size?: number; // File size in bytes
559
+ thumbnailUrl?: string; // Thumbnail image URL
560
+ url?: string; // Video URL
561
+ userId?: string; // Owner user ID
562
+ videoId?: string; // Unique video identifier
563
+ width?: number; // Video width in pixels
564
+ }
565
+ ```
566
+
567
+ ### Video Actions
568
+
569
+ ```typescript
570
+ import {createVideoActions} from '@nlabs/metropolisjs';
571
+
572
+ const videoActions = createVideoActions(flux);
573
+
574
+ interface VideoActions {
575
+ add: (videoData, props?) => Promise<Video>;
576
+ itemById: (videoId, props?) => Promise<Video>;
577
+ listByLatest: (from?, to?, props?) => Promise<Video[]>;
578
+ delete: (videoId, props?) => Promise<Video>;
579
+ update: (videoData, props?) => Promise<Video>;
580
+ updateVideoAdapter: (adapter) => void;
581
+ updateVideoAdapterOptions: (options) => void;
582
+ }
583
+ ```
584
+
585
+ ### Video Examples
586
+
587
+ ```typescript
588
+ // Upload video metadata
589
+ const video = await videoActions.add({
590
+ name: 'Tutorial Video',
591
+ description: 'Learn TypeScript basics',
592
+ url: 'https://cdn.example.com/videos/tutorial.mp4',
593
+ thumbnailUrl: 'https://cdn.example.com/thumbnails/tutorial.jpg',
594
+ duration: 600,
595
+ width: 1920,
596
+ height: 1080,
597
+ format: 'mp4',
598
+ size: 52428800 // 50MB in bytes
599
+ });
600
+
601
+ // Get video
602
+ const vid = await videoActions.itemById('video123', [
603
+ 'url',
604
+ 'thumbnailUrl',
605
+ 'duration',
606
+ 'user {username}'
607
+ ]);
608
+
609
+ // List videos
610
+ const videos = await videoActions.listByLatest(0, 20, [
611
+ 'name',
612
+ 'thumbnailUrl',
613
+ 'duration'
614
+ ]);
615
+
616
+ // Update video
617
+ await videoActions.update({
618
+ videoId: 'video123',
619
+ description: 'Updated description',
620
+ tags: ['tutorial', 'typescript'] // Extensible field
621
+ });
622
+
623
+ // Delete video
624
+ await videoActions.delete('video123');
625
+ ```
626
+
627
+ ## Images
628
+
629
+ Image content and metadata.
630
+
631
+ ### Image Fields
632
+
633
+ ```typescript
634
+ interface ImageType extends BaseDocument, ExtensibleFields {
635
+ alt?: string; // Alt text
636
+ description?: string; // Image description
637
+ format?: string; // Image format (jpg, png, webp, etc.)
638
+ height?: number; // Image height in pixels
639
+ imageId?: string; // Unique image identifier
640
+ name?: string; // Image name
641
+ size?: number; // File size in bytes
642
+ thumbUrl?: string; // Thumbnail URL
643
+ url?: string; // Image URL
644
+ userId?: string; // Owner user ID
645
+ width?: number; // Image width in pixels
646
+ }
647
+ ```
648
+
649
+ ### Image Actions
650
+
651
+ ```typescript
652
+ import {createImageActions} from '@nlabs/metropolisjs';
653
+
654
+ const imageActions = createImageActions(flux);
655
+
656
+ interface ImageActions {
657
+ add: (imageData, props?) => Promise<Image>;
658
+ itemById: (imageId, props?) => Promise<Image>;
659
+ listByLatest: (from?, to?, props?) => Promise<Image[]>;
660
+ delete: (imageId, props?) => Promise<Image>;
661
+ update: (imageData, props?) => Promise<Image>;
662
+ updateImageAdapter: (adapter) => void;
663
+ updateImageAdapterOptions: (options) => void;
664
+ }
665
+ ```
666
+
667
+ ### Image Examples
668
+
669
+ ```typescript
670
+ // Upload image metadata
671
+ const image = await imageActions.add({
672
+ name: 'Profile Picture',
673
+ alt: 'User profile photo',
674
+ url: 'https://cdn.example.com/images/profile.jpg',
675
+ thumbUrl: 'https://cdn.example.com/images/profile_thumb.jpg',
676
+ width: 1024,
677
+ height: 1024,
678
+ format: 'jpg',
679
+ size: 204800 // 200KB
680
+ });
681
+
682
+ // Get image
683
+ const img = await imageActions.itemById('image123', [
684
+ 'url',
685
+ 'thumbUrl',
686
+ 'width',
687
+ 'height'
688
+ ]);
689
+
690
+ // List images
691
+ const images = await imageActions.listByLatest(0, 20, [
692
+ 'name',
693
+ 'thumbUrl',
694
+ 'user {username}'
695
+ ]);
696
+
697
+ // Update image
698
+ await imageActions.update({
699
+ imageId: 'image123',
700
+ alt: 'Updated alt text',
701
+ tags: ['profile', 'avatar'] // Extensible field
702
+ });
703
+
704
+ // Delete image
705
+ await imageActions.delete('image123');
706
+ ```
707
+
708
+ ## Files
709
+
710
+ Generic file storage and metadata.
711
+
712
+ ### File Fields
713
+
714
+ ```typescript
715
+ interface FileType extends BaseDocument, ExtensibleFields {
716
+ description?: string; // File description
717
+ fileId?: string; // Unique file identifier
718
+ fileName?: string; // File name
719
+ fileType?: string; // MIME type
720
+ mimeType?: string; // MIME type (alternative)
721
+ name?: string; // Display name
722
+ size?: number; // File size in bytes
723
+ url?: string; // File URL
724
+ userId?: string; // Owner user ID
725
+ }
726
+ ```
727
+
728
+ ### File Examples
729
+
730
+ ```typescript
731
+ // Upload file metadata
732
+ const file = await fileActions.add({
733
+ fileName: 'document.pdf',
734
+ name: 'Project Proposal',
735
+ description: 'Q4 2024 proposal',
736
+ fileType: 'application/pdf',
737
+ url: 'https://cdn.example.com/files/proposal.pdf',
738
+ size: 1048576 // 1MB
739
+ });
740
+
741
+ // Get file
742
+ const f = await fileActions.itemById('file123', [
743
+ 'url',
744
+ 'fileName',
745
+ 'fileType',
746
+ 'size'
747
+ ]);
748
+
749
+ // List files
750
+ const files = await fileActions.listByLatest(0, 20);
751
+
752
+ // Update file
753
+ await fileActions.update({
754
+ fileId: 'file123',
755
+ description: 'Updated description'
756
+ });
757
+
758
+ // Delete file
759
+ await fileActions.delete('file123');
760
+ ```
761
+
762
+ ## Apps
763
+
764
+ Application integrations and third-party connections.
765
+
766
+ ### App Fields
767
+
768
+ ```typescript
769
+ interface AppType extends BaseDocument, ExtensibleFields {
770
+ appId?: string; // Unique app identifier
771
+ apiKey?: string; // API key
772
+ credentials?: Record<string, any>; // App credentials
773
+ description?: string; // App description
774
+ isActive?: boolean; // Active status
775
+ name?: string; // App name
776
+ settings?: Record<string, any>; // App settings
777
+ userId?: string; // Owner user ID
778
+ webhookUrl?: string; // Webhook URL
779
+ }
780
+ ```
781
+
782
+ ### App Examples
783
+
784
+ ```typescript
785
+ // Register app
786
+ const app = await appActions.add({
787
+ name: 'Slack Integration',
788
+ description: 'Connect with Slack workspace',
789
+ apiKey: 'sk_live_...',
790
+ webhookUrl: 'https://hooks.slack.com/services/...',
791
+ isActive: true,
792
+ settings: {
793
+ channel: '#general',
794
+ notifications: true
795
+ }
796
+ });
797
+
798
+ // Get app
799
+ const application = await appActions.itemById('app123', [
800
+ 'name',
801
+ 'isActive',
802
+ 'settings'
803
+ ]);
804
+
805
+ // List apps
806
+ const apps = await appActions.listByLatest(0, 20);
807
+
808
+ // Update app settings
809
+ await appActions.update({
810
+ appId: 'app123',
811
+ settings: {
812
+ channel: '#announcements',
813
+ notifications: false
814
+ }
815
+ });
816
+
817
+ // Delete app
818
+ await appActions.delete('app123');
819
+ ```
820
+
821
+ ## Personas
822
+
823
+ Extended user personas with additional information.
824
+
825
+ ### Persona Fields
826
+
827
+ ```typescript
828
+ interface PersonaType extends BaseDocument, ExtensibleFields {
829
+ bio?: string; // User biography
830
+ company?: string; // Company name
831
+ location?: string; // Location string
832
+ personaId?: string; // Unique persona identifier
833
+ social?: Record<string, string>; // Social media links
834
+ title?: string; // Job title
835
+ userId?: string; // Associated user ID
836
+ website?: string; // Website URL
837
+ }
838
+ ```
839
+
840
+ ### Persona Examples
841
+
842
+ ```typescript
843
+ // Create persona
844
+ const persona = await personaActions.addPersona({
845
+ userId: 'user123',
846
+ bio: 'Software engineer passionate about web technologies',
847
+ title: 'Senior Developer',
848
+ company: 'Tech Corp',
849
+ location: 'San Francisco, CA',
850
+ website: 'https://example.com',
851
+ social: {
852
+ twitter: 'https://twitter.com/username',
853
+ linkedin: 'https://linkedin.com/in/username',
854
+ github: 'https://github.com/username'
855
+ }
856
+ });
857
+
858
+ // Get persona
859
+ const persona = await personaActions.getPersona('persona123');
860
+
861
+ // Update persona
862
+ await personaActions.updatePersona({
863
+ personaId: 'persona123',
864
+ bio: 'Updated bio',
865
+ title: 'Lead Developer'
866
+ });
867
+
868
+ // Delete persona
869
+ await personaActions.deletePersona('persona123');
870
+ ```
871
+
872
+ ## Tags
873
+
874
+ Categorization and organization tags.
875
+
876
+ ### Tag Fields
877
+
878
+ ```typescript
879
+ interface TagType extends BaseDocument, ExtensibleFields {
880
+ color?: string; // Tag color (hex)
881
+ description?: string; // Tag description
882
+ name?: string; // Tag name
883
+ tagId?: string; // Unique tag identifier
884
+ usageCount?: number; // Number of times used
885
+ }
886
+ ```
887
+
888
+ ### Tag Examples
889
+
890
+ ```typescript
891
+ // Create tag
892
+ const tag = await tagActions.add({
893
+ name: 'javascript',
894
+ description: 'JavaScript programming language',
895
+ color: '#f7df1e'
896
+ });
897
+
898
+ // Get tag
899
+ const t = await tagActions.itemById('tag123', [
900
+ 'usageCount'
901
+ ]);
902
+
903
+ // List tags
904
+ const tags = await tagActions.listByLatest(0, 50);
905
+
906
+ // Update tag
907
+ await tagActions.update({
908
+ tagId: 'tag123',
909
+ description: 'Updated description'
910
+ });
911
+
912
+ // Delete tag
913
+ await tagActions.delete('tag123');
914
+ ```
915
+
916
+ ## Content
917
+
918
+ CMS content and localized strings.
919
+
920
+ ### Content Fields
921
+
922
+ ```typescript
923
+ interface ContentType extends BaseDocument, ExtensibleFields {
924
+ category?: string; // Content category
925
+ content?: string; // Content body
926
+ contentId?: string; // Unique content identifier
927
+ description?: string; // Content description
928
+ isActive?: boolean; // Active status
929
+ key?: string; // Content key (unique per locale)
930
+ locale?: string; // Locale (e.g., 'en', 'es', 'fr')
931
+ }
932
+ ```
933
+
934
+ ### Content Actions
935
+
936
+ ```typescript
937
+ import {createContentActions} from '@nlabs/metropolisjs';
938
+
939
+ const contentActions = createContentActions(flux);
940
+
941
+ interface ContentActions {
942
+ add: (contentData, props?) => Promise<Content>;
943
+ itemById: (contentId, props?) => Promise<Content>;
944
+ itemByKey: (key, locale?, props?) => Promise<Content>;
945
+ listByCategory: (category, props?) => Promise<Content[]>;
946
+ list: (props?) => Promise<Content[]>;
947
+ delete: (contentId, props?) => Promise<Content>;
948
+ update: (contentData, props?) => Promise<Content>;
949
+ updateContentAdapter: (adapter) => void;
950
+ updateContentAdapterOptions: (options) => void;
951
+ }
952
+ ```
953
+
954
+ ### Content Examples
955
+
956
+ ```typescript
957
+ // Create content
958
+ const content = await contentActions.add({
959
+ key: 'welcome_message',
960
+ locale: 'en',
961
+ content: 'Welcome to our platform!',
962
+ category: 'onboarding',
963
+ description: 'Welcome message for new users',
964
+ isActive: true
965
+ });
966
+
967
+ // Create localized content
968
+ const spanishContent = await contentActions.add({
969
+ key: 'welcome_message',
970
+ locale: 'es',
971
+ content: '¡Bienvenido a nuestra plataforma!',
972
+ category: 'onboarding',
973
+ isActive: true
974
+ });
975
+
976
+ // Get content by key
977
+ const welcomeMsg = await contentActions.itemByKey('welcome_message', 'en');
978
+
979
+ // Get content by ID
980
+ const contentById = await contentActions.itemById('content123');
981
+
982
+ // List by category
983
+ const onboardingContent = await contentActions.listByCategory('onboarding', [
984
+ 'key',
985
+ 'locale',
986
+ 'content'
987
+ ]);
988
+
989
+ // List all content
990
+ const allContent = await contentActions.list(['key', 'locale', 'category']);
991
+
992
+ // Update content
993
+ await contentActions.update({
994
+ contentId: 'content123',
995
+ content: 'Updated welcome message'
996
+ });
997
+
998
+ // Delete content
999
+ await contentActions.delete('content123');
1000
+ ```
1001
+
1002
+ ## Best Practices by Collection
1003
+
1004
+ ### Posts
1005
+ - Always include `tags` and `user` relations when listing
1006
+ - Use location queries for location-based features
1007
+ - Implement pagination for large lists
1008
+ - Use `parentId` for comment threading
1009
+
1010
+ ### Groups
1011
+ - Store group permissions in `settings`
1012
+ - Use `memberCount` for display purposes
1013
+ - Implement connection checks for private groups
1014
+ - Use extensible fields for group-specific features
1015
+
1016
+ ### Messages
1017
+ - Always include `conversationId`
1018
+ - Load messages in batches (pagination)
1019
+ - Use `parentId` for message threads
1020
+ - Store read receipts in extensible fields
1021
+
1022
+ ### Videos/Images/Files
1023
+ - Store CDN URLs, not binary data
1024
+ - Include dimensions for responsive layouts
1025
+ - Use thumbnails for list views
1026
+ - Validate file types and sizes client-side
1027
+
1028
+ ### Users
1029
+ - Never expose sensitive fields (passwords, tokens)
1030
+ - Use separate profile collection for extended data
1031
+ - Implement proper authentication checks
1032
+ - Store preferences in extensible fields
1033
+
1034
+ ## Next Steps
1035
+
1036
+ - [CRUD Integration Guide](./CRUD_INTEGRATION.md) - Learn CRUD patterns
1037
+ - [Connections Guide](./CONNECTIONS.md) - Manage relationships
1038
+ - [MetropolisJS Documentation](../README.md) - Main library docs