@nlabs/metropolisjs 0.1.1 → 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 +1343 -0
- 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/factory-pattern-usage.ts +283 -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/factoryPatternGuide.md +244 -0
- package/index.js +1 -0
- package/jest.config.mjs +28 -0
- package/lex.config.mjs +26 -0
- 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 +65 -0
- package/lib/actions/eventActions/eventActions.d.ts.map +1 -0
- package/lib/actions/eventActions/eventActions.js +436 -0
- 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 +62 -0
- package/lib/actions/imageActions/imageActions.d.ts.map +1 -0
- package/lib/actions/imageActions/imageActions.js +593 -0
- package/lib/actions/index.d.ts +21 -0
- package/lib/actions/index.d.ts.map +1 -0
- package/lib/actions/index.js +22 -0
- package/lib/actions/locationActions/locationActions.d.ts +60 -0
- package/lib/actions/locationActions/locationActions.d.ts.map +1 -0
- package/lib/actions/locationActions/locationActions.js +388 -0
- package/lib/actions/messageActions/messageActions.d.ts +38 -0
- package/lib/actions/messageActions/messageActions.d.ts.map +1 -0
- package/lib/actions/messageActions/messageActions.js +235 -0
- 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 +36 -0
- package/lib/actions/postActions/postActions.d.ts.map +1 -0
- package/lib/actions/postActions/postActions.js +447 -0
- package/lib/actions/reactionActions/reactionActions.d.ts +38 -0
- package/lib/actions/reactionActions/reactionActions.d.ts.map +1 -0
- package/lib/actions/reactionActions/reactionActions.js +413 -0
- package/lib/actions/sseActions/sseActions.d.ts +38 -0
- package/lib/actions/sseActions/sseActions.d.ts.map +1 -0
- package/lib/actions/sseActions/sseActions.js +148 -0
- 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 +37 -0
- package/lib/actions/tagActions/tagActions.d.ts.map +1 -0
- package/lib/actions/tagActions/tagActions.js +347 -0
- 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 +78 -0
- package/lib/actions/userActions/userActions.d.ts.map +1 -0
- package/lib/actions/userActions/userActions.js +844 -0
- 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 +30 -0
- package/lib/actions/websocketActions/websocketActions.d.ts.map +1 -0
- package/lib/actions/websocketActions/websocketActions.js +377 -0
- 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 +21 -0
- package/lib/adapters/arangoAdapter/arangoAdapter.d.ts.map +1 -0
- package/lib/adapters/arangoAdapter/arangoAdapter.js +75 -0
- package/lib/adapters/contentAdapter/contentAdapter.d.ts +32 -0
- package/lib/adapters/contentAdapter/contentAdapter.d.ts.map +1 -0
- package/lib/adapters/contentAdapter/contentAdapter.js +107 -0
- package/lib/adapters/conversationAdapter/conversationAdapter.d.ts +24 -0
- package/lib/adapters/conversationAdapter/conversationAdapter.d.ts.map +1 -0
- package/lib/adapters/conversationAdapter/conversationAdapter.js +75 -0
- package/lib/adapters/eventAdapter/eventAdapter.d.ts +46 -0
- package/lib/adapters/eventAdapter/eventAdapter.d.ts.map +1 -0
- package/lib/adapters/eventAdapter/eventAdapter.js +162 -0
- package/lib/adapters/fileAdapter/fileAdapter.d.ts +30 -0
- package/lib/adapters/fileAdapter/fileAdapter.d.ts.map +1 -0
- package/lib/adapters/fileAdapter/fileAdapter.js +118 -0
- 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 +38 -0
- package/lib/adapters/imageAdapter/imageAdapter.d.ts.map +1 -0
- package/lib/adapters/imageAdapter/imageAdapter.js +134 -0
- package/lib/adapters/index.d.ts +34 -0
- package/lib/adapters/index.d.ts.map +1 -0
- package/lib/adapters/index.js +19 -0
- package/lib/adapters/locationAdapter/locationAdapter.d.ts +28 -0
- package/lib/adapters/locationAdapter/locationAdapter.d.ts.map +1 -0
- package/lib/adapters/locationAdapter/locationAdapter.js +95 -0
- package/lib/adapters/messageAdapter/messageAdapter.d.ts +31 -0
- package/lib/adapters/messageAdapter/messageAdapter.d.ts.map +1 -0
- package/lib/adapters/messageAdapter/messageAdapter.js +82 -0
- 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 +44 -0
- package/lib/adapters/personaAdapter/personaAdapter.d.ts.map +1 -0
- package/lib/adapters/personaAdapter/personaAdapter.js +161 -0
- package/lib/adapters/postAdapter/postAdapter.d.ts +33 -0
- package/lib/adapters/postAdapter/postAdapter.d.ts.map +1 -0
- package/lib/adapters/postAdapter/postAdapter.js +115 -0
- package/lib/adapters/reactionAdapter/reactionAdapter.d.ts +23 -0
- package/lib/adapters/reactionAdapter/reactionAdapter.d.ts.map +1 -0
- package/lib/adapters/reactionAdapter/reactionAdapter.js +81 -0
- package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts +17 -0
- package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts.map +1 -0
- package/lib/adapters/reaktorAdapter/reaktorAdapter.js +58 -0
- package/lib/adapters/sessionAdapter/sessionAdapter.d.ts +24 -0
- package/lib/adapters/sessionAdapter/sessionAdapter.d.ts.map +1 -0
- package/lib/adapters/sessionAdapter/sessionAdapter.js +80 -0
- package/lib/adapters/tagAdapter/tagAdapter.d.ts +21 -0
- package/lib/adapters/tagAdapter/tagAdapter.d.ts.map +1 -0
- package/lib/adapters/tagAdapter/tagAdapter.js +98 -0
- 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 +67 -0
- package/lib/adapters/userAdapter/userAdapter.d.ts.map +1 -0
- package/lib/adapters/userAdapter/userAdapter.js +302 -0
- 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 +44 -0
- package/lib/config/index.d.ts.map +1 -0
- package/lib/config/index.js +97 -0
- 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 +15 -0
- package/lib/constants/MetropolisConstants.d.ts.map +1 -0
- package/lib/constants/MetropolisConstants.js +15 -0
- package/lib/graphql/message.d.ts +3 -0
- package/lib/graphql/message.d.ts.map +1 -0
- package/lib/graphql/message.js +20 -0
- package/lib/graphql/notification.d.ts +3 -0
- package/lib/graphql/notification.d.ts.map +1 -0
- package/lib/graphql/notification.js +20 -0
- package/lib/graphql/session.d.ts +2 -0
- package/lib/graphql/session.d.ts.map +1 -0
- package/lib/graphql/session.js +17 -0
- package/lib/index.d.ts +52 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +248 -0
- package/lib/stores/appStore.d.ts +23 -0
- package/lib/stores/appStore.d.ts.map +1 -0
- package/lib/stores/appStore.js +23 -0
- 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 +37 -0
- package/lib/stores/eventStore.d.ts.map +1 -0
- package/lib/stores/eventStore.js +47 -0
- 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 +40 -0
- package/lib/stores/imageStore.d.ts.map +1 -0
- package/lib/stores/imageStore.js +53 -0
- package/lib/stores/index.d.ts +24 -0
- package/lib/stores/index.d.ts.map +1 -0
- package/lib/stores/index.js +24 -0
- package/lib/stores/locationStore.d.ts +34 -0
- package/lib/stores/locationStore.d.ts.map +1 -0
- package/lib/stores/locationStore.js +42 -0
- package/lib/stores/messageStore.d.ts +51 -0
- package/lib/stores/messageStore.d.ts.map +1 -0
- package/lib/stores/messageStore.js +137 -0
- 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 +34 -0
- package/lib/stores/postStore.d.ts.map +1 -0
- package/lib/stores/postStore.js +53 -0
- package/lib/stores/reactionStore.d.ts +25 -0
- package/lib/stores/reactionStore.d.ts.map +1 -0
- package/lib/stores/reactionStore.js +28 -0
- 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 +34 -0
- package/lib/stores/tagStore.d.ts.map +1 -0
- package/lib/stores/tagStore.js +87 -0
- 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 +74 -0
- package/lib/stores/userStore.d.ts.map +1 -0
- package/lib/stores/userStore.js +319 -0
- 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 +24 -0
- package/lib/stores/websocketStore.d.ts.map +1 -0
- package/lib/stores/websocketStore.js +51 -0
- 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 +58 -0
- package/lib/utils/MetropolisProvider.d.ts.map +1 -0
- package/lib/utils/MetropolisProvider.js +31 -0
- package/lib/utils/actionFactory.d.ts +24 -0
- package/lib/utils/actionFactory.d.ts.map +1 -0
- package/lib/utils/actionFactory.js +95 -0
- package/lib/utils/api.d.ts +44 -0
- package/lib/utils/api.d.ts.map +1 -0
- package/lib/utils/api.js +253 -0
- package/lib/utils/app.d.ts +7 -0
- package/lib/utils/app.d.ts.map +1 -0
- package/lib/utils/app.js +15 -0
- package/lib/utils/baseActionFactory.d.ts +16 -0
- package/lib/utils/baseActionFactory.d.ts.map +1 -0
- package/lib/utils/baseActionFactory.js +72 -0
- 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 +3 -0
- package/lib/utils/dateUtils.d.ts.map +1 -0
- package/lib/utils/dateUtils.js +11 -0
- package/lib/utils/file.d.ts +3 -0
- package/lib/utils/file.d.ts.map +1 -0
- package/lib/utils/file.js +156 -0
- 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 +10 -0
- package/lib/utils/location.d.ts.map +1 -0
- package/lib/utils/location.js +82 -0
- 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 -0
- package/lib/utils/useMetropolis.d.ts.map +1 -0
- package/lib/utils/useMetropolis.js +311 -0
- 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 +49 -0
- package/lib/utils/validatorFactory.d.ts.map +1 -0
- package/lib/utils/validatorFactory.js +95 -0
- package/package.json +75 -28
- package/temp_signin.ts +73 -0
- package/tsconfig.lint.json +25 -0
- package/tsconfig.test.json +14 -0
|
@@ -0,0 +1,702 @@
|
|
|
1
|
+
# MetropolisJS CRUD Integration Guide
|
|
2
|
+
|
|
3
|
+
This guide covers CRUD (Create, Read, Update, Delete) operations in MetropolisJS, including state management with ArkhamJS, extensible fields, and best practices.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Overview](#overview)
|
|
8
|
+
- [Basic Concepts](#basic-concepts)
|
|
9
|
+
- [CRUD Operations](#crud-operations)
|
|
10
|
+
- [Extensible Fields](#extensible-fields)
|
|
11
|
+
- [State Management](#state-management)
|
|
12
|
+
- [Error Handling](#error-handling)
|
|
13
|
+
- [Best Practices](#best-practices)
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
|
|
17
|
+
MetropolisJS provides a unified interface for performing CRUD operations on all collection types. Each collection follows consistent patterns through factory-based actions, Zod validation, and ArkhamJS state management.
|
|
18
|
+
|
|
19
|
+
### Available Collections
|
|
20
|
+
|
|
21
|
+
All collections are defined in `COLLECTIONS` constant:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import {COLLECTIONS} from '@nlabs/metropolisjs';
|
|
25
|
+
|
|
26
|
+
const {
|
|
27
|
+
APPS, // 'apps'
|
|
28
|
+
CONVERSATIONS, // 'conversations'
|
|
29
|
+
FILES, // 'files'
|
|
30
|
+
GROUPS, // 'groups'
|
|
31
|
+
IMAGES, // 'images'
|
|
32
|
+
MESSAGES, // 'messages'
|
|
33
|
+
POSTS, // 'posts'
|
|
34
|
+
PERSONAS, // 'personas'
|
|
35
|
+
TAGS, // 'tags'
|
|
36
|
+
USERS, // 'users'
|
|
37
|
+
VIDEOS // 'videos'
|
|
38
|
+
} = COLLECTIONS;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Basic Concepts
|
|
42
|
+
|
|
43
|
+
### Factory Pattern
|
|
44
|
+
|
|
45
|
+
All actions are created using factory functions:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import {Flux} from '@nlabs/arkhamjs';
|
|
49
|
+
import {createPostActions, createGroupActions, createUserActions} from '@nlabs/metropolisjs';
|
|
50
|
+
|
|
51
|
+
const flux = new Flux();
|
|
52
|
+
|
|
53
|
+
const postActions = createPostActions(flux);
|
|
54
|
+
const groupActions = createGroupActions(flux);
|
|
55
|
+
const userActions = createUserActions(flux);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Action Interface
|
|
59
|
+
|
|
60
|
+
Most collections provide standard CRUD methods:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
interface CollectionActions {
|
|
64
|
+
add: (data, props?) => Promise<Item>;
|
|
65
|
+
itemById: (id, props?) => Promise<Item>;
|
|
66
|
+
list: (filters?, props?) => Promise<Item[]>;
|
|
67
|
+
delete: (id, props?) => Promise<Item>;
|
|
68
|
+
update: (data, props?) => Promise<Item>;
|
|
69
|
+
updateAdapter: (adapter) => void;
|
|
70
|
+
updateAdapterOptions: (options) => void;
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Field Selection
|
|
75
|
+
|
|
76
|
+
All CRUD methods accept an optional `props` parameter to specify additional fields to retrieve:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const post = await postActions.itemById('post123', [
|
|
80
|
+
'viewCount',
|
|
81
|
+
'likeCount',
|
|
82
|
+
'comments {commentId, content, user {username}}'
|
|
83
|
+
]);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## CRUD Operations
|
|
87
|
+
|
|
88
|
+
### Create (Add)
|
|
89
|
+
|
|
90
|
+
Add new items to a collection:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// Add a post
|
|
94
|
+
const newPost = await postActions.add({
|
|
95
|
+
name: 'My First Post',
|
|
96
|
+
content: 'Hello, World!',
|
|
97
|
+
type: 'text',
|
|
98
|
+
tags: [{name: 'introduction'}]
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Add a group
|
|
102
|
+
const newGroup = await groupActions.add({
|
|
103
|
+
name: 'My Group',
|
|
104
|
+
description: 'A group for discussion',
|
|
105
|
+
isPrivate: false,
|
|
106
|
+
type: 'community'
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Add with extensible fields
|
|
110
|
+
const postWithMetadata = await postActions.add({
|
|
111
|
+
name: 'Custom Post',
|
|
112
|
+
content: 'Post with metadata',
|
|
113
|
+
metadata: {
|
|
114
|
+
priority: 'high',
|
|
115
|
+
category: 'announcement'
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Read (Retrieve)
|
|
121
|
+
|
|
122
|
+
Retrieve items by ID or using list methods:
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// Get single item by ID
|
|
126
|
+
const post = await postActions.itemById('post123', [
|
|
127
|
+
'tags {name, tagId}',
|
|
128
|
+
'user {username, imageUrl}'
|
|
129
|
+
]);
|
|
130
|
+
|
|
131
|
+
// List items with pagination
|
|
132
|
+
const recentPosts = await postActions.listByLatest(0, 20);
|
|
133
|
+
|
|
134
|
+
// List by location
|
|
135
|
+
const nearbyPosts = await postActions.listByLocation(
|
|
136
|
+
37.7749, // latitude
|
|
137
|
+
-122.4194, // longitude
|
|
138
|
+
0, // from
|
|
139
|
+
10 // to
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
// List by tags
|
|
143
|
+
const taggedPosts = await postActions.listByTags(
|
|
144
|
+
['technology', 'news'],
|
|
145
|
+
37.7749,
|
|
146
|
+
-122.4194,
|
|
147
|
+
0,
|
|
148
|
+
10
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
// List by reactions
|
|
152
|
+
const popularPosts = await postActions.listByReactions(
|
|
153
|
+
['like', 'view'],
|
|
154
|
+
37.7749,
|
|
155
|
+
-122.4194,
|
|
156
|
+
0,
|
|
157
|
+
10
|
|
158
|
+
);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Update
|
|
162
|
+
|
|
163
|
+
Update existing items:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// Update post
|
|
167
|
+
const updatedPost = await postActions.update({
|
|
168
|
+
postId: 'post123',
|
|
169
|
+
content: 'Updated content',
|
|
170
|
+
name: 'Updated Title'
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Update group
|
|
174
|
+
const updatedGroup = await groupActions.update({
|
|
175
|
+
groupId: 'group456',
|
|
176
|
+
description: 'New description',
|
|
177
|
+
settings: {
|
|
178
|
+
allowInvites: true,
|
|
179
|
+
requireApproval: false
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Partial updates with extensible fields
|
|
184
|
+
const partialUpdate = await postActions.update({
|
|
185
|
+
postId: 'post123',
|
|
186
|
+
customField: 'new value'
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Delete
|
|
191
|
+
|
|
192
|
+
Remove items from collections:
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
// Delete post
|
|
196
|
+
const deletedPost = await postActions.delete('post123');
|
|
197
|
+
|
|
198
|
+
// Delete group
|
|
199
|
+
const deletedGroup = await groupActions.delete('group456');
|
|
200
|
+
|
|
201
|
+
// Delete returns the deleted item
|
|
202
|
+
console.log(`Deleted post: ${deletedPost.name}`);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Extensible Fields
|
|
206
|
+
|
|
207
|
+
All collection types support extensible fields through the `ExtensibleFields` interface, allowing custom properties beyond the predefined schema.
|
|
208
|
+
|
|
209
|
+
### Using Extensible Fields
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
// Add custom fields to posts
|
|
213
|
+
const post = await postActions.add({
|
|
214
|
+
name: 'Event Announcement',
|
|
215
|
+
content: 'Join us for the meetup',
|
|
216
|
+
eventDate: '2024-06-15',
|
|
217
|
+
eventLocation: 'San Francisco',
|
|
218
|
+
capacity: 50,
|
|
219
|
+
registrationUrl: 'https://example.com/register'
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// Query with custom fields
|
|
223
|
+
const postWithCustomFields = await postActions.itemById('post123', [
|
|
224
|
+
'eventDate',
|
|
225
|
+
'eventLocation',
|
|
226
|
+
'capacity'
|
|
227
|
+
]);
|
|
228
|
+
|
|
229
|
+
// Update custom fields
|
|
230
|
+
await postActions.update({
|
|
231
|
+
postId: 'post123',
|
|
232
|
+
capacity: 75,
|
|
233
|
+
soldOut: true
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Common Use Cases
|
|
238
|
+
|
|
239
|
+
**1. Metadata Storage:**
|
|
240
|
+
```typescript
|
|
241
|
+
const post = await postActions.add({
|
|
242
|
+
name: 'Article',
|
|
243
|
+
content: 'Content...',
|
|
244
|
+
metadata: {
|
|
245
|
+
author: 'John Doe',
|
|
246
|
+
category: 'Tech',
|
|
247
|
+
readTime: 5
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**2. Feature Flags:**
|
|
253
|
+
```typescript
|
|
254
|
+
const group = await groupActions.add({
|
|
255
|
+
name: 'Beta Group',
|
|
256
|
+
description: 'Testing new features',
|
|
257
|
+
features: {
|
|
258
|
+
chatEnabled: true,
|
|
259
|
+
videoEnabled: false,
|
|
260
|
+
pollsEnabled: true
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**3. Custom Timestamps:**
|
|
266
|
+
```typescript
|
|
267
|
+
const post = await postActions.add({
|
|
268
|
+
name: 'Scheduled Post',
|
|
269
|
+
content: 'Future content',
|
|
270
|
+
scheduledPublishDate: Date.now() + 86400000,
|
|
271
|
+
lastReviewedDate: Date.now()
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## State Management
|
|
276
|
+
|
|
277
|
+
MetropolisJS uses ArkhamJS for state management, automatically dispatching actions on CRUD operations.
|
|
278
|
+
|
|
279
|
+
### Store Structure
|
|
280
|
+
|
|
281
|
+
Each collection has its own store with consistent structure:
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
{
|
|
285
|
+
[collectionName]: {
|
|
286
|
+
item: {}, // Single item from get/add/update
|
|
287
|
+
list: [], // List of items from list queries
|
|
288
|
+
error: null, // Last error if any
|
|
289
|
+
loading: false // Loading state
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Accessing State
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import {useFlux} from '@nlabs/arkhamjs-utils-react';
|
|
298
|
+
|
|
299
|
+
const MyComponent = () => {
|
|
300
|
+
const flux = useFlux();
|
|
301
|
+
|
|
302
|
+
// Get single post
|
|
303
|
+
const post = flux.getState('posts.item', {});
|
|
304
|
+
|
|
305
|
+
// Get list of posts
|
|
306
|
+
const postList = flux.getState('posts.list', []);
|
|
307
|
+
|
|
308
|
+
// Get error state
|
|
309
|
+
const error = flux.getState('posts.error', null);
|
|
310
|
+
|
|
311
|
+
// Access nested state
|
|
312
|
+
const user = flux.getState('users.item', {});
|
|
313
|
+
|
|
314
|
+
return (
|
|
315
|
+
<div>
|
|
316
|
+
{post.name && <h1>{post.name}</h1>}
|
|
317
|
+
{postList.map(p => <div key={p.postId}>{p.name}</div>)}
|
|
318
|
+
</div>
|
|
319
|
+
);
|
|
320
|
+
};
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Store Constants
|
|
324
|
+
|
|
325
|
+
Each collection defines action constants for state updates:
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import {POST_CONSTANTS, GROUP_CONSTANTS} from '@nlabs/metropolisjs';
|
|
329
|
+
|
|
330
|
+
// Listen for specific actions
|
|
331
|
+
flux.on(POST_CONSTANTS.ADD_ITEM_SUCCESS, (state) => {
|
|
332
|
+
const newPost = state.posts.item;
|
|
333
|
+
console.log('Post created:', newPost);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
flux.on(GROUP_CONSTANTS.GET_LIST_SUCCESS, (state) => {
|
|
337
|
+
const groups = state.groups.list;
|
|
338
|
+
console.log('Groups loaded:', groups.length);
|
|
339
|
+
});
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Manual State Updates
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
// Dispatch custom actions
|
|
346
|
+
flux.dispatch({
|
|
347
|
+
type: POST_CONSTANTS.ADD_ITEM_SUCCESS,
|
|
348
|
+
post: customPostData
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// Clear state
|
|
352
|
+
flux.dispatch({
|
|
353
|
+
type: POST_CONSTANTS.GET_LIST_SUCCESS,
|
|
354
|
+
list: []
|
|
355
|
+
});
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Error Handling
|
|
359
|
+
|
|
360
|
+
### Try-Catch Pattern
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
import {PostValidationError} from '@nlabs/metropolisjs';
|
|
364
|
+
|
|
365
|
+
try {
|
|
366
|
+
const post = await postActions.add({
|
|
367
|
+
name: 'New Post',
|
|
368
|
+
content: 'Content here'
|
|
369
|
+
});
|
|
370
|
+
console.log('Post created:', post.postId);
|
|
371
|
+
} catch (error) {
|
|
372
|
+
if (error instanceof PostValidationError) {
|
|
373
|
+
console.error('Validation error:', error.message);
|
|
374
|
+
console.error('Failed field:', error.field);
|
|
375
|
+
} else {
|
|
376
|
+
console.error('API error:', error);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Error State
|
|
382
|
+
|
|
383
|
+
Errors are automatically stored in the state:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
const MyComponent = () => {
|
|
387
|
+
const flux = useFlux();
|
|
388
|
+
const error = flux.getState('posts.error', null);
|
|
389
|
+
|
|
390
|
+
React.useEffect(() => {
|
|
391
|
+
if (error) {
|
|
392
|
+
console.error('Post operation failed:', error);
|
|
393
|
+
// Show error notification
|
|
394
|
+
}
|
|
395
|
+
}, [error]);
|
|
396
|
+
|
|
397
|
+
return <div>{error && <ErrorMessage error={error} />}</div>;
|
|
398
|
+
};
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Validation Errors
|
|
402
|
+
|
|
403
|
+
Collections use Zod schemas for validation:
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
try {
|
|
407
|
+
await postActions.add({
|
|
408
|
+
// Missing required fields or invalid data
|
|
409
|
+
content: null
|
|
410
|
+
});
|
|
411
|
+
} catch (error) {
|
|
412
|
+
// Error message includes field-level details
|
|
413
|
+
// "Post validation failed: content: Expected string, received null"
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## Best Practices
|
|
418
|
+
|
|
419
|
+
### 1. Use Factory Functions
|
|
420
|
+
|
|
421
|
+
Always create actions using factory functions:
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
// ✅ Correct
|
|
425
|
+
const postActions = createPostActions(flux);
|
|
426
|
+
|
|
427
|
+
// ❌ Incorrect - direct instantiation not supported
|
|
428
|
+
const postActions = new PostActions(flux);
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### 2. Request Only Needed Fields
|
|
432
|
+
|
|
433
|
+
Minimize data transfer by requesting only required fields:
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
// ✅ Efficient
|
|
437
|
+
const posts = await postActions.listByLatest(0, 10, [
|
|
438
|
+
'viewCount',
|
|
439
|
+
'likeCount'
|
|
440
|
+
]);
|
|
441
|
+
|
|
442
|
+
// ❌ Inefficient - retrieves all nested data
|
|
443
|
+
const posts = await postActions.listByLatest(0, 10, [
|
|
444
|
+
'user {*}',
|
|
445
|
+
'tags {*}',
|
|
446
|
+
'comments {*}'
|
|
447
|
+
]);
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### 3. Handle Pagination
|
|
451
|
+
|
|
452
|
+
Always implement pagination for large datasets:
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
const PAGE_SIZE = 20;
|
|
456
|
+
|
|
457
|
+
const loadMore = async (page: number) => {
|
|
458
|
+
const from = page * PAGE_SIZE;
|
|
459
|
+
const to = from + PAGE_SIZE;
|
|
460
|
+
return await postActions.listByLatest(from, to);
|
|
461
|
+
};
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### 4. Validate Before Submission
|
|
465
|
+
|
|
466
|
+
Pre-validate data before API calls:
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
import {validatePostInput} from '@nlabs/metropolisjs';
|
|
470
|
+
|
|
471
|
+
const handleSubmit = async (formData) => {
|
|
472
|
+
try {
|
|
473
|
+
// Validate locally first
|
|
474
|
+
const validatedData = validatePostInput(formData);
|
|
475
|
+
|
|
476
|
+
// Submit to API
|
|
477
|
+
const post = await postActions.add(validatedData);
|
|
478
|
+
} catch (error) {
|
|
479
|
+
// Handle validation errors before API call
|
|
480
|
+
showValidationErrors(error);
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### 5. Use Custom Adapters for Business Logic
|
|
486
|
+
|
|
487
|
+
Implement custom validation or transformation:
|
|
488
|
+
|
|
489
|
+
```typescript
|
|
490
|
+
const customPostAdapter = (input: unknown) => {
|
|
491
|
+
const post = validatePostInput(input);
|
|
492
|
+
|
|
493
|
+
// Add business logic
|
|
494
|
+
return {
|
|
495
|
+
...post,
|
|
496
|
+
processedContent: sanitizeHtml(post.content),
|
|
497
|
+
contentPreview: post.content?.substring(0, 200)
|
|
498
|
+
};
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
const postActions = createPostActions(flux, {
|
|
502
|
+
postAdapter: customPostAdapter
|
|
503
|
+
});
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### 6. Leverage Extensible Fields
|
|
507
|
+
|
|
508
|
+
Use extensible fields for application-specific data:
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
// Store application state
|
|
512
|
+
const post = await postActions.add({
|
|
513
|
+
name: 'Post',
|
|
514
|
+
content: 'Content',
|
|
515
|
+
// Custom fields for your app
|
|
516
|
+
isDraft: true,
|
|
517
|
+
publishDate: Date.now(),
|
|
518
|
+
analytics: {
|
|
519
|
+
impressions: 0,
|
|
520
|
+
clicks: 0
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### 7. Clean Up State
|
|
526
|
+
|
|
527
|
+
Clear state when unmounting components:
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
React.useEffect(() => {
|
|
531
|
+
return () => {
|
|
532
|
+
// Clear post list on unmount
|
|
533
|
+
flux.dispatch({
|
|
534
|
+
type: POST_CONSTANTS.GET_LIST_SUCCESS,
|
|
535
|
+
list: []
|
|
536
|
+
});
|
|
537
|
+
};
|
|
538
|
+
}, []);
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### 8. Batch Operations
|
|
542
|
+
|
|
543
|
+
Perform multiple operations efficiently:
|
|
544
|
+
|
|
545
|
+
```typescript
|
|
546
|
+
const createPostsInGroup = async (groupId: string, postData: any[]) => {
|
|
547
|
+
const posts = await Promise.all(
|
|
548
|
+
postData.map(data => postActions.add({
|
|
549
|
+
...data,
|
|
550
|
+
groupId
|
|
551
|
+
}))
|
|
552
|
+
);
|
|
553
|
+
|
|
554
|
+
// Connect all posts to group
|
|
555
|
+
await Promise.all(
|
|
556
|
+
posts.map(post => connectionActions.addConnection(
|
|
557
|
+
COLLECTIONS.POSTS,
|
|
558
|
+
post.postId,
|
|
559
|
+
COLLECTIONS.GROUPS,
|
|
560
|
+
groupId
|
|
561
|
+
))
|
|
562
|
+
);
|
|
563
|
+
|
|
564
|
+
return posts;
|
|
565
|
+
};
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### 9. Type Safety
|
|
569
|
+
|
|
570
|
+
Use TypeScript interfaces for type safety:
|
|
571
|
+
|
|
572
|
+
```typescript
|
|
573
|
+
import type {PostType, GroupType} from '@nlabs/metropolisjs';
|
|
574
|
+
|
|
575
|
+
const processPost = (post: PostType): string => {
|
|
576
|
+
return `${post.name}: ${post.content}`;
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
const createGroupPost = async (
|
|
580
|
+
group: GroupType,
|
|
581
|
+
postData: Partial<PostType>
|
|
582
|
+
): Promise<PostType> => {
|
|
583
|
+
return await postActions.add({
|
|
584
|
+
...postData,
|
|
585
|
+
groupId: group.groupId
|
|
586
|
+
});
|
|
587
|
+
};
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
### 10. Error Recovery
|
|
591
|
+
|
|
592
|
+
Implement retry logic for failed operations:
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
const retryOperation = async <T>(
|
|
596
|
+
operation: () => Promise<T>,
|
|
597
|
+
maxRetries: number = 3
|
|
598
|
+
): Promise<T> => {
|
|
599
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
600
|
+
try {
|
|
601
|
+
return await operation();
|
|
602
|
+
} catch (error) {
|
|
603
|
+
if (i === maxRetries - 1) throw error;
|
|
604
|
+
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
throw new Error('Max retries exceeded');
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
// Usage
|
|
611
|
+
const post = await retryOperation(() =>
|
|
612
|
+
postActions.itemById('post123')
|
|
613
|
+
);
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
## Examples by Collection
|
|
617
|
+
|
|
618
|
+
### Posts
|
|
619
|
+
|
|
620
|
+
```typescript
|
|
621
|
+
const postActions = createPostActions(flux);
|
|
622
|
+
|
|
623
|
+
// Create
|
|
624
|
+
const post = await postActions.add({
|
|
625
|
+
name: 'Post Title',
|
|
626
|
+
content: 'Post content',
|
|
627
|
+
type: 'text',
|
|
628
|
+
tags: [{name: 'tech'}]
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
// Read
|
|
632
|
+
const post = await postActions.itemById('post123');
|
|
633
|
+
const posts = await postActions.listByLatest(0, 10);
|
|
634
|
+
|
|
635
|
+
// Update
|
|
636
|
+
await postActions.update({
|
|
637
|
+
postId: 'post123',
|
|
638
|
+
content: 'Updated content'
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
// Delete
|
|
642
|
+
await postActions.delete('post123');
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
### Groups
|
|
646
|
+
|
|
647
|
+
```typescript
|
|
648
|
+
const groupActions = createGroupActions(flux);
|
|
649
|
+
|
|
650
|
+
// Create
|
|
651
|
+
const group = await groupActions.add({
|
|
652
|
+
name: 'Tech Group',
|
|
653
|
+
description: 'Discuss technology',
|
|
654
|
+
isPrivate: false
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
// Read
|
|
658
|
+
const group = await groupActions.itemById('group123');
|
|
659
|
+
const groups = await groupActions.listByLatest(0, 10);
|
|
660
|
+
|
|
661
|
+
// Update
|
|
662
|
+
await groupActions.update({
|
|
663
|
+
groupId: 'group123',
|
|
664
|
+
settings: {allowInvites: true}
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
// Delete
|
|
668
|
+
await groupActions.delete('group123');
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
### Content
|
|
672
|
+
|
|
673
|
+
```typescript
|
|
674
|
+
const contentActions = createContentActions(flux);
|
|
675
|
+
|
|
676
|
+
// Create
|
|
677
|
+
const content = await contentActions.add({
|
|
678
|
+
key: 'welcome_message',
|
|
679
|
+
locale: 'en',
|
|
680
|
+
content: 'Welcome to our app!',
|
|
681
|
+
category: 'onboarding'
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
// Read
|
|
685
|
+
const content = await contentActions.itemByKey('welcome_message', 'en');
|
|
686
|
+
const contents = await contentActions.listByCategory('onboarding');
|
|
687
|
+
|
|
688
|
+
// Update
|
|
689
|
+
await contentActions.update({
|
|
690
|
+
contentId: 'content123',
|
|
691
|
+
content: 'Updated welcome message'
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
// Delete
|
|
695
|
+
await contentActions.delete('content123');
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
## Next Steps
|
|
699
|
+
|
|
700
|
+
- [Collections Reference](./COLLECTIONS.md) - Detailed field information for each collection
|
|
701
|
+
- [Connections Guide](./CONNECTIONS.md) - Managing relationships between collections
|
|
702
|
+
- [MetropolisJS Documentation](../README.md) - Main library documentation
|