sunsama-api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +215 -0
  3. package/dist/cjs/client/index.js +347 -0
  4. package/dist/cjs/client/index.js.map +1 -0
  5. package/dist/cjs/errors/index.js +110 -0
  6. package/dist/cjs/errors/index.js.map +1 -0
  7. package/dist/cjs/index.js +21 -0
  8. package/dist/cjs/index.js.map +1 -0
  9. package/dist/cjs/queries/fragments/index.js +9 -0
  10. package/dist/cjs/queries/fragments/index.js.map +1 -0
  11. package/dist/cjs/queries/fragments/stream.js +74 -0
  12. package/dist/cjs/queries/fragments/stream.js.map +1 -0
  13. package/dist/cjs/queries/fragments/task.js +500 -0
  14. package/dist/cjs/queries/fragments/task.js.map +1 -0
  15. package/dist/cjs/queries/index.js +11 -0
  16. package/dist/cjs/queries/index.js.map +1 -0
  17. package/dist/cjs/queries/streams.js +19 -0
  18. package/dist/cjs/queries/streams.js.map +1 -0
  19. package/dist/cjs/queries/tasks.js +41 -0
  20. package/dist/cjs/queries/tasks.js.map +1 -0
  21. package/dist/cjs/queries/user.js +472 -0
  22. package/dist/cjs/queries/user.js.map +1 -0
  23. package/dist/cjs/types/api.js +9 -0
  24. package/dist/cjs/types/api.js.map +1 -0
  25. package/dist/cjs/types/client.js +6 -0
  26. package/dist/cjs/types/client.js.map +1 -0
  27. package/dist/cjs/types/common.js +6 -0
  28. package/dist/cjs/types/common.js.map +1 -0
  29. package/dist/cjs/types/index.js +8 -0
  30. package/dist/cjs/types/index.js.map +1 -0
  31. package/dist/cjs/utils/index.js +63 -0
  32. package/dist/cjs/utils/index.js.map +1 -0
  33. package/dist/esm/client/index.js +348 -0
  34. package/dist/esm/client/index.js.map +1 -0
  35. package/dist/esm/errors/index.js +105 -0
  36. package/dist/esm/errors/index.js.map +1 -0
  37. package/dist/esm/index.js +16 -0
  38. package/dist/esm/index.js.map +1 -0
  39. package/dist/esm/queries/fragments/index.js +6 -0
  40. package/dist/esm/queries/fragments/index.js.map +1 -0
  41. package/dist/esm/queries/fragments/stream.js +71 -0
  42. package/dist/esm/queries/fragments/stream.js.map +1 -0
  43. package/dist/esm/queries/fragments/task.js +497 -0
  44. package/dist/esm/queries/fragments/task.js.map +1 -0
  45. package/dist/esm/queries/index.js +8 -0
  46. package/dist/esm/queries/index.js.map +1 -0
  47. package/dist/esm/queries/streams.js +16 -0
  48. package/dist/esm/queries/streams.js.map +1 -0
  49. package/dist/esm/queries/tasks.js +38 -0
  50. package/dist/esm/queries/tasks.js.map +1 -0
  51. package/dist/esm/queries/user.js +469 -0
  52. package/dist/esm/queries/user.js.map +1 -0
  53. package/dist/esm/types/api.js +8 -0
  54. package/dist/esm/types/api.js.map +1 -0
  55. package/dist/esm/types/client.js +5 -0
  56. package/dist/esm/types/client.js.map +1 -0
  57. package/dist/esm/types/common.js +5 -0
  58. package/dist/esm/types/common.js.map +1 -0
  59. package/dist/esm/types/index.js +7 -0
  60. package/dist/esm/types/index.js.map +1 -0
  61. package/dist/esm/utils/index.js +57 -0
  62. package/dist/esm/utils/index.js.map +1 -0
  63. package/dist/types/client/index.d.ts +109 -0
  64. package/dist/types/client/index.d.ts.map +1 -0
  65. package/dist/types/errors/index.d.ts +67 -0
  66. package/dist/types/errors/index.d.ts.map +1 -0
  67. package/dist/types/index.d.ts +14 -0
  68. package/dist/types/index.d.ts.map +1 -0
  69. package/dist/types/queries/fragments/index.d.ts +6 -0
  70. package/dist/types/queries/fragments/index.d.ts.map +1 -0
  71. package/dist/types/queries/fragments/stream.d.ts +5 -0
  72. package/dist/types/queries/fragments/stream.d.ts.map +1 -0
  73. package/dist/types/queries/fragments/task.d.ts +8 -0
  74. package/dist/types/queries/fragments/task.d.ts.map +1 -0
  75. package/dist/types/queries/index.d.ts +8 -0
  76. package/dist/types/queries/index.d.ts.map +1 -0
  77. package/dist/types/queries/streams.d.ts +5 -0
  78. package/dist/types/queries/streams.d.ts.map +1 -0
  79. package/dist/types/queries/tasks.d.ts +6 -0
  80. package/dist/types/queries/tasks.d.ts.map +1 -0
  81. package/dist/types/queries/user.d.ts +5 -0
  82. package/dist/types/queries/user.d.ts.map +1 -0
  83. package/dist/types/types/api.d.ts +838 -0
  84. package/dist/types/types/api.d.ts.map +1 -0
  85. package/dist/types/types/client.d.ts +30 -0
  86. package/dist/types/types/client.d.ts.map +1 -0
  87. package/dist/types/types/common.d.ts +58 -0
  88. package/dist/types/types/common.d.ts.map +1 -0
  89. package/dist/types/types/index.d.ts +9 -0
  90. package/dist/types/types/index.d.ts.map +1 -0
  91. package/dist/types/utils/index.d.ts +35 -0
  92. package/dist/types/utils/index.d.ts.map +1 -0
  93. package/package.json +90 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Robert Niimi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,215 @@
