Skip to main content
Glama

mcp-google-sheets

utils.ts3.75 kB
import { deepmerge } from 'deepmerge-ts' export function isString(str: unknown): str is string { return str != null && typeof str === 'string' } export function isNil<T>(value: T | null | undefined): value is null | undefined { return value === null || value === undefined } // eslint-disable-next-line @typescript-eslint/no-explicit-any export function setAtPath<T, K extends keyof any>(obj: T, path: K | K[], value: any): void { const pathArray = Array.isArray(path) ? path : (path as string).match(/([^[.\]])+/g) as unknown as K[] // eslint-disable-next-line @typescript-eslint/no-explicit-any pathArray.reduce((acc: any, key: K, i: number) => { if (acc[key] === undefined) acc[key] = {} if (i === pathArray.length - 1) acc[key] = value return acc[key] }, obj) } export function insertAt<T>(array: T[], index: number, item: T): T[] { return [...array.slice(0, index), item, ...array.slice(index)] } export function debounce<T>(func: (...args: T[]) => void, wait: number): (...args: T[]) => void { let timeout: NodeJS.Timeout return function (...args: T[]) { const later = () => { clearTimeout(timeout) func(...args) } clearTimeout(timeout) timeout = setTimeout(later, wait) } } type DeepPartial<T> = { [P in keyof T]?: T[P] extends Record<string, unknown> ? DeepPartial<T[P]> : T[P]; } /** * This function also merges arrays, x = [1, 2], y = [3, 4], z = deepMergeAndCast(x, y) -> [1, 2, 3, 4] **/ export function deepMergeAndCast<T>(target: DeepPartial<T>, source: DeepPartial<T>): T { return deepmerge(target as Partial<T>, source as Partial<T>) as T } export function kebabCase(str: string): string { return str .replace(/([a-z])([A-Z])/g, '$1-$2') // Handle camelCase by adding hyphen between lowercase and uppercase letters .replace(/\s+/g, '-') // Replace spaces with hyphens .replace(/_/g, '-') // Replace underscores with hyphens .toLowerCase() // Convert to lowercase .replace(/^-+|-+$/g, '') // Remove leading and trailing hyphens } export function isEmpty<T>(value: T | null | undefined): boolean { if (value == null) { return true } if (typeof value === 'string' || Array.isArray(value)) { return value.length === 0 } if (typeof value === 'object') { return Object.keys(value).length === 0 } return false } export function startCase(str: string): string { return str .replace(/([a-z])([A-Z])/g, '$1 $2') .replace(/[_-]+/g, ' ') .replace(/\s+/g, ' ') .replace(/^[a-z]/, match => match.toUpperCase()) .replace(/\b[a-z]/g, match => match.toUpperCase()) } export function camelCase(str: string): string { return str .replace(/([-_][a-z])/g, group => group.toUpperCase() .replace('-', '') .replace('_', '')) } export function parseToJsonIfPossible(str: unknown): unknown { try { return JSON.parse(str as string) } catch (e) { return str } } export function pickBy<T extends Record<string, unknown>>( object: T, predicate: (value: T[keyof T], key: keyof T) => boolean, ): Partial<T> { return Object.keys(object).reduce((result: Partial<T>, key: keyof T) => { if (predicate(object[key], key)) { result[key] = object[key] } return result }, {}) } export function chunk<T>(records: T[], size: number) { const chunks: T[][] = [] for (let i = 0; i < records.length; i += size) { chunks.push(records.slice(i, i + size)) } return chunks }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server