Skip to content

feat: add Sunsama API TypeScript wrapper as workspace package - #3

Open
devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1777912579-add-sunsama-api
Open

feat: add Sunsama API TypeScript wrapper as workspace package#3
devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1777912579-add-sunsama-api

Conversation

@devin-ai-integration

Copy link
Copy Markdown

Summary

Thêm package @workspace/sunsama-api vào monorepo tại lib/integrations/sunsama-api/, dựa trên robertn702/sunsama-api.

Package này cung cấp TypeScript wrapper type-safe cho Sunsama GraphQL API, hỗ trợ quản lý công việc hàng ngày (daily planning & task management).

Tính năng chính:

  • SunsamaClient với xác thực email/password hoặc session token
  • CRUD tasks: tạo, xóa, hoàn thành, cập nhật text/notes/stream/due date
  • Quản lý subtasks: tạo, đổi tên, hoàn thành/bỏ hoàn thành
  • Lên lịch & sắp xếp thứ tự task trong ngày
  • Tạo & cập nhật calendar events (sync với Google Calendar, v.v.)
  • Collaborative editing với Yjs cho task notes
  • Chuyển đổi HTML ↔ Markdown
  • Validation input với Zod
  • Sinh task ID kiểu MongoDB ObjectId

Cấu trúc:

lib/integrations/sunsama-api/
├── package.json          # @workspace/sunsama-api
├── tsconfig.json
└── src/
    ├── client/           # SunsamaClient (inheritance chain)
    │   ├── base.ts       # Auth, HTTP, session management
    │   ├── index.ts      # Assembled client class
    │   └── methods/      # Domain-specific methods
    ├── queries/          # GraphQL queries & mutations
    ├── types/            # TypeScript type definitions
    ├── errors/           # Custom error hierarchy
    └── utils/            # Validation, conversion, dates, collab

Sử dụng trong các package khác:

import { SunsamaClient } from '@workspace/sunsama-api';

const client = new SunsamaClient();
await client.login('email', 'password');
const tasks = await client.getTasksByDay('2026-05-04');

Review & Testing Checklist for Human

  • Verify pnpm installpnpm run typecheck pass thành công
  • Kiểm tra @workspace/sunsama-api có thể import được từ các package khác (ví dụ: api-server)
  • Test thử kết nối với Sunsama API bằng credentials thật (login + getUser)

Notes

  • Package được đặt ở lib/integrations/sunsama-api/ theo workspace pattern lib/integrations/* đã có sẵn trong pnpm-workspace.yaml
  • Build artifacts (dist/, *.tsbuildinfo) đã được gitignore
  • Không bao gồm test files từ repo gốc — có thể thêm sau nếu cần

Link to Devin session: https://app.devin.ai/sessions/03643b5d5c78409099bb9567ea048010
Requested by: @TanUIUX

Add @workspace/sunsama-api integration library based on robertn702/sunsama-api.
Provides type-safe access to Sunsama's GraphQL API for daily planning and task
management.

Features:
- Full TypeScript support with comprehensive type definitions
- GraphQL client with cookie-based authentication
- Task CRUD, scheduling, reordering, and subtask management
- Calendar event creation and updates
- Yjs-powered collaborative editing for task notes
- HTML/Markdown conversion utilities
- Zod validation for input safety
- MongoDB ObjectId-style task ID generation

Co-Authored-By: adamer <adamer@hunght1890.com>
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

View 6 additional findings in Devin Review.

Open in Devin Review

sequence: null,
followers: [],
recommendedTimeEstimate: null,
timeEstimate: options?.timeEstimate || null,

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 timeEstimate: 0 silently converted to null due to || operator

At task-lifecycle.ts:333, options?.timeEstimate || null uses the logical OR operator, which treats 0 as falsy. If a user passes timeEstimate: 0 to explicitly set zero minutes (e.g., to clear the estimate on a new task), it gets converted to null ("no estimate"). The updateTaskPlannedTime method at task-updates.ts:256-257 explicitly documents 0 as a valid value for clearing the time estimate, confirming that 0 is semantically meaningful. The nullish coalescing operator ?? should be used instead.

Suggested change
timeEstimate: options?.timeEstimate || null,
timeEstimate: options?.timeEstimate ?? null,
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

* @internal
*/
private static getNextCounter(): number {
SunsamaClientBase._counter = (SunsamaClientBase._counter + 1) % 0xffffff;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 ObjectId counter off-by-one: % 0xffffff never produces the max 3-byte value

In the getNextCounter method, (counter + 1) % 0xffffff produces values in the range [0, 0xfffffe] (0 to 16777214), skipping 0xffffff (16777215). A 3-byte counter should cover the full range [0, 0xffffff], so the modulus should be 0x1000000 (16777216). Additionally, the initial value at base.ts:301 (Math.floor(Math.random() * 0xffffff)) also never produces 0xffffff; it should be Math.floor(Math.random() * 0x1000000).

Suggested change
SunsamaClientBase._counter = (SunsamaClientBase._counter + 1) % 0xffffff;
SunsamaClientBase._counter = (SunsamaClientBase._counter + 1) % 0x1000000;
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

- Fix ObjectId counter off-by-one: use 0x1000000 modulus to cover full 3-byte range
- Fix timeEstimate: use ?? instead of || so 0 is not silently converted to null

Co-Authored-By: adamer <adamer@hunght1890.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant