Link

Core Concepts


Data Flow

Object Queries

As one of the most important features of the yack-connector-framework, the object query partial is how we pass and share data between providers. These object queries are just plain javascript objects.

Core Queries
  1. channelQuery
  2. threadQuery
  3. commentQuery
  4. userQuery
  5. categoryQuery
  6. fileQuery

While the general flow of data for the key object queries goes IChannelProviderIThreadProviderICommentProvider, the diagram below helps to visualize which query objects key providers’ functions inherit. Core Query Objects Diagram

Flex Queries

Flex Queries allow providers and interfaces to easily access multiple types of Core Query objects conditionally. All Flex Query objects have two properties where the objectType flags what type of core objectQuery to expect.

  1. objectType
  2. objectQuery - one of the six Core Queries

The below diagram depicts which providers and interfaces make use of Flex Queries. Flex Query Objects Diagram

Providers/interfaces that accept Flex Queries and their corresponding objectTypes:

Example: Search

Example: Form

Important Notes

All object queries include a flexible metadata property. See Metadata
Not all references to objectTypes in the yack-connector-framework have an associated objectQuery. See Non-Query objectTypes

Metadata

If the returned response data from a Connector source does not fit perfectly into the interface and you find yourself needing this data at some later point, then you should store this data in the metadata object. The metadata will be available in the object query. See Object Queries for a full list of object queries mapped to their corresponding interfaces to better understand the flow of data.


Authentication

OAuth

DO THIS

Basic Auth

DO THIS

Basic Auth relies heavily on the Session Container


Replies

The yack-connector-framework does not have a separate interface for replies. The app is able to distinguish that a given comment is a reply by setting the parentCommentId property on the Comment model.

✎ Example 1: Set Comment As A Reply
    // Here we're selecting 2nd comment from the response data
    const selectComment = response.data[3];

    // Check if function was passed a parentCommentId
    const parentCommentId = !!parentCommentQuery ? parentCommentQuery.id : null;

    // Populate comment
    const comment: Comment = {
        id: selectComment.id.toString(), // id = 3
        content: {
            type: TextContent.Types.html,
            value: $body.html()
        },
        utcCreateDate: selectComment.created,
        createdBy: {
            id: selectComment.user.id,
            username: selectComment.user.username
        },
        threadId: threadQuery.id,
    };

    // Setting parent Id
    if(parentCommentId){
        // if were already given a parent id set it on the comment object
        populatedComment.parentCommentId = parentCommentId;
    }else if("reply_to_comment_id" in selectComment){
        // Check if response comment's data has a parent comment id
        populatedComment.parentCommentId = comment.reply_to_comment_id.toString();
    }else{
        // Is top-level comment
    } 

Pagination

Channels

Threads

Comments

The first time that the getCommentsByThread() is called the options.nextPageToken and parentCommentQuery will be undefined because they are only used for fetching the next page of comments/replies.

✎ Example 1: Checking if Paginated
ICommentProvider.getCommentsByThread()

If is provided a nextPageToken property on its options argument, then you know the function was called because the app is trying to fetch the next page of comments.

let paginated: boolean = !!options.nextPageToken;
✎ Example 2: Checking if Paginated Replies or Paginated Top-Level Comments
ICommentProvider.getCommentsByThread()

All functions in the ICommentProvider are optionally and conditionally provided a parentCommentQuery property. If this property is provided, then the comment is a reply. Otherwise, it’s a top-level comment.

let paginated: boolean = !!options.nextPageToken;
const parentCommentId = !!parentCommentQuery ? parentCommentQuery.id : null;

if(paginated && !parentCommentId){
    // App triggers getCommentsByThread() when the user reaches the end of the comments list.
    console.log("Fetch next page of top-level comments")
}else if(paginated && parentCommentId){
    // App triggers getCommentsByThread() for replies when user clicks the __Load X More Replies__ link.
    console.log("Fetch next page of replies")
✎ Example 3: Setting Comment NextPageToken
ICommentProvider.getCommentsByThread()
const comments = new PagedArray<Comment>();

for(const comment in response.data){
    const populatedComment = populateComment(comment);
    comments.push(populatedComment);
}

// If the comments list has a next page set it
"nextToken" in response.data ? comments.nextPageToken = response.data.nextToken : null;    

return Result.success(comments)

✎ Example 4: Setting repliesNextPageToken
ICommentProvider.getCommentsByThread()
for(const comment in response.data){
    const populatedComment = populateComment(comment);
    if(comment.has_more_replies){
        comment.repliesNextPageToken = comment.replies_token;
    }
    comments.push(populatedComment);
}


File Uploads


Error Handling


Configs


User Sessions

The SessionContainer is where cookies and requestHeaders are stored locally within the context of the Connector’s PluginSession instance. The session container is passed to provider interfaces through the options parameter of type PluginRequestOptions.

↳ Hierarchy: IPlugin.basicAuthClientIBasicAuthClient.loginUserPluginRequestOptions.sessionPluginSession.sessionContainer
✎ Example 1: Get Session Info
export class UserProvider implements IUserProvider {
    async getSelf(options: PluginRequestOptions): Promise<Result<PluginUser>> {
        const sessionContainer = options.session.sessionContainer;
        const sessionCookies = sessionContainer.cookies,
        sessionHeaders = sessionContainer.requestHeaders,
        sessionMetadata = sessionContainer.metadata;
    }
}
✎ Example 2: Set Session Info
export class BasicAuthClient implements IBasicAuthClient {
    async loginUser(response: BasicAuthResponse): Promise<Result<SessionContainer>> {
        const loginObj = {
            cookies: response.sessionCookies,
            metadata: null,
            requestHeaders: null
        };
        return Result.success(loginObj);
    }
}

Not to be confused with PluginSession
Only useful for Yack Connectors that use BasicAuth
Locally stored session information is inaccessible from Chrome DevTools.


Request Options


Table of contents