Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

Commit

Permalink
feat: Add query for table column aggregate count.
Browse files Browse the repository at this point in the history
  • Loading branch information
fourjuaneight committed Jun 16, 2022
1 parent dd001fb commit 5eba9cc
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 1 deletion.
33 changes: 32 additions & 1 deletion src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import { bookmarkStackExchange } from './bookmark-stackexchange';
import { bookmarkTweets } from './bookmark-tweets';
import { bookmarkVimeo } from './bookmark-vimeos';
import { bookmarkYouTube } from './bookmark-youtubes';
import { queryBookmarkItems, queryTags, searchBookmarkItems } from './hasura';
import {
queryBookmarkAggregateCount,
queryBookmarkItems,
queryTags,
searchBookmarkItems,
} from './hasura';

import { BookmarkingResponse, RecordData, RequestPayload } from './typings.d';

Expand Down Expand Up @@ -114,6 +119,22 @@ const handleAction = async (payload: RequestPayload): Promise<Response> => {
responseInit
);
}
case payload.type === 'Count': {
location = `${payload.type}-${payload.table}`;

const queryResults = await queryBookmarkAggregateCount(
payload.table,
payload.countColumn
);

return new Response(
JSON.stringify({
count: queryResults,
location,
}),
responseInit
);
}
case payload.table === 'Podcasts':
location = payload.table;
response = await bookmarkPodcasts(data.url, data.tags);
Expand Down Expand Up @@ -224,6 +245,16 @@ export const handleRequest = async (request: Request): Promise<Response> => {
JSON.stringify({ error: "Missing 'column' parameter." }),
badReqBody
);
case payload.type === 'Count' && !payload.countColumn:
return new Response(
JSON.stringify({ error: "Missing 'countColumn' parameter." }),
badReqBody
);
case payload.type === 'Count' && !payload.table:
return new Response(
JSON.stringify({ error: "Missing 'table' parameter." }),
badReqBody
);
case payload.table === 'Articles' && !payload.data?.title:
return new Response(
JSON.stringify({ error: "Missing 'data.title' parameter." }),
Expand Down
78 changes: 78 additions & 0 deletions src/hasura.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import {
HasuraErrors,
HasuraInsertResp,
HasuraQueryAggregateResp,
HasuraQueryResp,
HasuraQueryTagsResp,
CountColumn,
RecordColumnAggregateCount,
RecordData,
} from './typings.d';

Expand Down Expand Up @@ -31,6 +34,22 @@ const objToQueryString = (obj: { [key: string]: any }) =>
return `${key}: ${fmtValue}`;
});

const countUnique = (iterable: string[]) =>
iterable.reduce((acc: RecordColumnAggregateCount, item) => {
acc[item] = (acc[item] || 0) + 1;
return acc;
}, {});

const countUniqueSorted = (iterable: string[]) =>
// sort descending by count
Object.entries(countUnique(iterable))
.sort((a, b) => b[1] - a[1])
.reduce(
(acc: RecordColumnAggregateCount, [key, val]) =>
({ ...acc, [key]: val } as RecordColumnAggregateCount),
{}
);

/**
* Get bookmark tags from Hasura.
* @function
Expand Down Expand Up @@ -133,6 +152,65 @@ export const queryBookmarkItems = async (
}
};

/**
* Get aggregated count of bookmark column from Hasura.
* @function
* @async
*
* @param {string} table
* @param {CountColumn} column
* @returns {Promise<RecordColumnAggregateCount>}
*/
export const queryBookmarkAggregateCount = async (
table: string,
column: CountColumn
): Promise<RecordColumnAggregateCount> => {
const sort = column === 'tags' ? 'title' : column;
const query = `
{
bookmarks_${table}(order_by: {${sort}: asc}) {
${column}
}
}
`;

try {
const request = await fetch(`${HASURA_ENDPOINT}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Hasura-Admin-Secret': `${HASURA_ADMIN_SECRET}`,
},
body: JSON.stringify({ query }),
});
const response: any = await request.json();

if (response.errors) {
const { errors } = response as HasuraErrors;

throw `(queryBookmarkAggregateCount) - ${table}: \n ${errors
.map(err => `${err.extensions.path}: ${err.message}`)
.join('\n')} \n ${query}`;
}

const data = (response as HasuraQueryAggregateResp).data[
`bookmarks_${table}`
];
let collection: string[];

if (column === 'tags') {
collection = data.map(item => item[column] as string[]).flat();
} else {
collection = data.map(item => item[column] as string);
}

return countUniqueSorted(collection);
} catch (error) {
console.log(error);
throw error;
}
};

/**
* Search bookmark entries from Hasura.
* @function
Expand Down
20 changes: 20 additions & 0 deletions src/typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,19 @@ export interface RecordData {
archive?: string;
}

export interface RecordColumnAggregateCount {
[key: string]: number;
}

export type CountColumn =
| 'author'
| 'creator'
| 'site'
| 'dead'
| 'subreddit'
| 'tags'
| 'user';

export interface BookmarkingResponse {
success: boolean;
message: string;
Expand All @@ -1138,6 +1151,7 @@ export interface RequestPayload {
tagList?: string;
query?: string;
column?: string;
countColumn?: CountColumn;
data?: PageData;
}

Expand All @@ -1163,6 +1177,12 @@ export interface HasuraQueryResp {
};
}

export interface HasuraQueryAggregateResp {
data: {
[key: string]: string | string[];
};
}

export interface HasuraQueryTagsResp {
data: {
meta_tags: { name: string }[];
Expand Down

0 comments on commit 5eba9cc

Please sign in to comment.