@nlabs/metropolisjs 0.1.2 → 0.2.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.
- package/.github/copilot-instructions.md +167 -0
- package/AGENTS.md +13 -0
- package/CHANGELOG.md +112 -0
- package/GRAPHQL_VALIDATION_RESULTS.md +158 -0
- package/PERMISSION_GRAPHQL_INTEGRATION.md +293 -0
- package/PERMISSION_IMPLEMENTATION_SUMMARY.md +243 -0
- package/README.md +1123 -112
- package/SIGNIN_GRAPHQL_VALIDATION.md +125 -0
- package/VAULT_GRAPHQL_API_FINDINGS.md +312 -0
- package/docs/ACTIONS.md +63 -0
- package/docs/COLLECTIONS.md +1038 -0
- package/docs/CONNECTIONS.md +1367 -0
- package/docs/CRUD_INTEGRATION.md +702 -0
- package/examples/connections-usage.tsx +909 -0
- package/examples/content-actions-usage.ts +144 -0
- package/examples/crud-usage.tsx +847 -0
- package/examples/extensibility-usage.tsx +889 -0
- package/examples/i18n-import-examples.ts +86 -0
- package/examples/i18n-namespace-usage.ts +118 -0
- package/examples/i18next-singleton-demo.ts +187 -0
- package/examples/permission-system-usage.tsx +415 -0
- package/examples/project-details.tsx +397 -0
- package/examples/shared-i18n-usage.tsx +203 -0
- package/examples/signup-error-handling.ts +100 -0
- package/examples/translation-types.ts +86 -0
- package/examples/translation-usage.tsx +336 -0
- package/index.js +1 -0
- package/jest.config.mjs +28 -0
- package/lex.config.mjs +11 -2
- package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts +22 -0
- package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts.map +1 -0
- package/lib/__tests__/e2e/helpers/testGraphQLServer.js +197 -0
- package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts +3 -0
- package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts.map +1 -0
- package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.js +52 -0
- package/lib/actions/appActions/appActions.d.ts +29 -0
- package/lib/actions/appActions/appActions.d.ts.map +1 -0
- package/lib/actions/appActions/appActions.js +159 -0
- package/lib/actions/connectionActions/connectionActions.d.ts +19 -0
- package/lib/actions/connectionActions/connectionActions.d.ts.map +1 -0
- package/lib/actions/connectionActions/connectionActions.js +131 -0
- package/lib/actions/contentActions/contentActions.d.ts +34 -0
- package/lib/actions/contentActions/contentActions.d.ts.map +1 -0
- package/lib/actions/contentActions/contentActions.js +314 -0
- package/lib/actions/conversationActions/conversationActions.d.ts +30 -0
- package/lib/actions/conversationActions/conversationActions.d.ts.map +1 -0
- package/lib/actions/conversationActions/conversationActions.js +225 -0
- package/lib/actions/eventActions/eventActions.d.ts +27 -7
- package/lib/actions/eventActions/eventActions.d.ts.map +1 -0
- package/lib/actions/eventActions/eventActions.js +436 -2
- package/lib/actions/groupActions/groupActions.d.ts +30 -0
- package/lib/actions/groupActions/groupActions.d.ts.map +1 -0
- package/lib/actions/groupActions/groupActions.js +229 -0
- package/lib/actions/imageActions/imageActions.d.ts +16 -10
- package/lib/actions/imageActions/imageActions.d.ts.map +1 -0
- package/lib/actions/imageActions/imageActions.js +593 -2
- package/lib/actions/index.d.ts +21 -9
- package/lib/actions/index.d.ts.map +1 -0
- package/lib/actions/index.js +22 -2
- package/lib/actions/locationActions/locationActions.d.ts +11 -9
- package/lib/actions/locationActions/locationActions.d.ts.map +1 -0
- package/lib/actions/locationActions/locationActions.js +388 -2
- package/lib/actions/messageActions/messageActions.d.ts +16 -32
- package/lib/actions/messageActions/messageActions.d.ts.map +1 -0
- package/lib/actions/messageActions/messageActions.js +235 -2
- package/lib/actions/permissionActions/permissionActions.d.ts +34 -0
- package/lib/actions/permissionActions/permissionActions.d.ts.map +1 -0
- package/lib/actions/permissionActions/permissionActions.js +330 -0
- package/lib/actions/personaActions/personaActions.d.ts +65 -0
- package/lib/actions/personaActions/personaActions.d.ts.map +1 -0
- package/lib/actions/personaActions/personaActions.js +572 -0
- package/lib/actions/postActions/postActions.d.ts +12 -32
- package/lib/actions/postActions/postActions.d.ts.map +1 -0
- package/lib/actions/postActions/postActions.js +447 -2
- package/lib/actions/reactionActions/reactionActions.d.ts +13 -27
- package/lib/actions/reactionActions/reactionActions.d.ts.map +1 -0
- package/lib/actions/reactionActions/reactionActions.js +413 -2
- package/lib/actions/sseActions/sseActions.d.ts +1 -0
- package/lib/actions/sseActions/sseActions.d.ts.map +1 -0
- package/lib/actions/sseActions/sseActions.js +148 -2
- package/lib/actions/subscriptionActions/subscriptionActions.d.ts +24 -0
- package/lib/actions/subscriptionActions/subscriptionActions.d.ts.map +1 -0
- package/lib/actions/subscriptionActions/subscriptionActions.js +329 -0
- package/lib/actions/tagActions/tagActions.d.ts +13 -31
- package/lib/actions/tagActions/tagActions.d.ts.map +1 -0
- package/lib/actions/tagActions/tagActions.js +347 -2
- package/lib/actions/translationActions/translationActions.d.ts +38 -0
- package/lib/actions/translationActions/translationActions.d.ts.map +1 -0
- package/lib/actions/translationActions/translationActions.js +189 -0
- package/lib/actions/userActions/userActions.d.ts +42 -95
- package/lib/actions/userActions/userActions.d.ts.map +1 -0
- package/lib/actions/userActions/userActions.js +844 -2
- package/lib/actions/videoActions/videoActions.d.ts +41 -0
- package/lib/actions/videoActions/videoActions.d.ts.map +1 -0
- package/lib/actions/videoActions/videoActions.js +532 -0
- package/lib/actions/websocketActions/websocketActions.d.ts +20 -21
- package/lib/actions/websocketActions/websocketActions.d.ts.map +1 -0
- package/lib/actions/websocketActions/websocketActions.js +377 -2
- package/lib/adapters/appAdapter/appAdapter.d.ts +8 -0
- package/lib/adapters/appAdapter/appAdapter.d.ts.map +1 -0
- package/lib/adapters/appAdapter/appAdapter.js +90 -0
- package/lib/adapters/arangoAdapter/arangoAdapter.d.ts +3 -2
- package/lib/adapters/arangoAdapter/arangoAdapter.d.ts.map +1 -0
- package/lib/adapters/arangoAdapter/arangoAdapter.js +75 -2
- package/lib/adapters/contentAdapter/contentAdapter.d.ts +3 -2
- package/lib/adapters/contentAdapter/contentAdapter.d.ts.map +1 -0
- package/lib/adapters/contentAdapter/contentAdapter.js +107 -2
- package/lib/adapters/conversationAdapter/conversationAdapter.d.ts +3 -2
- package/lib/adapters/conversationAdapter/conversationAdapter.d.ts.map +1 -0
- package/lib/adapters/conversationAdapter/conversationAdapter.js +75 -2
- package/lib/adapters/eventAdapter/eventAdapter.d.ts +5 -2
- package/lib/adapters/eventAdapter/eventAdapter.d.ts.map +1 -0
- package/lib/adapters/eventAdapter/eventAdapter.js +162 -2
- package/lib/adapters/fileAdapter/fileAdapter.d.ts +3 -2
- package/lib/adapters/fileAdapter/fileAdapter.d.ts.map +1 -0
- package/lib/adapters/fileAdapter/fileAdapter.js +118 -2
- package/lib/adapters/groupAdapter/groupAdapter.d.ts +28 -0
- package/lib/adapters/groupAdapter/groupAdapter.d.ts.map +1 -0
- package/lib/adapters/groupAdapter/groupAdapter.js +66 -0
- package/lib/adapters/imageAdapter/imageAdapter.d.ts +9 -2
- package/lib/adapters/imageAdapter/imageAdapter.d.ts.map +1 -0
- package/lib/adapters/imageAdapter/imageAdapter.js +134 -2
- package/lib/adapters/index.d.ts +34 -16
- package/lib/adapters/index.d.ts.map +1 -0
- package/lib/adapters/index.js +19 -2
- package/lib/adapters/locationAdapter/locationAdapter.d.ts +3 -2
- package/lib/adapters/locationAdapter/locationAdapter.d.ts.map +1 -0
- package/lib/adapters/locationAdapter/locationAdapter.js +95 -2
- package/lib/adapters/messageAdapter/messageAdapter.d.ts +23 -19
- package/lib/adapters/messageAdapter/messageAdapter.d.ts.map +1 -0
- package/lib/adapters/messageAdapter/messageAdapter.js +82 -2
- package/lib/adapters/permissionAdapter/permissionAdapter.d.ts +41 -0
- package/lib/adapters/permissionAdapter/permissionAdapter.d.ts.map +1 -0
- package/lib/adapters/permissionAdapter/permissionAdapter.js +120 -0
- package/lib/adapters/personaAdapter/personaAdapter.d.ts +28 -2
- package/lib/adapters/personaAdapter/personaAdapter.d.ts.map +1 -0
- package/lib/adapters/personaAdapter/personaAdapter.js +161 -2
- package/lib/adapters/postAdapter/postAdapter.d.ts +3 -2
- package/lib/adapters/postAdapter/postAdapter.d.ts.map +1 -0
- package/lib/adapters/postAdapter/postAdapter.js +115 -2
- package/lib/adapters/reactionAdapter/reactionAdapter.d.ts +5 -2
- package/lib/adapters/reactionAdapter/reactionAdapter.d.ts.map +1 -0
- package/lib/adapters/reactionAdapter/reactionAdapter.js +81 -2
- package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts +3 -2
- package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts.map +1 -0
- package/lib/adapters/reaktorAdapter/reaktorAdapter.js +58 -2
- package/lib/adapters/sessionAdapter/sessionAdapter.d.ts +3 -2
- package/lib/adapters/sessionAdapter/sessionAdapter.d.ts.map +1 -0
- package/lib/adapters/sessionAdapter/sessionAdapter.js +80 -2
- package/lib/adapters/tagAdapter/tagAdapter.d.ts +3 -2
- package/lib/adapters/tagAdapter/tagAdapter.d.ts.map +1 -0
- package/lib/adapters/tagAdapter/tagAdapter.js +98 -2
- package/lib/adapters/translationAdapter/translationAdapter.d.ts +21 -0
- package/lib/adapters/translationAdapter/translationAdapter.d.ts.map +1 -0
- package/lib/adapters/translationAdapter/translationAdapter.js +55 -0
- package/lib/adapters/userAdapter/userAdapter.d.ts +18 -6
- package/lib/adapters/userAdapter/userAdapter.d.ts.map +1 -0
- package/lib/adapters/userAdapter/userAdapter.js +302 -2
- package/lib/adapters/videoAdapter/videoAdapter.d.ts +8 -0
- package/lib/adapters/videoAdapter/videoAdapter.d.ts.map +1 -0
- package/lib/adapters/videoAdapter/videoAdapter.js +194 -0
- package/lib/config/index.d.ts +19 -6
- package/lib/config/index.d.ts.map +1 -0
- package/lib/config/index.js +97 -2
- package/lib/constants/Collections.d.ts +44 -0
- package/lib/constants/Collections.d.ts.map +1 -0
- package/lib/constants/Collections.js +40 -0
- package/lib/constants/MetropolisConstants.d.ts +1 -0
- package/lib/constants/MetropolisConstants.d.ts.map +1 -0
- package/lib/constants/MetropolisConstants.js +15 -2
- package/lib/graphql/message.d.ts +1 -0
- package/lib/graphql/message.d.ts.map +1 -0
- package/lib/graphql/message.js +6 -4
- package/lib/graphql/notification.d.ts +1 -0
- package/lib/graphql/notification.d.ts.map +1 -0
- package/lib/graphql/notification.js +6 -4
- package/lib/graphql/session.d.ts +1 -0
- package/lib/graphql/session.d.ts.map +1 -0
- package/lib/graphql/session.js +4 -3
- package/lib/index.d.ts +45 -22
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +248 -2
- package/lib/stores/appStore.d.ts +1 -0
- package/lib/stores/appStore.d.ts.map +1 -0
- package/lib/stores/appStore.js +23 -2
- package/lib/stores/contentStore.d.ts +36 -0
- package/lib/stores/contentStore.d.ts.map +1 -0
- package/lib/stores/contentStore.js +139 -0
- package/lib/stores/conversationStore.d.ts +38 -0
- package/lib/stores/conversationStore.d.ts.map +1 -0
- package/lib/stores/conversationStore.js +117 -0
- package/lib/stores/eventStore.d.ts +4 -1
- package/lib/stores/eventStore.d.ts.map +1 -0
- package/lib/stores/eventStore.js +47 -2
- package/lib/stores/groupStore.d.ts +37 -0
- package/lib/stores/groupStore.d.ts.map +1 -0
- package/lib/stores/groupStore.js +68 -0
- package/lib/stores/imageStore.d.ts +6 -1
- package/lib/stores/imageStore.d.ts.map +1 -0
- package/lib/stores/imageStore.js +53 -2
- package/lib/stores/index.d.ts +20 -11
- package/lib/stores/index.d.ts.map +1 -0
- package/lib/stores/index.js +24 -2
- package/lib/stores/locationStore.d.ts +2 -1
- package/lib/stores/locationStore.d.ts.map +1 -0
- package/lib/stores/locationStore.js +42 -2
- package/lib/stores/messageStore.d.ts +19 -4
- package/lib/stores/messageStore.d.ts.map +1 -0
- package/lib/stores/messageStore.js +137 -2
- package/lib/stores/notificationStore.d.ts +33 -0
- package/lib/stores/notificationStore.d.ts.map +1 -0
- package/lib/stores/notificationStore.js +55 -0
- package/lib/stores/permissionStore.d.ts +37 -0
- package/lib/stores/permissionStore.d.ts.map +1 -0
- package/lib/stores/permissionStore.js +117 -0
- package/lib/stores/personaStore.d.ts +26 -0
- package/lib/stores/personaStore.d.ts.map +1 -0
- package/lib/stores/personaStore.js +118 -0
- package/lib/stores/postStore.d.ts +2 -1
- package/lib/stores/postStore.d.ts.map +1 -0
- package/lib/stores/postStore.js +53 -2
- package/lib/stores/reactionStore.d.ts +1 -0
- package/lib/stores/reactionStore.d.ts.map +1 -0
- package/lib/stores/reactionStore.js +28 -2
- package/lib/stores/subscriptionStore.d.ts +41 -0
- package/lib/stores/subscriptionStore.d.ts.map +1 -0
- package/lib/stores/subscriptionStore.js +85 -0
- package/lib/stores/tagStore.d.ts +8 -5
- package/lib/stores/tagStore.d.ts.map +1 -0
- package/lib/stores/tagStore.js +87 -2
- package/lib/stores/translationStore.d.ts +42 -0
- package/lib/stores/translationStore.d.ts.map +1 -0
- package/lib/stores/translationStore.js +122 -0
- package/lib/stores/userStore.d.ts +5 -4
- package/lib/stores/userStore.d.ts.map +1 -0
- package/lib/stores/userStore.js +319 -2
- package/lib/stores/videoStore.d.ts +39 -0
- package/lib/stores/videoStore.d.ts.map +1 -0
- package/lib/stores/videoStore.js +132 -0
- package/lib/stores/websocketStore.d.ts +1 -0
- package/lib/stores/websocketStore.d.ts.map +1 -0
- package/lib/stores/websocketStore.js +51 -2
- package/lib/types/apps.types.d.ts +17 -0
- package/lib/types/apps.types.d.ts.map +1 -0
- package/lib/types/apps.types.js +6 -0
- package/lib/types/common.types.d.ts +31 -0
- package/lib/types/common.types.d.ts.map +1 -0
- package/lib/types/common.types.js +6 -0
- package/lib/types/conversations.types.d.ts +17 -0
- package/lib/types/conversations.types.d.ts.map +1 -0
- package/lib/types/conversations.types.js +6 -0
- package/lib/types/edges.types.d.ts +38 -0
- package/lib/types/edges.types.d.ts.map +1 -0
- package/lib/types/edges.types.js +6 -0
- package/lib/types/groups.types.d.ts +19 -0
- package/lib/types/groups.types.d.ts.map +1 -0
- package/lib/types/groups.types.js +6 -0
- package/lib/types/index.d.ts +12 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +12 -0
- package/lib/types/subscriptions.types.d.ts +32 -0
- package/lib/types/subscriptions.types.d.ts.map +1 -0
- package/lib/types/subscriptions.types.js +6 -0
- package/lib/types/videos.types.d.ts +61 -0
- package/lib/types/videos.types.d.ts.map +1 -0
- package/lib/types/videos.types.js +6 -0
- package/lib/utils/MetropolisProvider.d.ts +39 -15
- package/lib/utils/MetropolisProvider.d.ts.map +1 -0
- package/lib/utils/MetropolisProvider.js +31 -2
- package/lib/utils/actionFactory.d.ts +21 -19
- package/lib/utils/actionFactory.d.ts.map +1 -0
- package/lib/utils/actionFactory.js +95 -2
- package/lib/utils/api.d.ts +5 -4
- package/lib/utils/api.d.ts.map +1 -0
- package/lib/utils/api.js +252 -6
- package/lib/utils/app.d.ts +1 -0
- package/lib/utils/app.d.ts.map +1 -0
- package/lib/utils/app.js +15 -2
- package/lib/utils/baseActionFactory.d.ts +5 -23
- package/lib/utils/baseActionFactory.d.ts.map +1 -0
- package/lib/utils/baseActionFactory.js +72 -2
- package/lib/utils/configUtils.d.ts +11 -0
- package/lib/utils/configUtils.d.ts.map +1 -0
- package/lib/utils/configUtils.js +20 -0
- package/lib/utils/dateUtils.d.ts +1 -0
- package/lib/utils/dateUtils.d.ts.map +1 -0
- package/lib/utils/dateUtils.js +11 -2
- package/lib/utils/file.d.ts +3 -1
- package/lib/utils/file.d.ts.map +1 -0
- package/lib/utils/file.js +156 -2
- package/lib/utils/i18n.d.ts +7 -0
- package/lib/utils/i18n.d.ts.map +1 -0
- package/lib/utils/i18n.js +96 -0
- package/lib/utils/index.d.ts +20 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/index.js +26 -0
- package/lib/utils/location.d.ts +4 -3
- package/lib/utils/location.d.ts.map +1 -0
- package/lib/utils/location.js +82 -2
- package/lib/utils/permissionUtils.d.ts +22 -0
- package/lib/utils/permissionUtils.d.ts.map +1 -0
- package/lib/utils/permissionUtils.js +72 -0
- package/lib/utils/requestCache.d.ts +8 -0
- package/lib/utils/requestCache.d.ts.map +1 -0
- package/lib/utils/requestCache.js +53 -0
- package/lib/utils/session.d.ts +14 -0
- package/lib/utils/session.d.ts.map +1 -0
- package/lib/utils/session.js +107 -0
- package/lib/utils/useConversationTyping.d.ts +26 -0
- package/lib/utils/useConversationTyping.d.ts.map +1 -0
- package/lib/utils/useConversationTyping.js +117 -0
- package/lib/utils/useMetropolis.d.ts +67 -12
- package/lib/utils/useMetropolis.d.ts.map +1 -0
- package/lib/utils/useMetropolis.js +311 -2
- package/lib/utils/useTranslations.d.ts +16 -0
- package/lib/utils/useTranslations.d.ts.map +1 -0
- package/lib/utils/useTranslations.js +105 -0
- package/lib/utils/validatorFactory.d.ts +3 -2
- package/lib/utils/validatorFactory.d.ts.map +1 -0
- package/lib/utils/validatorFactory.js +95 -2
- package/package.json +58 -17
- package/temp_signin.ts +73 -0
- package/lib/actions/profileActions/profileActions.d.ts +0 -50
- package/lib/actions/profileActions/profileActions.js +0 -2
- package/lib/adapters/profileAdapter/profileAdapter.d.ts +0 -32
- package/lib/adapters/profileAdapter/profileAdapter.js +0 -2
- package/lib/stores/profileStore.d.ts +0 -24
- package/lib/stores/profileStore.js +0 -2
- /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
|