pagination-utils.ts•3.63 kB
import { SeekPage } from '@activepieces/shared'
import dayjs from 'dayjs'
import { CursorResult } from './paginator'
export function atob(value: string): string {
return Buffer.from(value, 'base64').toString()
}
export function btoa(value: string): string {
return Buffer.from(value).toString('base64')
}
export function encodeByType(type: string, value: unknown): string | null {
if (value === null) return null
switch (type) {
case 'timestamp with time zone':
case 'datetime':
case 'date': {
return dayjs(value as string)
.valueOf()
.toString()
}
case 'number': {
return `${value}`
}
case 'string': {
return encodeURIComponent(value as string)
}
case 'object': {
/**
* if reflection type is Object, check whether an object is a date.
* see: https://github.com/rbuckton/reflect-metadata/issues/84
*/
if (typeof (value as Record<string, unknown>).getTime === 'function') {
return (value as Date).getTime().toString()
}
break
}
default:
break
}
throw new Error(`unknown type in cursor: [${type}]${value}`)
}
export function decodeByType(
type: string,
value: string,
): string | number | Date {
switch (type) {
case 'object':
case 'timestamp with time zone':
case 'datetime':
case 'date': {
const timestamp = parseInt(value, 10)
if (Number.isNaN(timestamp)) {
throw new Error('date column in cursor should be a valid timestamp')
}
return new Date(timestamp).toISOString()
}
case 'number': {
const num = parseFloat(value)
if (Number.isNaN(num)) {
throw new Error('number column in cursor should be a valid number')
}
return num
}
case 'string': {
return decodeURIComponent(value)
}
default: {
throw new Error(`unknown type in cursor: [${type}]${value}`)
}
}
}
const decode = (str: string): string =>
Buffer.from(str, 'base64').toString('binary')
const encode = (str: string): string =>
Buffer.from(str, 'binary').toString('base64')
function encodeNextCursor(cursor: string | null | undefined) {
if (cursor === null) {
return null
}
return encode('next_' + cursor)
}
function encodePreviousCursor(cursor: string | null | undefined) {
if (cursor === null) {
return null
}
return encode('prev_' + cursor)
}
export const paginationHelper = {
createPage<T>(data: T[], cursor: CursorResult | null): SeekPage<T> {
return {
next: encodeNextCursor(cursor?.afterCursor),
previous: encodePreviousCursor(cursor?.beforeCursor),
data,
}
},
decodeCursor(encodedCursor: string | null): {
nextCursor: string | undefined
previousCursor: string | undefined
} {
if (encodedCursor === null || encodedCursor === undefined) {
return {
nextCursor: undefined,
previousCursor: undefined,
}
}
const decodedRawCursor = decode(encodedCursor)
const isNext = decodedRawCursor.startsWith('next_')
const cursor = decodedRawCursor.split('_')[1]
return {
nextCursor: isNext ? cursor : undefined,
previousCursor: isNext ? undefined : cursor,
}
},
}