@dotwalker-com/gootasks-client
v0.1.0
Published
Browser-first TypeScript client for the Google Tasks API. Zero runtime dependencies, RFC 3339 validation, rate limiting with Retry-After, swappable cache and auth providers.
Downloads
231
Maintainers
Readme
@dotwalker-com/gootasks-client
Browser-first TypeScript client for the Google Tasks API. Zero runtime dependencies, swappable auth + cache, rate limiting with
Retry-Aftersupport.
Why
Existing Google Tasks API clients fall short for modern applications:
| Client | Issue |
|---|---|
| googleapis | Server-only (Node.js, no browser) — drags in 2MB of dependencies |
| gapi.client.tasks | Deprecated by Google, broken with Next.js SSR |
| Most wrappers | No field masking, no Retry-After handling, no swappable cache |
gootasks-client fills this gap:
- Browser-first — uses the global
fetchAPI, zero runtime dependencies. - Field masking — reduce API payload by 30-50% by requesting only the fields you need.
- Rate limiting — full 429 handling with
Retry-Afterparsing (delta-seconds and HTTP-date) and exponential backoff. - Swappable auth — implement
AuthProviderwith 2 lines. Works with Google Identity Services,google-auth-library, or any custom OAuth flow. - Swappable cache — bring your own
CacheProvider, or use the built-inMemoryCache. - Isomorphic — works in Node 18+, browsers, and edge runtimes.
Installation
# pnpm
pnpm add @dotwalker-com/gootasks-client
# npm
npm install @dotwalker-com/gootasks-client
# yarn
yarn add @dotwalker-com/gootasks-clientQuick start
import { TasksApi, MemoryCache } from '@dotwalker-com/gootasks-client';
// 1. Implement your auth provider (anywhere you have an access token).
const auth = {
async getAccessToken(): Promise<string> {
return yourTokenGetter(); // e.g. Google Identity Services in the browser
},
};
// 2. Create the API client.
const api = new TasksApi({
auth,
cache: new MemoryCache(), // optional — default if omitted
});
// 3. Use it.
const lists = await api.lists.list();
const { tasks } = await api.tasks.list(lists[0].id);Or: standalone function wrappers (preferred for simple apps)
import { configure, getTasks, createTask } from '@dotwalker-com/gootasks-client';
configure({ auth, cache: new MemoryCache() });
const lists = await getTaskLists();
const task = await createTask(lists[0].id, { title: 'Hello, world!' });API overview
Task Lists
api.lists.list() // GoogleTaskList[]
api.lists.get(listId) // GoogleTaskList
api.lists.create({ title }) // GoogleTaskList
api.lists.update(listId, { title }) // GoogleTaskList (PUT — replaces)
api.lists.patch(listId, { title }) // GoogleTaskList (PATCH — partial)
api.lists.delete(listId) // void
api.lists.rename(listId, newTitle) // GoogleTaskList (alias for update)Tasks
api.tasks.list(listId, options?) // { tasks, nextPageToken? }
api.tasks.get(listId, taskId) // GoogleTask
api.tasks.create(listId, task) // GoogleTask
api.tasks.update(listId, taskId, patch) // GoogleTask (PATCH — partial)
api.tasks.delete(listId, taskId) // void
api.tasks.move(listId, taskId, parent?, previousSibling?) // GoogleTask
api.tasks.clearCompleted(listId) // voidPagination
let pageToken: string | undefined;
do {
const { tasks, nextPageToken } = await api.tasks.list(listId, { pageToken });
// ...process tasks...
pageToken = nextPageToken;
} while (pageToken);Field masking
const { tasks } = await api.tasks.list(listId, {
fields: 'items(id,title,due,status),nextPageToken',
});Custom AuthProvider
import type { AuthProvider } from '@dotwalker-com/gootasks-client';
const auth: AuthProvider = {
async getAccessToken(): Promise<string> {
// Browser: Google Identity Services
// Server: google-auth-library
// Custom: any OAuth flow
return 'ya29.a0AcM...';
},
};Custom CacheProvider
import type { CacheProvider } from '@dotwalker-com/gootasks-client';
const cache: CacheProvider = {
get<T>(key: string): T | undefined {
return yourCacheStore.get(key);
},
set<T>(key: string, value: T, ttlMs: number): void {
yourCacheStore.set(key, value, ttlMs);
},
clear(pattern?: string): void {
yourCacheStore.clear(pattern);
},
};Error handling
import { GoogleTasksError, RateLimitError, TaskNotFoundError } from '@dotwalker-com/gootasks-client';
try {
await api.tasks.get(listId, taskId);
} catch (err) {
if (err instanceof TaskNotFoundError) {
// Task was deleted remotely
} else if (err instanceof RateLimitError) {
// Google's API throttled us — `Retry-After` was exceeded
} else if (err instanceof GoogleTasksError) {
// Other Google Tasks API error
} else {
throw err; // Unknown — propagate
}
}Requirements
- Node.js 18 or higher (for the global
fetchAPI). - TypeScript 5.0 or higher (strict mode recommended).
Development
pnpm install
pnpm test # run tests
pnpm test:watch # watch mode
pnpm type-check # tsc --noEmit
pnpm lint # eslint
pnpm build # build to dist/See RELEASE.md for the release checklist and security policy.
License
MIT © dotwalker-com
Related
- COVERAGE.md — Google Tasks API endpoint coverage matrix.
- docs/PARITY.md — behavioral parity matrix vs the original Kanbris code.
- kanbris-app — the kanban app that consumes this library (dogfooding).
