@loculabs/api-client 1.0.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.
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/index.d.mts +1075 -0
- package/dist/index.d.ts +1075 -0
- package/dist/index.js +259 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +227 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +78 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1075 @@
|
|
|
1
|
+
interface components {
|
|
2
|
+
schemas: {
|
|
3
|
+
/** @description Task description in multiple formats */
|
|
4
|
+
TaskDescription: {
|
|
5
|
+
/** @description Description content as Markdown */
|
|
6
|
+
markdown: string;
|
|
7
|
+
/** @description Description content as HTML (only included when includeHtml=true) */
|
|
8
|
+
html?: string;
|
|
9
|
+
/**
|
|
10
|
+
* @description ProseMirror JSON document. Root node always has type "doc" with a content array of child nodes.
|
|
11
|
+
* @example {
|
|
12
|
+
* "type": "doc",
|
|
13
|
+
* "content": [
|
|
14
|
+
* {
|
|
15
|
+
* "type": "paragraph",
|
|
16
|
+
* "content": [
|
|
17
|
+
* {
|
|
18
|
+
* "type": "text",
|
|
19
|
+
* "text": "Hello "
|
|
20
|
+
* },
|
|
21
|
+
* {
|
|
22
|
+
* "type": "text",
|
|
23
|
+
* "text": "world",
|
|
24
|
+
* "marks": [
|
|
25
|
+
* {
|
|
26
|
+
* "type": "bold"
|
|
27
|
+
* }
|
|
28
|
+
* ]
|
|
29
|
+
* }
|
|
30
|
+
* ]
|
|
31
|
+
* }
|
|
32
|
+
* ]
|
|
33
|
+
* }
|
|
34
|
+
*/
|
|
35
|
+
json?: {
|
|
36
|
+
/**
|
|
37
|
+
* @description Document root type, always "doc"
|
|
38
|
+
* @enum {string}
|
|
39
|
+
*/
|
|
40
|
+
type: "doc";
|
|
41
|
+
/** @description Array of child document nodes */
|
|
42
|
+
content: {
|
|
43
|
+
/** @description Node type (e.g., "paragraph", "text", "heading", "bulletList") */
|
|
44
|
+
type: string;
|
|
45
|
+
/** @description Node attributes */
|
|
46
|
+
attrs?: {
|
|
47
|
+
[key: string]: (string | null) | number | boolean;
|
|
48
|
+
};
|
|
49
|
+
/** @description Child nodes (recursive DocumentNode array) */
|
|
50
|
+
content?: Record<string, never>[];
|
|
51
|
+
/** @description Text content (only for text nodes) */
|
|
52
|
+
text?: string;
|
|
53
|
+
/** @description Text marks (bold, italic, links, etc.) - only for text nodes */
|
|
54
|
+
marks?: {
|
|
55
|
+
/** @description Mark type (e.g., "bold", "italic", "link") */
|
|
56
|
+
type: string;
|
|
57
|
+
/** @description Mark attributes */
|
|
58
|
+
attrs?: {
|
|
59
|
+
[key: string]: (string | null) | number | boolean;
|
|
60
|
+
};
|
|
61
|
+
}[];
|
|
62
|
+
}[];
|
|
63
|
+
};
|
|
64
|
+
/** @description Description content as plain text */
|
|
65
|
+
plainText: string;
|
|
66
|
+
} | null;
|
|
67
|
+
LocuTask: {
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
done: "completed" | "canceled" | unknown;
|
|
71
|
+
doneAt: number | null;
|
|
72
|
+
createdAt: number;
|
|
73
|
+
parent: {
|
|
74
|
+
id: string;
|
|
75
|
+
order: number | null;
|
|
76
|
+
} | null;
|
|
77
|
+
waiting?: {
|
|
78
|
+
reason?: string;
|
|
79
|
+
waitingAt: number;
|
|
80
|
+
} | null;
|
|
81
|
+
projectId?: string | null;
|
|
82
|
+
cursorAgentUrl?: string | null;
|
|
83
|
+
integrationId: unknown;
|
|
84
|
+
slackLink?: string;
|
|
85
|
+
/**
|
|
86
|
+
* @default locu
|
|
87
|
+
* @enum {string}
|
|
88
|
+
*/
|
|
89
|
+
type: "locu";
|
|
90
|
+
description?: components["schemas"]["TaskDescription"];
|
|
91
|
+
};
|
|
92
|
+
LinearTask: {
|
|
93
|
+
id: string;
|
|
94
|
+
name: string;
|
|
95
|
+
done: "completed" | "canceled" | unknown;
|
|
96
|
+
doneAt: number | null;
|
|
97
|
+
createdAt: number;
|
|
98
|
+
parent: {
|
|
99
|
+
id: string;
|
|
100
|
+
order: number | null;
|
|
101
|
+
} | null;
|
|
102
|
+
waiting?: {
|
|
103
|
+
reason?: string;
|
|
104
|
+
waitingAt: number;
|
|
105
|
+
} | null;
|
|
106
|
+
projectId?: string | null;
|
|
107
|
+
cursorAgentUrl?: string | null;
|
|
108
|
+
integrationId: string;
|
|
109
|
+
number: number;
|
|
110
|
+
priority?: number;
|
|
111
|
+
organizationId: string;
|
|
112
|
+
teamId: string;
|
|
113
|
+
description?: components["schemas"]["TaskDescription"];
|
|
114
|
+
assignee: {
|
|
115
|
+
id: string;
|
|
116
|
+
name: string;
|
|
117
|
+
} | null;
|
|
118
|
+
state: {
|
|
119
|
+
id: string;
|
|
120
|
+
type: string;
|
|
121
|
+
};
|
|
122
|
+
url: string;
|
|
123
|
+
identifier: string;
|
|
124
|
+
deletedInLinear: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* @default linear
|
|
127
|
+
* @enum {string}
|
|
128
|
+
*/
|
|
129
|
+
type: "linear";
|
|
130
|
+
};
|
|
131
|
+
JiraTask: {
|
|
132
|
+
id: string;
|
|
133
|
+
name: string;
|
|
134
|
+
done: "completed" | "canceled" | unknown;
|
|
135
|
+
doneAt: number | null;
|
|
136
|
+
createdAt: number;
|
|
137
|
+
parent: {
|
|
138
|
+
id: string;
|
|
139
|
+
order: number | null;
|
|
140
|
+
} | null;
|
|
141
|
+
waiting?: {
|
|
142
|
+
reason?: string;
|
|
143
|
+
waitingAt: number;
|
|
144
|
+
} | null;
|
|
145
|
+
projectId: string;
|
|
146
|
+
cursorAgentUrl?: string | null;
|
|
147
|
+
integrationId: string;
|
|
148
|
+
description?: components["schemas"]["TaskDescription"];
|
|
149
|
+
assignee: {
|
|
150
|
+
id: string;
|
|
151
|
+
avatar?: string;
|
|
152
|
+
name: string;
|
|
153
|
+
} | null;
|
|
154
|
+
issueType: {
|
|
155
|
+
id: string;
|
|
156
|
+
name: string;
|
|
157
|
+
icon: string;
|
|
158
|
+
};
|
|
159
|
+
state: {
|
|
160
|
+
id: string;
|
|
161
|
+
name: string;
|
|
162
|
+
statusCategory: {
|
|
163
|
+
id: number;
|
|
164
|
+
key: string;
|
|
165
|
+
name: string;
|
|
166
|
+
color: string;
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
url: string;
|
|
170
|
+
identifier: string;
|
|
171
|
+
deletedInJira: boolean;
|
|
172
|
+
/**
|
|
173
|
+
* @default jira
|
|
174
|
+
* @enum {string}
|
|
175
|
+
*/
|
|
176
|
+
type: "jira";
|
|
177
|
+
};
|
|
178
|
+
Task: components["schemas"]["LocuTask"] | components["schemas"]["LinearTask"] | components["schemas"]["JiraTask"];
|
|
179
|
+
Note: {
|
|
180
|
+
id: string;
|
|
181
|
+
text: string;
|
|
182
|
+
name: string;
|
|
183
|
+
/** @default null */
|
|
184
|
+
icon: string | null;
|
|
185
|
+
/** @default null */
|
|
186
|
+
color: string | null;
|
|
187
|
+
/** @default null */
|
|
188
|
+
parent: {
|
|
189
|
+
id: string;
|
|
190
|
+
type: "folder" | "virtual-folder";
|
|
191
|
+
} | null;
|
|
192
|
+
createdAt?: number;
|
|
193
|
+
updatedAt?: number;
|
|
194
|
+
/** @description Note content as Markdown */
|
|
195
|
+
markdown: string;
|
|
196
|
+
/** @description Note content as HTML (only included when includeHtml=true) */
|
|
197
|
+
html?: string;
|
|
198
|
+
/**
|
|
199
|
+
* @description ProseMirror JSON document. Root node always has type "doc" with a content array of child nodes.
|
|
200
|
+
* @example {
|
|
201
|
+
* "type": "doc",
|
|
202
|
+
* "content": [
|
|
203
|
+
* {
|
|
204
|
+
* "type": "paragraph",
|
|
205
|
+
* "content": [
|
|
206
|
+
* {
|
|
207
|
+
* "type": "text",
|
|
208
|
+
* "text": "Hello "
|
|
209
|
+
* },
|
|
210
|
+
* {
|
|
211
|
+
* "type": "text",
|
|
212
|
+
* "text": "world",
|
|
213
|
+
* "marks": [
|
|
214
|
+
* {
|
|
215
|
+
* "type": "bold"
|
|
216
|
+
* }
|
|
217
|
+
* ]
|
|
218
|
+
* }
|
|
219
|
+
* ]
|
|
220
|
+
* }
|
|
221
|
+
* ]
|
|
222
|
+
* }
|
|
223
|
+
*/
|
|
224
|
+
json?: {
|
|
225
|
+
/**
|
|
226
|
+
* @description Document root type, always "doc"
|
|
227
|
+
* @enum {string}
|
|
228
|
+
*/
|
|
229
|
+
type: "doc";
|
|
230
|
+
/** @description Array of child document nodes */
|
|
231
|
+
content: {
|
|
232
|
+
/** @description Node type (e.g., "paragraph", "text", "heading", "bulletList") */
|
|
233
|
+
type: string;
|
|
234
|
+
/** @description Node attributes */
|
|
235
|
+
attrs?: {
|
|
236
|
+
[key: string]: (string | null) | number | boolean;
|
|
237
|
+
};
|
|
238
|
+
/** @description Child nodes (recursive DocumentNode array) */
|
|
239
|
+
content?: Record<string, never>[];
|
|
240
|
+
/** @description Text content (only for text nodes) */
|
|
241
|
+
text?: string;
|
|
242
|
+
/** @description Text marks (bold, italic, links, etc.) - only for text nodes */
|
|
243
|
+
marks?: {
|
|
244
|
+
/** @description Mark type (e.g., "bold", "italic", "link") */
|
|
245
|
+
type: string;
|
|
246
|
+
/** @description Mark attributes */
|
|
247
|
+
attrs?: {
|
|
248
|
+
[key: string]: (string | null) | number | boolean;
|
|
249
|
+
};
|
|
250
|
+
}[];
|
|
251
|
+
}[];
|
|
252
|
+
};
|
|
253
|
+
/** @description Note content as plain text */
|
|
254
|
+
plainText: string;
|
|
255
|
+
};
|
|
256
|
+
NoteListResponse: {
|
|
257
|
+
data: components["schemas"]["Note"][];
|
|
258
|
+
nextCursor: string | null;
|
|
259
|
+
hasMore: boolean;
|
|
260
|
+
};
|
|
261
|
+
ErrorResponse: {
|
|
262
|
+
error: string;
|
|
263
|
+
message: string;
|
|
264
|
+
code?: string;
|
|
265
|
+
};
|
|
266
|
+
CreateNoteRequest: {
|
|
267
|
+
/**
|
|
268
|
+
* Format: uuid
|
|
269
|
+
* @description Optional custom ID for the note
|
|
270
|
+
*/
|
|
271
|
+
id?: string;
|
|
272
|
+
/** @description Initial markdown text content */
|
|
273
|
+
text: string;
|
|
274
|
+
/** @description Icon for the note: Lucide icon name (e.g., "FileText") or emoji shortcode (e.g., ":memo:") */
|
|
275
|
+
icon?: string | null;
|
|
276
|
+
/** @description Hex color for the icon (e.g., "#FF5733"). Only applies to Lucide icons, not emojis. */
|
|
277
|
+
color?: string | null;
|
|
278
|
+
/** @description Parent folder ID */
|
|
279
|
+
folderId?: string;
|
|
280
|
+
};
|
|
281
|
+
UpdateNoteRequest: {
|
|
282
|
+
/** @description New text content for the note */
|
|
283
|
+
text?: string;
|
|
284
|
+
/** @description New icon for the note: Lucide icon name (e.g., "FileText") or emoji shortcode (e.g., ":memo:") */
|
|
285
|
+
icon?: string | null;
|
|
286
|
+
/** @description New hex color for the icon (e.g., "#FF5733"). Only applies to Lucide icons, not emojis. */
|
|
287
|
+
color?: string | null;
|
|
288
|
+
/** @description New parent folder ID */
|
|
289
|
+
folderId?: string | null;
|
|
290
|
+
};
|
|
291
|
+
DeleteNoteResponse: {
|
|
292
|
+
success: boolean;
|
|
293
|
+
};
|
|
294
|
+
/** @description Project description in multiple formats */
|
|
295
|
+
ProjectDescription: {
|
|
296
|
+
/** @description Description content as Markdown */
|
|
297
|
+
markdown: string;
|
|
298
|
+
/** @description Description content as HTML (only included when includeHtml=true) */
|
|
299
|
+
html?: string;
|
|
300
|
+
/**
|
|
301
|
+
* @description ProseMirror JSON document. Root node always has type "doc" with a content array of child nodes.
|
|
302
|
+
* @example {
|
|
303
|
+
* "type": "doc",
|
|
304
|
+
* "content": [
|
|
305
|
+
* {
|
|
306
|
+
* "type": "paragraph",
|
|
307
|
+
* "content": [
|
|
308
|
+
* {
|
|
309
|
+
* "type": "text",
|
|
310
|
+
* "text": "Hello "
|
|
311
|
+
* },
|
|
312
|
+
* {
|
|
313
|
+
* "type": "text",
|
|
314
|
+
* "text": "world",
|
|
315
|
+
* "marks": [
|
|
316
|
+
* {
|
|
317
|
+
* "type": "bold"
|
|
318
|
+
* }
|
|
319
|
+
* ]
|
|
320
|
+
* }
|
|
321
|
+
* ]
|
|
322
|
+
* }
|
|
323
|
+
* ]
|
|
324
|
+
* }
|
|
325
|
+
*/
|
|
326
|
+
json?: {
|
|
327
|
+
/**
|
|
328
|
+
* @description Document root type, always "doc"
|
|
329
|
+
* @enum {string}
|
|
330
|
+
*/
|
|
331
|
+
type: "doc";
|
|
332
|
+
/** @description Array of child document nodes */
|
|
333
|
+
content: {
|
|
334
|
+
/** @description Node type (e.g., "paragraph", "text", "heading", "bulletList") */
|
|
335
|
+
type: string;
|
|
336
|
+
/** @description Node attributes */
|
|
337
|
+
attrs?: {
|
|
338
|
+
[key: string]: (string | null) | number | boolean;
|
|
339
|
+
};
|
|
340
|
+
/** @description Child nodes (recursive DocumentNode array) */
|
|
341
|
+
content?: Record<string, never>[];
|
|
342
|
+
/** @description Text content (only for text nodes) */
|
|
343
|
+
text?: string;
|
|
344
|
+
/** @description Text marks (bold, italic, links, etc.) - only for text nodes */
|
|
345
|
+
marks?: {
|
|
346
|
+
/** @description Mark type (e.g., "bold", "italic", "link") */
|
|
347
|
+
type: string;
|
|
348
|
+
/** @description Mark attributes */
|
|
349
|
+
attrs?: {
|
|
350
|
+
[key: string]: (string | null) | number | boolean;
|
|
351
|
+
};
|
|
352
|
+
}[];
|
|
353
|
+
}[];
|
|
354
|
+
};
|
|
355
|
+
/** @description Description content as plain text */
|
|
356
|
+
plainText: string;
|
|
357
|
+
} | null;
|
|
358
|
+
Project: {
|
|
359
|
+
id: string;
|
|
360
|
+
name: string;
|
|
361
|
+
icon: string | null;
|
|
362
|
+
color: string | null;
|
|
363
|
+
state: "planned" | "completed";
|
|
364
|
+
completedAt?: number | null;
|
|
365
|
+
createdAt: number;
|
|
366
|
+
updatedAt: number;
|
|
367
|
+
description?: components["schemas"]["ProjectDescription"];
|
|
368
|
+
};
|
|
369
|
+
ProjectListResponse: {
|
|
370
|
+
data: components["schemas"]["Project"][];
|
|
371
|
+
nextCursor: string | null;
|
|
372
|
+
hasMore: boolean;
|
|
373
|
+
};
|
|
374
|
+
CreateProjectRequest: {
|
|
375
|
+
/**
|
|
376
|
+
* Format: uuid
|
|
377
|
+
* @description Optional custom ID for the project
|
|
378
|
+
*/
|
|
379
|
+
id?: string;
|
|
380
|
+
/** @description Name of the project */
|
|
381
|
+
name: string;
|
|
382
|
+
/** @description Project description in markdown format */
|
|
383
|
+
description?: string;
|
|
384
|
+
/** @description Icon for the project: Lucide icon name (e.g., "Folder") or emoji shortcode (e.g., ":rocket:") */
|
|
385
|
+
icon?: string | null;
|
|
386
|
+
/** @description Hex color for the icon (e.g., "#FF5733"). Only applies to Lucide icons, not emojis. */
|
|
387
|
+
color?: string | null;
|
|
388
|
+
};
|
|
389
|
+
UpdateProjectRequest: {
|
|
390
|
+
/** @description New name for the project */
|
|
391
|
+
name?: string;
|
|
392
|
+
/** @description Project description in markdown format */
|
|
393
|
+
description?: string;
|
|
394
|
+
/** @description New icon for the project: Lucide icon name (e.g., "Folder") or emoji shortcode (e.g., ":rocket:") */
|
|
395
|
+
icon?: string | null;
|
|
396
|
+
/** @description New hex color for the icon (e.g., "#FF5733"). Only applies to Lucide icons, not emojis. */
|
|
397
|
+
color?: string | null;
|
|
398
|
+
/**
|
|
399
|
+
* @description New state for the project
|
|
400
|
+
* @enum {string}
|
|
401
|
+
*/
|
|
402
|
+
state?: "planned" | "completed";
|
|
403
|
+
};
|
|
404
|
+
DeleteProjectResponse: {
|
|
405
|
+
success: boolean;
|
|
406
|
+
};
|
|
407
|
+
SessionActivity: {
|
|
408
|
+
/** @enum {string} */
|
|
409
|
+
type: "TASK";
|
|
410
|
+
taskId: string;
|
|
411
|
+
id: string;
|
|
412
|
+
createdAt: number;
|
|
413
|
+
finishedAt: number;
|
|
414
|
+
sessionId: string;
|
|
415
|
+
isManual: boolean;
|
|
416
|
+
} | {
|
|
417
|
+
/** @enum {string} */
|
|
418
|
+
type: "MEETING";
|
|
419
|
+
title: string;
|
|
420
|
+
htmlLink: string;
|
|
421
|
+
meetingId: string;
|
|
422
|
+
calendarId?: string;
|
|
423
|
+
id: string;
|
|
424
|
+
createdAt: number;
|
|
425
|
+
finishedAt: number;
|
|
426
|
+
sessionId: string;
|
|
427
|
+
isManual: boolean;
|
|
428
|
+
} | {
|
|
429
|
+
/** @enum {string} */
|
|
430
|
+
type: "PLANNING";
|
|
431
|
+
id: string;
|
|
432
|
+
createdAt: number;
|
|
433
|
+
finishedAt: number;
|
|
434
|
+
sessionId: string;
|
|
435
|
+
isManual: boolean;
|
|
436
|
+
} | {
|
|
437
|
+
/** @enum {string} */
|
|
438
|
+
type: "WRAP_UP";
|
|
439
|
+
id: string;
|
|
440
|
+
createdAt: number;
|
|
441
|
+
finishedAt: number;
|
|
442
|
+
sessionId: string;
|
|
443
|
+
isManual: boolean;
|
|
444
|
+
};
|
|
445
|
+
Session: {
|
|
446
|
+
/**
|
|
447
|
+
* Format: uuid
|
|
448
|
+
* @description Unique identifier for the session
|
|
449
|
+
*/
|
|
450
|
+
id: string;
|
|
451
|
+
/** @description Whether the session was manually created */
|
|
452
|
+
isManual: boolean;
|
|
453
|
+
/** @description Start timestamp (Unix seconds) */
|
|
454
|
+
createdAt: number;
|
|
455
|
+
/** @description End timestamp (Unix seconds) */
|
|
456
|
+
finishedAt: number;
|
|
457
|
+
};
|
|
458
|
+
SessionWithActivities: components["schemas"]["Session"] & {
|
|
459
|
+
/** @description Activities within this session */
|
|
460
|
+
activities: components["schemas"]["SessionActivity"][];
|
|
461
|
+
};
|
|
462
|
+
SessionListResponse: {
|
|
463
|
+
data: components["schemas"]["SessionWithActivities"][];
|
|
464
|
+
nextCursor: string | null;
|
|
465
|
+
hasMore: boolean;
|
|
466
|
+
};
|
|
467
|
+
CreateSessionRequest: {
|
|
468
|
+
/**
|
|
469
|
+
* Format: uuid
|
|
470
|
+
* @description Optional custom ID for the session
|
|
471
|
+
*/
|
|
472
|
+
id?: string;
|
|
473
|
+
/** @description Start timestamp (Unix seconds) */
|
|
474
|
+
createdAt: number;
|
|
475
|
+
/** @description End timestamp (Unix seconds) */
|
|
476
|
+
finishedAt: number;
|
|
477
|
+
};
|
|
478
|
+
UpdateSessionRequest: {
|
|
479
|
+
/** @description New start timestamp (Unix seconds) */
|
|
480
|
+
createdAt?: number;
|
|
481
|
+
/** @description New end timestamp (Unix seconds) */
|
|
482
|
+
finishedAt?: number;
|
|
483
|
+
};
|
|
484
|
+
DeleteSessionResponse: {
|
|
485
|
+
success: boolean;
|
|
486
|
+
};
|
|
487
|
+
ActivityListResponse: {
|
|
488
|
+
data: components["schemas"]["SessionActivity"][];
|
|
489
|
+
};
|
|
490
|
+
CreateActivityRequest: {
|
|
491
|
+
/** @description Optional custom ID for the activity */
|
|
492
|
+
id?: string;
|
|
493
|
+
/** @enum {string} */
|
|
494
|
+
type: "TASK";
|
|
495
|
+
/** @description Associated task ID */
|
|
496
|
+
taskId: string;
|
|
497
|
+
/** @description Start timestamp (Unix seconds) */
|
|
498
|
+
createdAt: number;
|
|
499
|
+
/** @description End timestamp (Unix seconds) */
|
|
500
|
+
finishedAt: number;
|
|
501
|
+
};
|
|
502
|
+
UpdateActivityRequest: {
|
|
503
|
+
/** @description New start timestamp (Unix seconds) */
|
|
504
|
+
createdAt?: number;
|
|
505
|
+
/** @description New end timestamp (Unix seconds) */
|
|
506
|
+
finishedAt?: number;
|
|
507
|
+
};
|
|
508
|
+
DeleteActivityResponse: {
|
|
509
|
+
success: boolean;
|
|
510
|
+
};
|
|
511
|
+
TaskListResponse: {
|
|
512
|
+
data: components["schemas"]["Task"][];
|
|
513
|
+
nextCursor: string | null;
|
|
514
|
+
hasMore: boolean;
|
|
515
|
+
};
|
|
516
|
+
TaskBySection: {
|
|
517
|
+
/** Format: uuid */
|
|
518
|
+
taskId: string;
|
|
519
|
+
/** @enum {string} */
|
|
520
|
+
section: "today" | "sooner" | "later";
|
|
521
|
+
order: number;
|
|
522
|
+
task: components["schemas"]["Task"];
|
|
523
|
+
};
|
|
524
|
+
TaskSectionsResponse: {
|
|
525
|
+
today: components["schemas"]["TaskBySection"][];
|
|
526
|
+
sooner: components["schemas"]["TaskBySection"][];
|
|
527
|
+
later: components["schemas"]["TaskBySection"][];
|
|
528
|
+
};
|
|
529
|
+
TaskSubtasksResponse: {
|
|
530
|
+
data: components["schemas"]["Task"][];
|
|
531
|
+
nextCursor: string | null;
|
|
532
|
+
hasMore: boolean;
|
|
533
|
+
};
|
|
534
|
+
CreateTaskRequest: {
|
|
535
|
+
/**
|
|
536
|
+
* Format: uuid
|
|
537
|
+
* @description Optional custom ID for the task
|
|
538
|
+
*/
|
|
539
|
+
id?: string;
|
|
540
|
+
/** @description Task name */
|
|
541
|
+
name: string;
|
|
542
|
+
/** @description Task description in markdown format */
|
|
543
|
+
description?: string;
|
|
544
|
+
/**
|
|
545
|
+
* Format: uuid
|
|
546
|
+
* @description Parent task ID for subtasks
|
|
547
|
+
*/
|
|
548
|
+
parentId?: string;
|
|
549
|
+
/**
|
|
550
|
+
* Format: uuid
|
|
551
|
+
* @description Project to assign the task to
|
|
552
|
+
*/
|
|
553
|
+
projectId?: string;
|
|
554
|
+
/**
|
|
555
|
+
* @description Section to place the task in. Required for root tasks (when parentId is not provided). Ignored for subtasks.
|
|
556
|
+
* @enum {string}
|
|
557
|
+
*/
|
|
558
|
+
section?: "today" | "sooner" | "later";
|
|
559
|
+
};
|
|
560
|
+
UpdateTaskRequest: {
|
|
561
|
+
/** @description Task name */
|
|
562
|
+
name?: string;
|
|
563
|
+
/** @description Task description in markdown format */
|
|
564
|
+
description?: string;
|
|
565
|
+
/** @description Task completion status */
|
|
566
|
+
done?: "completed" | "canceled" | unknown | unknown;
|
|
567
|
+
/**
|
|
568
|
+
* Format: uuid
|
|
569
|
+
* @description Project to assign the task to
|
|
570
|
+
*/
|
|
571
|
+
projectId?: string | null;
|
|
572
|
+
/** @description Mark task as waiting */
|
|
573
|
+
waiting?: {
|
|
574
|
+
reason?: string;
|
|
575
|
+
} | null;
|
|
576
|
+
};
|
|
577
|
+
DeleteTaskResponse: {
|
|
578
|
+
success: boolean;
|
|
579
|
+
};
|
|
580
|
+
TimerState: {
|
|
581
|
+
/**
|
|
582
|
+
* @description Current timer state
|
|
583
|
+
* @enum {string}
|
|
584
|
+
*/
|
|
585
|
+
state: "IDLE" | "ACTIVE" | "PAUSED";
|
|
586
|
+
/** @description Planned duration in seconds (only present when not IDLE) */
|
|
587
|
+
duration?: number;
|
|
588
|
+
/** @description ID of the task being worked on (only present when ACTIVE with a task) */
|
|
589
|
+
currentTaskId?: string;
|
|
590
|
+
/** @description When the timer was started as Unix timestamp in seconds (only present when not IDLE) */
|
|
591
|
+
startedAt?: number;
|
|
592
|
+
};
|
|
593
|
+
StartTimerRequest: {
|
|
594
|
+
/** @description Duration in seconds (must be positive) */
|
|
595
|
+
duration: number;
|
|
596
|
+
/** @description Optional task ID to start working on */
|
|
597
|
+
taskId?: string;
|
|
598
|
+
};
|
|
599
|
+
StopTimerSession: {
|
|
600
|
+
/** @description Unique identifier for the session */
|
|
601
|
+
id: string;
|
|
602
|
+
/** @description Whether the session was manually created */
|
|
603
|
+
isManual: boolean;
|
|
604
|
+
/** @description Start timestamp (Unix seconds) */
|
|
605
|
+
createdAt: number;
|
|
606
|
+
/** @description End timestamp (Unix seconds) */
|
|
607
|
+
finishedAt: number;
|
|
608
|
+
};
|
|
609
|
+
StopTimerResponse: {
|
|
610
|
+
/** @description The completed sessions that were created */
|
|
611
|
+
sessions: components["schemas"]["StopTimerSession"][];
|
|
612
|
+
};
|
|
613
|
+
Webhook: {
|
|
614
|
+
/**
|
|
615
|
+
* Format: uuid
|
|
616
|
+
* @description Unique identifier for the webhook
|
|
617
|
+
*/
|
|
618
|
+
id: string;
|
|
619
|
+
/**
|
|
620
|
+
* Format: uri
|
|
621
|
+
* @description URL to receive webhook payloads
|
|
622
|
+
*/
|
|
623
|
+
url: string;
|
|
624
|
+
/** @description Entity types to listen for (task, project, timer, note) */
|
|
625
|
+
entityTypes: ("task" | "project" | "timer" | "note")[];
|
|
626
|
+
/** @description Event types to listen for (created, updated, deleted) */
|
|
627
|
+
eventTypes: ("created" | "updated" | "deleted")[];
|
|
628
|
+
/** @description Whether the webhook is active */
|
|
629
|
+
isActive: boolean;
|
|
630
|
+
/**
|
|
631
|
+
* Format: date-time
|
|
632
|
+
* @description Creation timestamp
|
|
633
|
+
*/
|
|
634
|
+
createdAt: string;
|
|
635
|
+
/**
|
|
636
|
+
* Format: date-time
|
|
637
|
+
* @description Last update timestamp
|
|
638
|
+
*/
|
|
639
|
+
updatedAt: string;
|
|
640
|
+
};
|
|
641
|
+
WebhookListResponse: {
|
|
642
|
+
data: components["schemas"]["Webhook"][];
|
|
643
|
+
nextCursor: string | null;
|
|
644
|
+
hasMore: boolean;
|
|
645
|
+
};
|
|
646
|
+
WebhookWithSecret: components["schemas"]["Webhook"] & {
|
|
647
|
+
/** @description Secret for verifying webhook signatures (only shown once) */
|
|
648
|
+
secret: string;
|
|
649
|
+
};
|
|
650
|
+
CreateWebhookRequest: {
|
|
651
|
+
/**
|
|
652
|
+
* Format: uri
|
|
653
|
+
* @description URL to receive webhook payloads
|
|
654
|
+
*/
|
|
655
|
+
url: string;
|
|
656
|
+
/**
|
|
657
|
+
* @description Entity types to listen for
|
|
658
|
+
* @default [
|
|
659
|
+
* "task",
|
|
660
|
+
* "project",
|
|
661
|
+
* "timer",
|
|
662
|
+
* "note"
|
|
663
|
+
* ]
|
|
664
|
+
*/
|
|
665
|
+
entityTypes: ("task" | "project" | "timer" | "note")[];
|
|
666
|
+
/**
|
|
667
|
+
* @description Event types to listen for
|
|
668
|
+
* @default [
|
|
669
|
+
* "created",
|
|
670
|
+
* "updated",
|
|
671
|
+
* "deleted"
|
|
672
|
+
* ]
|
|
673
|
+
*/
|
|
674
|
+
eventTypes: ("created" | "updated" | "deleted")[];
|
|
675
|
+
};
|
|
676
|
+
UpdateWebhookRequest: {
|
|
677
|
+
/**
|
|
678
|
+
* Format: uri
|
|
679
|
+
* @description New URL for webhook payloads
|
|
680
|
+
*/
|
|
681
|
+
url?: string;
|
|
682
|
+
/** @description New entity types to listen for */
|
|
683
|
+
entityTypes?: ("task" | "project" | "timer" | "note")[];
|
|
684
|
+
/** @description New event types to listen for */
|
|
685
|
+
eventTypes?: ("created" | "updated" | "deleted")[];
|
|
686
|
+
/** @description Enable or disable the webhook */
|
|
687
|
+
isActive?: boolean;
|
|
688
|
+
};
|
|
689
|
+
DeleteWebhookResponse: {
|
|
690
|
+
success: boolean;
|
|
691
|
+
};
|
|
692
|
+
WebhookDelivery: {
|
|
693
|
+
/**
|
|
694
|
+
* Format: uuid
|
|
695
|
+
* @description Delivery ID
|
|
696
|
+
*/
|
|
697
|
+
id: string;
|
|
698
|
+
/**
|
|
699
|
+
* Format: uuid
|
|
700
|
+
* @description Associated webhook ID
|
|
701
|
+
*/
|
|
702
|
+
webhookId: string;
|
|
703
|
+
/**
|
|
704
|
+
* @description Delivery status
|
|
705
|
+
* @enum {string}
|
|
706
|
+
*/
|
|
707
|
+
status: "pending" | "success" | "failed";
|
|
708
|
+
/** @description Number of delivery attempts */
|
|
709
|
+
attemptNumber: number;
|
|
710
|
+
/** @description HTTP response status code */
|
|
711
|
+
responseStatus: number | null;
|
|
712
|
+
/** @description Error message if failed */
|
|
713
|
+
errorMessage: string | null;
|
|
714
|
+
/**
|
|
715
|
+
* Format: date-time
|
|
716
|
+
* @description Delivery creation timestamp
|
|
717
|
+
*/
|
|
718
|
+
createdAt: string;
|
|
719
|
+
/**
|
|
720
|
+
* Format: date-time
|
|
721
|
+
* @description Delivery completion timestamp
|
|
722
|
+
*/
|
|
723
|
+
completedAt: string | null;
|
|
724
|
+
};
|
|
725
|
+
WebhookDeliveryListResponse: {
|
|
726
|
+
data: components["schemas"]["WebhookDelivery"][];
|
|
727
|
+
nextCursor: string | null;
|
|
728
|
+
hasMore: boolean;
|
|
729
|
+
};
|
|
730
|
+
RotateSecretResponse: {
|
|
731
|
+
/** @description New webhook secret */
|
|
732
|
+
secret: string;
|
|
733
|
+
};
|
|
734
|
+
};
|
|
735
|
+
responses: never;
|
|
736
|
+
parameters: never;
|
|
737
|
+
requestBodies: never;
|
|
738
|
+
headers: never;
|
|
739
|
+
pathItems: never;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Re-export types from the generated OpenAPI types.
|
|
744
|
+
* These provide typed access to the Locu API.
|
|
745
|
+
*/
|
|
746
|
+
|
|
747
|
+
type Task = components["schemas"]["Task"];
|
|
748
|
+
type LocuTask = components["schemas"]["LocuTask"];
|
|
749
|
+
type LinearTask = components["schemas"]["LinearTask"];
|
|
750
|
+
type JiraTask = components["schemas"]["JiraTask"];
|
|
751
|
+
type TaskDescription = components["schemas"]["TaskDescription"];
|
|
752
|
+
type CreateTaskRequest = components["schemas"]["CreateTaskRequest"];
|
|
753
|
+
type UpdateTaskRequest = components["schemas"]["UpdateTaskRequest"];
|
|
754
|
+
type TaskListResponse = components["schemas"]["TaskListResponse"];
|
|
755
|
+
type TaskBySection = components["schemas"]["TaskBySection"];
|
|
756
|
+
type TaskSectionsResponse = components["schemas"]["TaskSectionsResponse"];
|
|
757
|
+
type DeleteTaskResponse = components["schemas"]["DeleteTaskResponse"];
|
|
758
|
+
type Project = components["schemas"]["Project"];
|
|
759
|
+
type ProjectDescription = components["schemas"]["ProjectDescription"];
|
|
760
|
+
type CreateProjectRequest = components["schemas"]["CreateProjectRequest"];
|
|
761
|
+
type UpdateProjectRequest = components["schemas"]["UpdateProjectRequest"];
|
|
762
|
+
type ProjectListResponse = components["schemas"]["ProjectListResponse"];
|
|
763
|
+
type DeleteProjectResponse = components["schemas"]["DeleteProjectResponse"];
|
|
764
|
+
type Note = components["schemas"]["Note"];
|
|
765
|
+
type CreateNoteRequest = components["schemas"]["CreateNoteRequest"];
|
|
766
|
+
type UpdateNoteRequest = components["schemas"]["UpdateNoteRequest"];
|
|
767
|
+
type NoteListResponse = components["schemas"]["NoteListResponse"];
|
|
768
|
+
type DeleteNoteResponse = components["schemas"]["DeleteNoteResponse"];
|
|
769
|
+
type Session = components["schemas"]["Session"];
|
|
770
|
+
type SessionWithActivities = components["schemas"]["SessionWithActivities"];
|
|
771
|
+
type SessionActivity = components["schemas"]["SessionActivity"];
|
|
772
|
+
type CreateSessionRequest = components["schemas"]["CreateSessionRequest"];
|
|
773
|
+
type UpdateSessionRequest = components["schemas"]["UpdateSessionRequest"];
|
|
774
|
+
type SessionListResponse = components["schemas"]["SessionListResponse"];
|
|
775
|
+
type DeleteSessionResponse = components["schemas"]["DeleteSessionResponse"];
|
|
776
|
+
type CreateActivityRequest = components["schemas"]["CreateActivityRequest"];
|
|
777
|
+
type UpdateActivityRequest = components["schemas"]["UpdateActivityRequest"];
|
|
778
|
+
type ActivityListResponse = components["schemas"]["ActivityListResponse"];
|
|
779
|
+
type DeleteActivityResponse = components["schemas"]["DeleteActivityResponse"];
|
|
780
|
+
type TimerState = components["schemas"]["TimerState"];
|
|
781
|
+
type StartTimerRequest = components["schemas"]["StartTimerRequest"];
|
|
782
|
+
type StopTimerResponse = components["schemas"]["StopTimerResponse"];
|
|
783
|
+
type StopTimerSession = components["schemas"]["StopTimerSession"];
|
|
784
|
+
type Webhook = components["schemas"]["Webhook"];
|
|
785
|
+
type WebhookWithSecret = components["schemas"]["WebhookWithSecret"];
|
|
786
|
+
type CreateWebhookRequest = components["schemas"]["CreateWebhookRequest"];
|
|
787
|
+
type UpdateWebhookRequest = components["schemas"]["UpdateWebhookRequest"];
|
|
788
|
+
type WebhookListResponse = components["schemas"]["WebhookListResponse"];
|
|
789
|
+
type WebhookDelivery = components["schemas"]["WebhookDelivery"];
|
|
790
|
+
type WebhookDeliveryListResponse = components["schemas"]["WebhookDeliveryListResponse"];
|
|
791
|
+
type RotateSecretResponse = components["schemas"]["RotateSecretResponse"];
|
|
792
|
+
type DeleteWebhookResponse = components["schemas"]["DeleteWebhookResponse"];
|
|
793
|
+
type ErrorResponse = components["schemas"]["ErrorResponse"];
|
|
794
|
+
type ApiError = ErrorResponse;
|
|
795
|
+
type WebhookPayload<T = unknown> = {
|
|
796
|
+
/** Event type, e.g. "task.created", "project.updated" */
|
|
797
|
+
event: string;
|
|
798
|
+
/** ISO 8601 timestamp when the event occurred */
|
|
799
|
+
timestamp: string;
|
|
800
|
+
/** The entity data that triggered the event */
|
|
801
|
+
data: T;
|
|
802
|
+
};
|
|
803
|
+
type PaginatedResponse<T> = {
|
|
804
|
+
data: T[];
|
|
805
|
+
nextCursor: string | null;
|
|
806
|
+
hasMore: boolean;
|
|
807
|
+
};
|
|
808
|
+
type PaginationParams = {
|
|
809
|
+
limit?: number;
|
|
810
|
+
cursor?: string;
|
|
811
|
+
};
|
|
812
|
+
type TaskListParams = PaginationParams & {
|
|
813
|
+
done?: "true" | "false";
|
|
814
|
+
projectId?: string;
|
|
815
|
+
parentId?: string;
|
|
816
|
+
section?: "today" | "sooner" | "later";
|
|
817
|
+
doneAfter?: string;
|
|
818
|
+
doneBefore?: string;
|
|
819
|
+
includeHtml?: boolean | null;
|
|
820
|
+
};
|
|
821
|
+
type TaskSectionsParams = {
|
|
822
|
+
projectId?: string;
|
|
823
|
+
includeHtml?: boolean | null;
|
|
824
|
+
};
|
|
825
|
+
type SubtaskListParams = PaginationParams & {
|
|
826
|
+
done?: "true" | "false";
|
|
827
|
+
includeHtml?: boolean | null;
|
|
828
|
+
};
|
|
829
|
+
type ProjectListParams = PaginationParams & {
|
|
830
|
+
state?: "planned" | "completed";
|
|
831
|
+
includeHtml?: boolean | null;
|
|
832
|
+
};
|
|
833
|
+
type NoteListParams = PaginationParams & {
|
|
834
|
+
folderId?: string;
|
|
835
|
+
includeHtml?: boolean | null;
|
|
836
|
+
};
|
|
837
|
+
type SessionListParams = PaginationParams & {
|
|
838
|
+
startAfter?: string;
|
|
839
|
+
startBefore?: string;
|
|
840
|
+
includeActivities?: boolean | null;
|
|
841
|
+
};
|
|
842
|
+
type WebhookListParams = PaginationParams & {
|
|
843
|
+
isActive?: "true" | "false";
|
|
844
|
+
};
|
|
845
|
+
|
|
846
|
+
type LocuClientConfig = {
|
|
847
|
+
/** API base URL (defaults to https://api.locu.app/api/v1) */
|
|
848
|
+
baseUrl?: string;
|
|
849
|
+
/** Personal Access Token for authentication */
|
|
850
|
+
token: string;
|
|
851
|
+
/** Custom fetch implementation (defaults to global fetch) */
|
|
852
|
+
fetch?: typeof fetch;
|
|
853
|
+
};
|
|
854
|
+
declare class LocuApiError extends Error {
|
|
855
|
+
status: number;
|
|
856
|
+
code?: string;
|
|
857
|
+
constructor(message: string, status: number, code?: string);
|
|
858
|
+
}
|
|
859
|
+
declare const createLocuClient: (config: LocuClientConfig) => {
|
|
860
|
+
tasks: {
|
|
861
|
+
/** List all tasks */
|
|
862
|
+
list: (params?: TaskListParams) => Promise<PaginatedResponse<Task>>;
|
|
863
|
+
/** Get a single task by ID */
|
|
864
|
+
get: (id: string) => Promise<Task>;
|
|
865
|
+
/** Create a new task */
|
|
866
|
+
create: (data: CreateTaskRequest) => Promise<Task>;
|
|
867
|
+
/** Update an existing task */
|
|
868
|
+
update: (id: string, data: UpdateTaskRequest) => Promise<Task>;
|
|
869
|
+
/** Delete a task */
|
|
870
|
+
delete: (id: string) => Promise<{
|
|
871
|
+
success: boolean;
|
|
872
|
+
}>;
|
|
873
|
+
/** Get tasks organized by section (today, sooner, later) */
|
|
874
|
+
sections: (params?: TaskSectionsParams) => Promise<TaskSectionsResponse>;
|
|
875
|
+
/** List subtasks for a task */
|
|
876
|
+
subtasks: (id: string, params?: SubtaskListParams) => Promise<PaginatedResponse<Task>>;
|
|
877
|
+
/** Create a subtask under a parent task */
|
|
878
|
+
createSubtask: (parentId: string, data: Omit<CreateTaskRequest, "parentId" | "section">) => Promise<Task>;
|
|
879
|
+
};
|
|
880
|
+
projects: {
|
|
881
|
+
/** List all projects */
|
|
882
|
+
list: (params?: ProjectListParams) => Promise<PaginatedResponse<Project>>;
|
|
883
|
+
/** Get a single project by ID */
|
|
884
|
+
get: (id: string) => Promise<Project>;
|
|
885
|
+
/** Create a new project */
|
|
886
|
+
create: (data: CreateProjectRequest) => Promise<Project>;
|
|
887
|
+
/** Update an existing project */
|
|
888
|
+
update: (id: string, data: UpdateProjectRequest) => Promise<Project>;
|
|
889
|
+
/** Delete a project */
|
|
890
|
+
delete: (id: string) => Promise<{
|
|
891
|
+
success: boolean;
|
|
892
|
+
}>;
|
|
893
|
+
};
|
|
894
|
+
notes: {
|
|
895
|
+
/** List all notes */
|
|
896
|
+
list: (params?: NoteListParams) => Promise<PaginatedResponse<Note>>;
|
|
897
|
+
/** Get a single note by ID */
|
|
898
|
+
get: (id: string) => Promise<Note>;
|
|
899
|
+
/** Create a new note */
|
|
900
|
+
create: (data: CreateNoteRequest) => Promise<Note>;
|
|
901
|
+
/** Update an existing note */
|
|
902
|
+
update: (id: string, data: UpdateNoteRequest) => Promise<Note>;
|
|
903
|
+
/** Delete a note */
|
|
904
|
+
delete: (id: string) => Promise<{
|
|
905
|
+
success: boolean;
|
|
906
|
+
}>;
|
|
907
|
+
};
|
|
908
|
+
sessions: {
|
|
909
|
+
/** List all sessions */
|
|
910
|
+
list: (params?: SessionListParams) => Promise<PaginatedResponse<SessionWithActivities>>;
|
|
911
|
+
/** Get a single session by ID */
|
|
912
|
+
get: (id: string) => Promise<SessionWithActivities>;
|
|
913
|
+
/** Create a new session */
|
|
914
|
+
create: (data: CreateSessionRequest) => Promise<Session>;
|
|
915
|
+
/** Update an existing session */
|
|
916
|
+
update: (id: string, data: UpdateSessionRequest) => Promise<Session>;
|
|
917
|
+
/** Delete a session */
|
|
918
|
+
delete: (id: string) => Promise<{
|
|
919
|
+
success: boolean;
|
|
920
|
+
}>;
|
|
921
|
+
activities: {
|
|
922
|
+
/** List activities for a session */
|
|
923
|
+
list: (sessionId: string) => Promise<{
|
|
924
|
+
data: SessionActivity[];
|
|
925
|
+
}>;
|
|
926
|
+
/** Create a new activitie */
|
|
927
|
+
create: (sessionId: string, data: CreateActivityRequest) => Promise<SessionActivity>;
|
|
928
|
+
/** Update an activitie */
|
|
929
|
+
update: (sessionId: string, activityId: string, data: UpdateActivityRequest) => Promise<SessionActivity>;
|
|
930
|
+
/** Delete an activitie */
|
|
931
|
+
delete: (sessionId: string, activityId: string) => Promise<{
|
|
932
|
+
success: boolean;
|
|
933
|
+
}>;
|
|
934
|
+
};
|
|
935
|
+
};
|
|
936
|
+
webhooks: {
|
|
937
|
+
/** List all webhooks */
|
|
938
|
+
list: (params?: WebhookListParams) => Promise<PaginatedResponse<Webhook>>;
|
|
939
|
+
/** Get a single webhook by ID */
|
|
940
|
+
get: (id: string) => Promise<Webhook>;
|
|
941
|
+
/** Create a new webhook */
|
|
942
|
+
create: (data: CreateWebhookRequest) => Promise<WebhookWithSecret>;
|
|
943
|
+
/** Update an existing webhook */
|
|
944
|
+
update: (id: string, data: UpdateWebhookRequest) => Promise<Webhook>;
|
|
945
|
+
/** Delete a webhook */
|
|
946
|
+
delete: (id: string) => Promise<{
|
|
947
|
+
success: boolean;
|
|
948
|
+
}>;
|
|
949
|
+
/** Rotate webhook secret */
|
|
950
|
+
rotateSecret: (id: string) => Promise<{
|
|
951
|
+
secret: string;
|
|
952
|
+
}>;
|
|
953
|
+
/** List deliveries for a webhook */
|
|
954
|
+
deliveries: (id: string, params?: PaginationParams) => Promise<PaginatedResponse<WebhookDelivery>>;
|
|
955
|
+
};
|
|
956
|
+
timer: {
|
|
957
|
+
/** Get current timer state */
|
|
958
|
+
get: () => Promise<TimerState>;
|
|
959
|
+
/** Start a new timer */
|
|
960
|
+
start: (data?: StartTimerRequest) => Promise<TimerState>;
|
|
961
|
+
/** Pause the running timer */
|
|
962
|
+
pause: () => Promise<TimerState>;
|
|
963
|
+
/** Resume a paused timer */
|
|
964
|
+
continue: () => Promise<TimerState>;
|
|
965
|
+
/** Stop timer and save sessions */
|
|
966
|
+
stop: () => Promise<StopTimerResponse>;
|
|
967
|
+
};
|
|
968
|
+
};
|
|
969
|
+
type LocuClient = ReturnType<typeof createLocuClient>;
|
|
970
|
+
|
|
971
|
+
type WebhookSignatureResult = {
|
|
972
|
+
valid: true;
|
|
973
|
+
} | {
|
|
974
|
+
valid: false;
|
|
975
|
+
error: string;
|
|
976
|
+
};
|
|
977
|
+
type ParsedWebhookSignature = {
|
|
978
|
+
timestamp: number;
|
|
979
|
+
signature: string;
|
|
980
|
+
};
|
|
981
|
+
type VerifyWebhookOptions = {
|
|
982
|
+
/** Maximum age of signature in seconds (default: 300 = 5 minutes) */
|
|
983
|
+
maxAge?: number;
|
|
984
|
+
};
|
|
985
|
+
/**
|
|
986
|
+
* Parse a webhook signature header into its components.
|
|
987
|
+
*
|
|
988
|
+
* The signature header format is: `t=<timestamp>,v1=<hex_signature>`
|
|
989
|
+
*
|
|
990
|
+
* @param signatureHeader - The X-Webhook-Signature header value
|
|
991
|
+
* @returns Parsed timestamp and signature, or null if invalid format
|
|
992
|
+
*
|
|
993
|
+
* @example
|
|
994
|
+
* ```typescript
|
|
995
|
+
* const parsed = parseWebhookSignature(request.headers['x-webhook-signature'])
|
|
996
|
+
* if (parsed) {
|
|
997
|
+
* console.log('Timestamp:', parsed.timestamp)
|
|
998
|
+
* console.log('Signature:', parsed.signature)
|
|
999
|
+
* }
|
|
1000
|
+
* ```
|
|
1001
|
+
*/
|
|
1002
|
+
declare const parseWebhookSignature: (signatureHeader: string) => ParsedWebhookSignature | null;
|
|
1003
|
+
/**
|
|
1004
|
+
* Verify a webhook signature using HMAC-SHA256.
|
|
1005
|
+
*
|
|
1006
|
+
* This function verifies that a webhook payload was signed by Locu using your webhook secret.
|
|
1007
|
+
* It also checks that the signature timestamp is not too old to prevent replay attacks.
|
|
1008
|
+
*
|
|
1009
|
+
* @param secret - Your webhook secret (starts with `whsec_`)
|
|
1010
|
+
* @param signatureHeader - The X-Webhook-Signature header value
|
|
1011
|
+
* @param body - The raw request body as a string
|
|
1012
|
+
* @param options - Optional verification settings
|
|
1013
|
+
* @returns Object with `valid: true` if valid, or `valid: false` with an error message
|
|
1014
|
+
*
|
|
1015
|
+
* @example
|
|
1016
|
+
* ```typescript
|
|
1017
|
+
* import { verifyWebhookSignature } from '@locu/api-client'
|
|
1018
|
+
*
|
|
1019
|
+
* app.post('/webhooks/locu', (req, res) => {
|
|
1020
|
+
* const result = verifyWebhookSignature(
|
|
1021
|
+
* process.env.LOCU_WEBHOOK_SECRET,
|
|
1022
|
+
* req.headers['x-webhook-signature'],
|
|
1023
|
+
* req.body, // raw body string
|
|
1024
|
+
* { maxAge: 300 } // 5 minutes
|
|
1025
|
+
* )
|
|
1026
|
+
*
|
|
1027
|
+
* if (!result.valid) {
|
|
1028
|
+
* return res.status(401).json({ error: result.error })
|
|
1029
|
+
* }
|
|
1030
|
+
*
|
|
1031
|
+
* // Process the webhook
|
|
1032
|
+
* const payload = JSON.parse(req.body)
|
|
1033
|
+
* console.log('Received event:', payload.event)
|
|
1034
|
+
* })
|
|
1035
|
+
* ```
|
|
1036
|
+
*/
|
|
1037
|
+
declare const verifyWebhookSignature: (secret: string, signatureHeader: string, body: string, options?: VerifyWebhookOptions) => WebhookSignatureResult;
|
|
1038
|
+
/**
|
|
1039
|
+
* Parse a webhook payload from a JSON string.
|
|
1040
|
+
*
|
|
1041
|
+
* @param body - The raw request body as a JSON string
|
|
1042
|
+
* @returns The parsed webhook payload
|
|
1043
|
+
*
|
|
1044
|
+
* @example
|
|
1045
|
+
* ```typescript
|
|
1046
|
+
* import { parseWebhookPayload, TaskWebhookPayload } from '@locu/api-client'
|
|
1047
|
+
*
|
|
1048
|
+
* const payload = parseWebhookPayload<TaskWebhookPayload>(req.body)
|
|
1049
|
+
* console.log('Event:', payload.event) // e.g., "task.created"
|
|
1050
|
+
* console.log('Task name:', payload.data.name)
|
|
1051
|
+
* ```
|
|
1052
|
+
*/
|
|
1053
|
+
declare const parseWebhookPayload: <T = unknown>(body: string) => WebhookPayload<T>;
|
|
1054
|
+
/**
|
|
1055
|
+
* Generate a webhook signature for testing purposes.
|
|
1056
|
+
*
|
|
1057
|
+
* This is useful for testing your webhook handlers locally.
|
|
1058
|
+
*
|
|
1059
|
+
* @param secret - Your webhook secret
|
|
1060
|
+
* @param timestamp - Unix timestamp in seconds
|
|
1061
|
+
* @param body - The request body as a string
|
|
1062
|
+
* @returns The signature header value in format `t=<timestamp>,v1=<signature>`
|
|
1063
|
+
*
|
|
1064
|
+
* @example
|
|
1065
|
+
* ```typescript
|
|
1066
|
+
* import { generateWebhookSignature } from '@locu/api-client'
|
|
1067
|
+
*
|
|
1068
|
+
* const body = JSON.stringify({ event: 'task.created', timestamp: '...', data: {...} })
|
|
1069
|
+
* const signature = generateWebhookSignature('whsec_...', Math.floor(Date.now() / 1000), body)
|
|
1070
|
+
* // Use signature for testing your webhook handler
|
|
1071
|
+
* ```
|
|
1072
|
+
*/
|
|
1073
|
+
declare const generateWebhookSignature: (secret: string, timestamp: number, body: string) => string;
|
|
1074
|
+
|
|
1075
|
+
export { type ActivityListResponse, type ApiError, type CreateActivityRequest, type CreateNoteRequest, type CreateProjectRequest, type CreateSessionRequest, type CreateTaskRequest, type CreateWebhookRequest, type DeleteActivityResponse, type DeleteNoteResponse, type DeleteProjectResponse, type DeleteSessionResponse, type DeleteTaskResponse, type DeleteWebhookResponse, type ErrorResponse, type JiraTask, type LinearTask, LocuApiError, type LocuClient, type LocuClientConfig, type LocuTask, type Note, type NoteListParams, type NoteListResponse, type PaginatedResponse, type PaginationParams, type ParsedWebhookSignature, type Project, type ProjectDescription, type ProjectListParams, type ProjectListResponse, type RotateSecretResponse, type Session, type SessionActivity, type SessionListParams, type SessionListResponse, type SessionWithActivities, type StartTimerRequest, type StopTimerResponse, type StopTimerSession, type SubtaskListParams, type Task, type TaskBySection, type TaskDescription, type TaskListParams, type TaskListResponse, type TaskSectionsParams, type TaskSectionsResponse, type TimerState, type UpdateActivityRequest, type UpdateNoteRequest, type UpdateProjectRequest, type UpdateSessionRequest, type UpdateTaskRequest, type UpdateWebhookRequest, type VerifyWebhookOptions, type Webhook, type WebhookDelivery, type WebhookDeliveryListResponse, type WebhookListParams, type WebhookListResponse, type WebhookPayload, type WebhookSignatureResult, type WebhookWithSecret, createLocuClient, generateWebhookSignature, parseWebhookPayload, parseWebhookSignature, verifyWebhookSignature };
|