1
+ # Sunsama API TypeScript Wrapper
2
+
3
+ A comprehensive TypeScript wrapper for the Sunsama API, providing type-safe access to daily planning and task management functionality.
4
+
5
+ [![npm version](https://badge.fury.io/js/sunsama-api.svg)](https://www.npmjs.com/package/sunsama-api)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)
8
+
9
+ ## Features
10
+
11
+ - 🔒 **Type Safety**: Full TypeScript support with comprehensive type definitions
12
+ - 🚀 **Modern**: Built with modern JavaScript/TypeScript practices
13
+ - 📦 **Lightweight**: Minimal dependencies and optimized bundle size
14
+ - 🔧 **Developer Friendly**: Intuitive API design with excellent IDE support
15
+ - ✅ **Well Tested**: Comprehensive test coverage with Vitest
16
+ - 📚 **Documented**: Complete API documentation and examples
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install sunsama-api
22
+ ```
23
+
24
+ ```bash
25
+ yarn add sunsama-api
26
+ ```
27
+
28
+ ```bash
29
+ pnpm add sunsama-api
30
+ ```
31
+
32
+ ## Quick Start
33
+
34
+ ```typescript
35
+ import { SunsamaClient } from 'sunsama-api';
36
+
37
+ // Initialize the client
38
+ const client = new SunsamaClient();
39
+
40
+ // Example usage
41
+ async function example() {
42
+ try {
43
+ // Authenticate with email/password
44
+ await client.login('your-email@example.com', 'your-password');
45
+
46
+ // Get current user information
47
+ const user = await client.getUser();
48
+ console.log('User:', user.profile.firstname, user.profile.lastname);
49
+
50
+ // Get tasks for today
51
+ const today = new Date().toISOString().split('T')[0];
52
+ const tasks = await client.getTasksByDay(today);
53
+ console.log('Today\'s tasks:', tasks.length);
54
+
55
+ // Get backlog tasks
56
+ const backlog = await client.getTasksBacklog();
57
+ console.log('Backlog tasks:', backlog.length);
58
+
59
+ // Get streams/projects
60
+ const streams = await client.getStreamsByGroupId();
61
+ console.log('Streams:', streams.length);
62
+
63
+ // Get user's timezone
64
+ const timezone = await client.getUserTimezone();
65
+ console.log('Timezone:', timezone);
66
+
67
+ } catch (error) {
68
+ console.error('Error:', error);
69
+ }
70
+ }
71
+ ```
72
+
73
+ ## API Documentation
74
+
75
+ Full API documentation is available at [docs link - to be added].
76
+
77
+ ## Authentication
78
+
79
+ The client uses email/password authentication or session tokens:
80
+
81
+ ```typescript
82
+ // Method 1: Email/Password authentication
83
+ const client = new SunsamaClient();
84
+ await client.login('your-email@example.com', 'your-password');
85
+
86
+ // Method 2: Session token (if you have one)
87
+ const client = new SunsamaClient({
88
+ sessionToken: 'your-session-token'
89
+ });
90
+
91
+ // Check authentication status
92
+ const isAuth = await client.isAuthenticated();
93
+ console.log('Authenticated:', isAuth);
94
+
95
+ // Logout
96
+ client.logout();
97
+ ```
98
+
99
+ ## API Methods
100
+
101
+ The client provides the following methods:
102
+
103
+ ### User Information
104
+ ```typescript
105
+ // Get current user details
106
+ const user = await client.getUser();
107
+ console.log(user.profile.firstname, user.profile.lastname);
108
+
109
+ // Get user's timezone
110
+ const timezone = await client.getUserTimezone();
111
+ ```
112
+
113
+ ### Tasks
114
+ ```typescript
115
+ // Get tasks for a specific day
116
+ const tasks = await client.getTasksByDay('2025-01-15');
117
+ const tasksWithTz = await client.getTasksByDay('2025-01-15', 'America/New_York');
118
+
119
+ // Get backlog tasks
120
+ const backlog = await client.getTasksBacklog();
121
+ ```
122
+
123
+ ### Streams (Channels)
124
+ ```typescript
125
+ // Get all streams for the user's group
126
+ const streams = await client.getStreamsByGroupId();
127
+ streams.forEach(stream => {
128
+ console.log(stream.streamName, stream.color);
129
+ });
130
+ ```
131
+
132
+ ## Error Handling
133
+
134
+ The wrapper provides structured error handling:
135
+
136
+ ```typescript
137
+ import { SunsamaError, SunsamaAuthError, SunsamaApiError } from 'sunsama-api';
138
+
139
+ try {
140
+ await client.login('email@example.com', 'password');
141
+ const user = await client.getUser();
142
+ } catch (error) {
143
+ if (error instanceof SunsamaAuthError) {
144
+ console.error('Authentication Error:', error.message);
145
+ } else if (error instanceof SunsamaApiError) {
146
+ console.error('API Error:', error.message, error.status);
147
+ } else if (error instanceof SunsamaError) {
148
+ console.error('Client Error:', error.message);
149
+ } else {
150
+ console.error('Unknown Error:', error);
151
+ }
152
+ }
153
+ ```
154
+
155
+ ## Development
156
+
157
+ This project uses modern development tools:
158
+
159
+ - **TypeScript** for type safety
160
+ - **Vitest** for testing
161
+ - **ESLint + Prettier** for code quality
162
+ - **pnpm** for package management
163
+ - **Changesets** for version management
164
+
165
+ ### Setup
166
+
167
+ ```bash
168
+ # Clone the repository
169
+ git clone https://github.com/robertn702/sunsama-api.git
170
+ cd sunsama-api
171
+
172
+ # Install dependencies
173
+ pnpm install
174
+
175
+ # Run tests
176
+ pnpm test
177
+
178
+ # Build the package
179
+ pnpm build
180
+
181
+ # Run linting
182
+ pnpm lint
183
+ ```
184
+
185
+ ### Scripts
186
+
187
+ - `pnpm build` - Build the package for distribution
188
+ - `pnpm dev` - Start development mode with watch
189
+ - `pnpm test` - Run the test suite
190
+ - `pnpm test:coverage` - Run tests with coverage report
191
+ - `pnpm lint` - Lint the codebase
192
+ - `pnpm format` - Format code with Prettier
193
+
194
+ ## Contributing
195
+
196
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
197
+
198
+ ## License
199
+
200
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
201
+
202
+ ## Disclaimer
203
+
204
+ This is an unofficial wrapper for the Sunsama API. It is not affiliated with or endorsed by Sunsama.
205
+
206
+ ## Support
207
+
208
+ If you encounter any issues or have questions:
209
+
210
+ 1. Search [existing issues](https://github.com/robertn702/sunsama-api/issues)
211
+ 2. Create a [new issue](https://github.com/robertn702/sunsama-api/issues/new)
212
+
213
+ ---
214
+
215
+ Made with ❤️ for the Sunsama community
@@ -0,0 +1,347 @@
1
+ "use strict";
2
+ /**
3
+ * Main Sunsama API client
4
+ *
5
+ * Provides a type-safe interface to interact with all Sunsama API endpoints.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.SunsamaClient = void 0;
9
+ const graphql_1 = require("graphql");
10
+ const tough_cookie_1 = require("tough-cookie");
11
+ const errors_1 = require("../errors");
12
+ const queries_1 = require("../queries");
13
+ /**
14
+ * Main Sunsama API client class
15
+ *
16
+ * Provides a type-safe interface to interact with all Sunsama API endpoints.
17
+ */
18
+ class SunsamaClient {
19
+ /**
20
+ * Creates a new Sunsama client instance
21
+ *
22
+ * @param config - Client configuration options (optional)
23
+ */
24
+ constructor(config = {}) {
25
+ this.config = config;
26
+ this.cookieJar = new tough_cookie_1.CookieJar();
27
+ // If a session token is provided, set it as a cookie
28
+ if (config.sessionToken) {
29
+ this.setSessionTokenAsCookie(config.sessionToken);
30
+ }
31
+ }
32
+ /**
33
+ * Gets the current client configuration
34
+ */
35
+ getConfig() {
36
+ return { ...this.config };
37
+ }
38
+ /**
39
+ * Checks if the client is authenticated
40
+ *
41
+ * @returns True if cookies are present in the jar
42
+ */
43
+ async isAuthenticated() {
44
+ const cookies = await this.cookieJar.getCookies(SunsamaClient.BASE_URL);
45
+ return cookies.some(cookie => cookie.key === 'sunsamaSession');
46
+ }
47
+ /**
48
+ * Authenticates with email and password
49
+ *
50
+ * @param email - User email address
51
+ * @param password - User password
52
+ * @throws SunsamaAuthError if login fails
53
+ */
54
+ async login(email, password) {
55
+ // Prepare form data
56
+ const formData = new URLSearchParams();
57
+ formData.append('email', email);
58
+ formData.append('password', password);
59
+ try {
60
+ // For login, we need to handle redirects manually to capture the session cookie
61
+ const loginUrl = `${SunsamaClient.BASE_URL}/account/login/email`;
62
+ // Get cookies from jar for this URL
63
+ const cookies = await this.cookieJar.getCookies(loginUrl);
64
+ const headers = {
65
+ 'Content-Type': 'application/x-www-form-urlencoded',
66
+ Origin: 'https://app.sunsama.com',
67
+ };
68
+ if (cookies.length > 0) {
69
+ headers['Cookie'] = cookies.map(cookie => cookie.cookieString()).join('; ');
70
+ }
71
+ const response = await fetch(loginUrl, {
72
+ method: 'POST',
73
+ headers,
74
+ body: formData.toString(),
75
+ redirect: 'manual', // Don't follow redirects automatically
76
+ });
77
+ // For login, we expect a 302 redirect on success
78
+ if (response.status !== 302) {
79
+ const responseText = await response.text();
80
+ throw new errors_1.SunsamaAuthError(`Login failed: ${response.status} ${response.statusText}. Response: ${responseText}`);
81
+ }
82
+ // Extract and store cookies from response
83
+ const setCookieHeader = response.headers.get('set-cookie');
84
+ if (!setCookieHeader) {
85
+ // Debug: print all response headers
86
+ const allHeaders = {};
87
+ response.headers.forEach((value, key) => {
88
+ allHeaders[key] = value;
89
+ });
90
+ throw new errors_1.SunsamaAuthError(`No session cookie received from login. Response headers: ${JSON.stringify(allHeaders, null, 2)}`);
91
+ }
92
+ // Store the cookie in the jar
93
+ try {
94
+ const loginUrl = `${SunsamaClient.BASE_URL}/account/login/email`;
95
+ await this.cookieJar.setCookie(setCookieHeader, loginUrl);
96
+ }
97
+ catch (error) {
98
+ throw new errors_1.SunsamaAuthError(`Failed to store session cookie: ${error instanceof Error ? error.message : 'Unknown error'}`);
99
+ }
100
+ }
101
+ catch (error) {
102
+ if (error instanceof errors_1.SunsamaAuthError) {
103
+ throw error;
104
+ }
105
+ throw new errors_1.SunsamaAuthError(`Login request failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
106
+ }
107
+ }
108
+ /**
109
+ * Clears all cookies from the jar and cached user data
110
+ */
111
+ logout() {
112
+ this.cookieJar.removeAllCookiesSync();
113
+ this.userId = undefined;
114
+ this.groupId = undefined;
115
+ this.timezone = undefined;
116
+ }
117
+ /**
118
+ * Makes an authenticated request to the Sunsama API
119
+ *
120
+ * @param path - The API endpoint path (e.g., '/tasks')
121
+ * @param options - Request options
122
+ * @returns The response from the API
123
+ * @internal
124
+ */
125
+ async request(path, options) {
126
+ const url = `${SunsamaClient.BASE_URL}${path}`;
127
+ // Build headers
128
+ const headers = {
129
+ Origin: 'https://app.sunsama.com',
130
+ ...options.headers,
131
+ };
132
+ // Get cookies from jar for this URL
133
+ const cookies = await this.cookieJar.getCookies(url);
134
+ if (cookies.length > 0) {
135
+ headers['Cookie'] = cookies.map(cookie => cookie.cookieString()).join('; ');
136
+ }
137
+ // Build query string if params provided
138
+ let fullUrl = url;
139
+ if (options.params) {
140
+ const params = new URLSearchParams();
141
+ Object.entries(options.params).forEach(([key, value]) => {
142
+ params.append(key, String(value));
143
+ });
144
+ fullUrl = `${url}?${params.toString()}`;
145
+ }
146
+ // Process request body
147
+ let body;
148
+ if (options.body instanceof URLSearchParams) {
149
+ body = options.body.toString();
150
+ }
151
+ else if (options.body) {
152
+ body = JSON.stringify(options.body);
153
+ }
154
+ // Make the request
155
+ return await fetch(fullUrl, {
156
+ method: options.method,
157
+ headers,
158
+ body,
159
+ });
160
+ }
161
+ /**
162
+ * Makes a GraphQL request to the Sunsama API
163
+ *
164
+ * @param request - The GraphQL request
165
+ * @returns The GraphQL response
166
+ * @internal
167
+ */
168
+ async graphqlRequest(request) {
169
+ // Convert DocumentNode to string if needed
170
+ const queryString = typeof request.query === 'string' ? request.query : (0, graphql_1.print)(request.query);
171
+ const requestBody = {
172
+ ...request,
173
+ query: queryString,
174
+ };
175
+ const response = await this.request('/graphql', {
176
+ method: 'POST',
177
+ headers: {
178
+ 'Content-Type': 'application/json',
179
+ Accept: 'application/json',
180
+ ...(request.operationName && { 'x-gql-operation-name': request.operationName }),
181
+ },
182
+ body: requestBody,
183
+ });
184
+ if (!response.ok) {
185
+ const responseText = await response.text();
186
+ throw new errors_1.SunsamaAuthError(`GraphQL request failed: ${response.status} ${response.statusText}. Response: ${responseText}`);
187
+ }
188
+ const result = (await response.json());
189
+ if (result.errors && result.errors.length > 0) {
190
+ throw new errors_1.SunsamaAuthError(`GraphQL errors: ${result.errors.map(e => e.message).join(', ')}`);
191
+ }
192
+ return result;
193
+ }
194
+ /**
195
+ * Gets the current user information
196
+ *
197
+ * @returns The current user data
198
+ * @throws SunsamaAuthError if not authenticated or request fails
199
+ */
200
+ async getUser() {
201
+ const request = {
202
+ operationName: 'getUser',
203
+ variables: {},
204
+ query: queries_1.GET_USER_QUERY,
205
+ };
206
+ const response = await this.graphqlRequest(request);
207
+ if (!response.data) {
208
+ throw new errors_1.SunsamaAuthError('No user data received');
209
+ }
210
+ const user = response.data.currentUser;
211
+ // Cache user ID, group ID, and timezone for future requests
212
+ this.userId = user._id;
213
+ this.groupId = user.primaryGroup?.groupId;
214
+ this.timezone = user.profile.timezone;
215
+ return user;
216
+ }
217
+ /**
218
+ * Gets tasks for a specific day
219
+ *
220
+ * @param day - ISO date string (e.g., "2025-05-31")
221
+ * @param timezone - Timezone string (e.g., "America/New_York", defaults to user's timezone)
222
+ * @returns Array of tasks for the specified day
223
+ * @throws SunsamaAuthError if not authenticated or request fails
224
+ */
225
+ async getTasksByDay(day, timezone) {
226
+ // Use cached values if available, otherwise fetch user data
227
+ if (!this.userId || !this.groupId) {
228
+ await this.getUser();
229
+ }
230
+ const userTimezone = timezone || this.timezone || 'UTC';
231
+ if (!this.groupId) {
232
+ throw new errors_1.SunsamaAuthError('Unable to determine group ID from user data. User primaryGroup is required.');
233
+ }
234
+ const variables = {
235
+ day,
236
+ timezone: userTimezone,
237
+ userId: this.userId,
238
+ groupId: this.groupId,
239
+ };
240
+ const request = {
241
+ operationName: 'getTasksByDay',
242
+ variables: { input: variables },
243
+ query: queries_1.GET_TASKS_BY_DAY_QUERY,
244
+ };
245
+ const response = await this.graphqlRequest(request);
246
+ if (!response.data) {
247
+ throw new errors_1.SunsamaAuthError('No task data received');
248
+ }
249
+ return response.data.tasksByDayV2;
250
+ }
251
+ /**
252
+ * Gets tasks from the backlog
253
+ *
254
+ * @returns Array of backlog tasks
255
+ * @throws SunsamaAuthError if not authenticated or request fails
256
+ */
257
+ async getTasksBacklog() {
258
+ // Use cached values if available, otherwise fetch user data
259
+ if (!this.userId || !this.groupId) {
260
+ await this.getUser();
261
+ }
262
+ if (!this.groupId) {
263
+ throw new errors_1.SunsamaAuthError('Unable to determine group ID from user data. User primaryGroup is required.');
264
+ }
265
+ const variables = {
266
+ userId: this.userId,
267
+ groupId: this.groupId,
268
+ };
269
+ const request = {
270
+ operationName: 'getTasksBacklog',
271
+ variables,
272
+ query: queries_1.GET_TASKS_BACKLOG_QUERY,
273
+ };
274
+ const response = await this.graphqlRequest(request);
275
+ if (!response.data) {
276
+ throw new errors_1.SunsamaAuthError('No backlog data received');
277
+ }
278
+ return response.data.tasksBacklog;
279
+ }
280
+ /**
281
+ * Gets streams for the user's group
282
+ *
283
+ * @returns Array of streams for the user's group
284
+ * @throws SunsamaAuthError if not authenticated or request fails
285
+ */
286
+ async getStreamsByGroupId() {
287
+ // Use cached values if available, otherwise fetch user data
288
+ if (!this.groupId) {
289
+ await this.getUser();
290
+ }
291
+ if (!this.groupId) {
292
+ throw new errors_1.SunsamaAuthError('Unable to determine group ID from user data. User primaryGroup is required.');
293
+ }
294
+ const request = {
295
+ operationName: 'getStreamsByGroupId',
296
+ variables: { groupId: this.groupId },
297
+ query: queries_1.GET_STREAMS_BY_GROUP_ID_QUERY,
298
+ };
299
+ const response = await this.graphqlRequest(request);
300
+ if (!response.data) {
301
+ throw new errors_1.SunsamaAuthError('No stream data received');
302
+ }
303
+ return response.data.streamsByGroupId;
304
+ }
305
+ /**
306
+ * Gets the user's timezone
307
+ *
308
+ * @returns The user's timezone string (e.g., "America/New_York")
309
+ * @throws SunsamaAuthError if not authenticated or request fails
310
+ */
311
+ async getUserTimezone() {
312
+ // Use cached timezone if available, otherwise fetch user data
313
+ if (!this.timezone) {
314
+ await this.getUser();
315
+ }
316
+ if (!this.timezone) {
317
+ throw new errors_1.SunsamaAuthError('Unable to determine timezone from user data. User profile.timezone is required.');
318
+ }
319
+ return this.timezone;
320
+ }
321
+ /**
322
+ * Sets a session token as a cookie in the jar
323
+ *
324
+ * @param token - The session token to set
325
+ * @internal
326
+ */
327
+ setSessionTokenAsCookie(token) {
328
+ try {
329
+ const cookie = new tough_cookie_1.Cookie({
330
+ key: 'sunsamaSession',
331
+ value: token,
332
+ domain: 'api.sunsama.com',
333
+ path: '/',
334
+ httpOnly: true,
335
+ secure: true,
336
+ });
337
+ this.cookieJar.setCookieSync(cookie, SunsamaClient.BASE_URL);
338
+ }
339
+ catch (error) {
340
+ // Silently fail if cookie cannot be set
341
+ // Note: Error intentionally ignored to avoid breaking authentication flow
342
+ }
343
+ }
344
+ }
345
+ exports.SunsamaClient = SunsamaClient;
346
+ SunsamaClient.BASE_URL = 'https://api.sunsama.com';
347
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"}