Would you like to clone this notebook?

When you clone a notebook you are able to make changes without affecting the original notebook.

Cancel

Deep create messaging package

node v14.20.1
version: 3.0.0
endpointsharetweet
Copy and insert on 11 line path to your gql. (Recoment to use deep in cloud https://ivansglazunov.notion.site/Install-and-Using-8f213fbd532e4c869626b061b691ba2c in Gitpod developer cloud environment. Gql you can take from https://ivansglazunov.notion.site/GraphQL-12a676a2508541cf9a63cfeb564ffe7d).
require('react'); require('graphql'); require('lodash'); require('subscriptions-transport-ws'); const { generateApolloClient } = require("@deep-foundation/hasura/client"); const { DeepClient } = require('@deep-foundation/deeplinks/imports/client'); const { minilinks, Link } = require('@deep-foundation/deeplinks/imports/minilinks'); const apolloClient = generateApolloClient({ path: '3006-deepfoundation-dev-5arvsn4pui6.ws-eu39.gitpod.io/gql', // <<= HERE PATH TO UPDATE ssl: true, // admin token in prealpha deep secret key token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwczovL2hhc3VyYS5pby9qd3QvY2xhaW1zIjp7IngtaGFzdXJhLWFsbG93ZWQtcm9sZXMiOlsibGluayJdLCJ4LWhhc3VyYS1kZWZhdWx0LXJvbGUiOiJsaW5rIiwieC1oYXN1cmEtdXNlci1pZCI6IjIwNiJ9LCJpYXQiOjE2NDg0MDkzODV9.aiMZAI65NGEWwERsj1qdimHZcqkuaSLHBR8nGo8n2Nk', }); const deep = new DeepClient({ apolloClient, linkId: 206 });
deep.linkId // actualUserId
const Type = await deep.id('@deep-foundation/core', 'Type') // Type type link id
const Package = await deep.id('@deep-foundation/core', 'Package') // Package type link Id
const Contain = await deep.id('@deep-foundation/core', 'Contain') // Contain type link id
const Any = await deep.id('@deep-foundation/core', 'Any');
create Package @deep-foundation/messaging and nest it with Contain into deep.linkId. This is important, if you want support our recomended Contain tree for permission control. But, you can create any your rules in your deep.
const { data: [{ id: packageId }] } = await deep.insert({ type_id: Package, string: { data: { value: `@deep-foundation/messaging` } }, in: { data: { type_id: Contain, from_id: deep.linkId } }, });
// insert type Reply const { data: [{ id: Reply }] } = await deep.insert({ // Reply = from Any to Any type_id: Type, from_id: Any, to_id: Any, in: { data: { // nest into package as 'Reply' in Contain's tree under package type_id: Contain, from_id: packageId, // before created package string: { data: { value: 'Reply' } }, } }, });
const Value = await deep.id('@deep-foundation/core', 'Value'); // Value type link id
const String = await deep.id('@deep-foundation/core', 'String'); // String link id - use it as symbol
// insert type Message const { data: [{ id: Message }] } = await deep.insert({ // Message just dot type_id: Type, in: { data: { // nest into package as 'Message' in Contain's tree under package type_id: Contain, from_id: packageId, // before created package string: { data: { value: 'Message' } }, } }, out: { data: { // Message can have .string as .value of link. type_id: Value, to_id: String, } }, });
// insert type Author const { data: [{ id: Author }] } = await deep.insert({ // Reply = from Any to Any type_id: Type, from_id: Any, to_id: Any, in: { data: { // nest into package as 'Author' in Contain's tree under package type_id: Contain, from_id: packageId, // before created package string: { data: { value: 'Author' } }, } }, });
// insert type Join const { data: [{ id: Join }] } = await deep.insert({ // Reply = from Any to Any type_id: Type, from_id: Any, to_id: Any, in: { data: { // nest into package as 'Join' in Contain's tree under package type_id: Contain, from_id: packageId, // before created package string: { data: { value: 'Join' } }, } }, });
// insert first message in actual user const { data: [{ id: messageId1 }] } = await deep.insert({ type_id: Message, string: { data: { value: 'first message' } }, out: { data: { type_id: Reply, to_id: deep.linkId, } }, });
// insert second message as answer to first message const { data: [{ id: messageId2 }] } = await deep.insert({ type_id: Message, string: { data: { value: 'second message' } }, out: { data: { type_id: Reply, to_id: messageId1, } }, });
Ok, now we already have simple chat model. Not best, just one of concept.
const User = await deep.id('@deep-foundation/core', 'User'); // User type link id
const ml1 = minilinks((await deep.select({ type_id: { _in: [User, Reply, Message] }, })).data);
Let's play with this cache with it 1 minute...
const f = link => (link.inByType[Reply] || []).map(r => [r.from.value.value, ...f(r.from)]); f(ml1.byId[deep.linkId]);
Ok. Let's go forward. Tree in Deep based on materialied-path algorithm. We can for example cover Replies and Messages with indexes. But ofcourse each level of tree - more indexes. We provide more examples for easy tree covering.
First we need to create Tree, and include User, Reply and Message types into it.
const Tree = await deep.id('@deep-foundation/core', 'Tree');
const TreeIncludeNode = await deep.id('@deep-foundation/core', 'TreeIncludeNode');
const TreeIncludeUp = await deep.id('@deep-foundation/core', 'TreeIncludeUp');
We need create Tree where User and Message used as nodes, but Reply as links between Any and Any.
const { data: [{ id: messagingTree }] } = await deep.insert({ type_id: Tree, in: { data: { // just for permission control type_id: Contain, from_id: deep.linkId, string: { data: { value: 'messagingTree' } }, } }, out: { data: [ { type_id: TreeIncludeNode, to_id: User, }, { type_id: TreeIncludeNode, to_id: Message, }, { type_id: TreeIncludeUp, to_id: Reply, }, { type_id: TreeIncludeUp, to_id: Join, }, { type_id: TreeIncludeUp, to_id: Author, }, { type_id: TreeIncludeDown, to_id: await deep.id('@deep-foundation/core', 'Join'), }, ] }, });
Let's use our new Tree!
const userRepliesTree = await deep.select({ _by_item: { group_id: { _eq: messagingTree }, path_item_id: { _eq: deep.linkId } } });
userRepliesTree.data.length;
YES. We gets all down by deep.linkId. Lets find all elements but not replies upper from last message messageId2?
const upperFromM2 = await deep.select({ type_id: { _neq: Reply }, _by_path_item: { group_id: { _eq: messagingTree }, item_id: { _eq: messageId2 } } });
upperFromM2.data.length;
Continuation of development messanger you can find here: https://github.com/deep-foundation/nextjs If you already run dev in gitpod (first step in this guilde), you can exec in terminal: (cd ./packages/nextjs; PORT=4000 npm run dev) And your GitPod run's this example nextjs. In /messanger route you can find draft of messanger. I hope we are closer now). The deep is calling you - join our deep community. Write iamindeep in the #hi discord channel here https://discord.gg/vNJCTK4nZB.
const Rule = await deep.id('@deep-foundation/core', 'Rule');
const RuleSubject = await deep.id('@deep-foundation/core', 'RuleSubject');
const RuleObject = await deep.id('@deep-foundation/core', 'RuleObject');
const RuleAction = await deep.id('@deep-foundation/core', 'RuleAction');
const Selector = await deep.id('@deep-foundation/core', 'Selector');
const SelectorInclude = await deep.id('@deep-foundation/core', 'SelectorInclude');
const SelectorExclude = await deep.id('@deep-foundation/core', 'SelectorExclude');
const SelectorTree = await deep.id('@deep-foundation/core', 'SelectorTree');
const containTree = await deep.id('@deep-foundation/core', 'containTree');
const AllowInsert = await deep.id('@deep-foundation/core', 'AllowInsert');
const SelectorFilter = await deep.id('@deep-foundation/core', 'SelectorFilter');
const BoolExp = await deep.id('@deep-foundation/core', 'BoolExp');
const usersId = await deep.id('@deep-foundation/core', 'system', 'users');
const replyInsertPermission = await deep.insert({ type_id: Rule, out: { data: [ { type_id: RuleSubject, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: usersId, out: { data: { type_id: SelectorTree, to_id: await deep.id('@deep-foundation/core', 'joinTree'), }, }, }, ] }, }, }, }, { type_id: RuleObject, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: Reply, out: { data: { type_id: SelectorTree, to_id: containTree, }, }, }, { type_id: SelectorFilter, to: { data: { type_id: BoolExp, object: { data: { value: { // only if upper exists current user or join current user to: { _or: [ { _by_item: { group_id: { _eq: messagingTree }, root_id: { _eq: 'X-Deep-User-Id' } }, }, { _by_item: { group_id: { _eq: messagingTree }, path_item: { out: { type_id: { _eq: Join }, to_id: { _eq: 'X-Deep-User-Id' } } } }, }, ], }, from: { out: { type_id: { _eq: Author }, to_id: { _eq: 'X-Deep-User-Id' }, }, }, }, }, }, }, }, }, ], }, }, }, }, { type_id: RuleAction, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: AllowInsert, out: { data: { type_id: SelectorTree, to_id: containTree, }, }, }, ], }, }, }, }, ], }, });
// Ok then create message permission. const messagePermission = await deep.insert({ type_id: Rule, out: { data: [ { type_id: RuleSubject, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: usersId, out: { data: { type_id: SelectorTree, to_id: containTree, }, }, }, ] }, }, }, }, { type_id: RuleObject, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: Message, out: { data: { type_id: SelectorTree, to_id: containTree, }, }, }, ], }, }, }, }, { type_id: RuleAction, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: AllowInsert, out: { data: { type_id: SelectorTree, to_id: containTree, }, }, }, ], }, }, }, }, ], }, });
// Ok then create author permission. const authorPermission = await deep.insert({ type_id: Rule, out: { data: [ { type_id: RuleSubject, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: usersId, out: { data: { type_id: SelectorTree, to_id: containTree, }, }, }, ] }, }, }, }, { type_id: RuleObject, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: Author, out: { data: { type_id: SelectorTree, to_id: containTree, }, }, }, { type_id: SelectorFilter, to: { data: { type_id: BoolExp, object: { data: { value: { to_id: { _eq: 'X-Deep-User-Id' }, from: { _not: { out: { id: { _neq: 'X-Deep-Item-Id' }, type_id: { _eq: Author }, }, } }, }, }, }, }, }, }, ], }, }, }, }, { type_id: RuleAction, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: AllowInsert, out: { data: { type_id: SelectorTree, to_id: containTree, }, }, }, ], }, }, }, }, ], }, });
const joinPermission = await deep.insert({ type_id: Rule, out: { data: [ { type_id: RuleSubject, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: usersId, out: { data: { type_id: SelectorTree, to_id: containTree, }, }, }, ] }, }, }, }, { type_id: RuleObject, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: Join, out: { data: { type_id: SelectorTree, to_id: containTree, }, }, }, { type_id: SelectorFilter, to: { data: { type_id: BoolExp, object: { data: { value: { // only if owner of all reply tree can add join from: { _by_item: { group_id: { _eq: messagingTree }, path_item_id: { _eq: 'X-Deep-User-Id' } }, }, }, }, }, }, }, }, ], }, }, }, }, { type_id: RuleAction, to: { data: { type_id: Selector, out: { data: [ { type_id: SelectorInclude, to_id: AllowInsert, out: { data: { type_id: SelectorTree, to_id: containTree, }, }, }, ], }, }, }, }, ], }, });
Check.
const guest1 = await deep.guest(); const deepGuest1 = new DeepClient({ deep, ...guest1 });
const { data: [{ id: guest1Message1 }] } = await deepGuest1.insert({ type_id: Message, string: { data: { value: 'guest1message1' } }, });
const { data: [{ id: guest1Message1Reply }] } = await deepGuest1.insert({ type_id: Author, from_id: guest1Message1, to_id: deepGuest1.linkId, });
Guest1 success insert message and reply. But guest1 can't delete reply or message, because we don't create any rule about it.
await deepGuest1.delete(guest1Message1Reply);
// you cant insert reply without author from message const { error: guest1Message2 } = await deepGuest1.insert({ type_id: Reply, from: { data: { type_id: Message, string: { data: { value: 'guest1message2' } }, } }, to_id: deepGuest1.linkId, }, { silent: true });
const { data: [{ id: guest1Message2Reply }] } = await deepGuest1.insert({ type_id: Reply, from: { data: { type_id: Message, string: { data: { value: 'guest1message2' } }, out: { data: { type_id: Author, to_id: deepGuest1.linkId } }, } }, to_id: deepGuest1.linkId, }, { silent: true });
Loading…

no comments

    sign in to comment