@doist/todoist-api-typescript 5.7.1 → 5.9.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.
@@ -713,4 +713,123 @@ export declare const ActivityEventSchema: z.ZodObject<{
713
713
  * Represents an activity log event in Todoist.
714
714
  */
715
715
  export type ActivityEvent = z.infer<typeof ActivityEventSchema>;
716
+ /**
717
+ * Available workspace roles.
718
+ */
719
+ export declare const WORKSPACE_ROLES: readonly ["ADMIN", "MEMBER", "GUEST"];
720
+ /**
721
+ * Role of a user within a workspace.
722
+ */
723
+ export type WorkspaceRole = (typeof WORKSPACE_ROLES)[number];
724
+ export declare const WorkspaceRoleSchema: z.ZodEnum<{
725
+ ADMIN: "ADMIN";
726
+ MEMBER: "MEMBER";
727
+ GUEST: "GUEST";
728
+ }>;
729
+ export declare const WorkspaceUserSchema: z.ZodObject<{
730
+ userId: z.ZodString;
731
+ workspaceId: z.ZodString;
732
+ userEmail: z.ZodString;
733
+ fullName: z.ZodString;
734
+ timezone: z.ZodString;
735
+ role: z.ZodEnum<{
736
+ ADMIN: "ADMIN";
737
+ MEMBER: "MEMBER";
738
+ GUEST: "GUEST";
739
+ }>;
740
+ imageId: z.ZodNullable<z.ZodString>;
741
+ isDeleted: z.ZodDefault<z.ZodBoolean>;
742
+ }, z.core.$strip>;
743
+ /**
744
+ * Represents a user within a workspace (MemberView from API).
745
+ */
746
+ export type WorkspaceUser = z.infer<typeof WorkspaceUserSchema>;
747
+ export declare const WorkspaceInvitationSchema: z.ZodObject<{
748
+ id: z.ZodDefault<z.ZodString>;
749
+ inviterId: z.ZodString;
750
+ userEmail: z.ZodString;
751
+ workspaceId: z.ZodString;
752
+ role: z.ZodEnum<{
753
+ ADMIN: "ADMIN";
754
+ MEMBER: "MEMBER";
755
+ GUEST: "GUEST";
756
+ }>;
757
+ isExistingUser: z.ZodBoolean;
758
+ }, z.core.$strip>;
759
+ /**
760
+ * Represents a workspace invitation.
761
+ */
762
+ export type WorkspaceInvitation = z.infer<typeof WorkspaceInvitationSchema>;
763
+ export declare const PlanPriceSchema: z.ZodObject<{
764
+ currency: z.ZodString;
765
+ amount: z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>;
766
+ interval: z.ZodOptional<z.ZodString>;
767
+ }, z.core.$strip>;
768
+ /**
769
+ * Plan pricing information.
770
+ */
771
+ export type PlanPrice = z.infer<typeof PlanPriceSchema>;
772
+ export declare const FormattedPriceListingSchema: z.ZodObject<{
773
+ currency: z.ZodOptional<z.ZodString>;
774
+ amount: z.ZodOptional<z.ZodNumber>;
775
+ interval: z.ZodOptional<z.ZodString>;
776
+ formatted: z.ZodOptional<z.ZodString>;
777
+ }, z.core.$strip>;
778
+ /**
779
+ * Formatted price listing for workspace plans.
780
+ */
781
+ export type FormattedPriceListing = z.infer<typeof FormattedPriceListingSchema>;
782
+ export declare const WorkspacePlanDetailsSchema: z.ZodObject<{
783
+ currentMemberCount: z.ZodNumber;
784
+ currentPlan: z.ZodEnum<{
785
+ Business: "Business";
786
+ Starter: "Starter";
787
+ }>;
788
+ currentPlanStatus: z.ZodEnum<{
789
+ Active: "Active";
790
+ Downgraded: "Downgraded";
791
+ Cancelled: "Cancelled";
792
+ NeverSubscribed: "NeverSubscribed";
793
+ }>;
794
+ downgradeAt: z.ZodNullable<z.ZodString>;
795
+ currentActiveProjects: z.ZodNumber;
796
+ maximumActiveProjects: z.ZodNumber;
797
+ priceList: z.ZodArray<z.ZodObject<{
798
+ currency: z.ZodOptional<z.ZodString>;
799
+ amount: z.ZodOptional<z.ZodNumber>;
800
+ interval: z.ZodOptional<z.ZodString>;
801
+ formatted: z.ZodOptional<z.ZodString>;
802
+ }, z.core.$strip>>;
803
+ workspaceId: z.ZodNumber;
804
+ isTrialing: z.ZodBoolean;
805
+ trialEndsAt: z.ZodNullable<z.ZodString>;
806
+ cancelAtPeriodEnd: z.ZodBoolean;
807
+ hasTrialed: z.ZodBoolean;
808
+ planPrice: z.ZodNullable<z.ZodObject<{
809
+ currency: z.ZodString;
810
+ amount: z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>;
811
+ interval: z.ZodOptional<z.ZodString>;
812
+ }, z.core.$strip>>;
813
+ hasBillingPortal: z.ZodBoolean;
814
+ hasBillingPortalSwitchToAnnual: z.ZodBoolean;
815
+ }, z.core.$strip>;
816
+ /**
817
+ * Represents workspace plan and billing details.
818
+ */
819
+ export type WorkspacePlanDetails = z.infer<typeof WorkspacePlanDetailsSchema>;
820
+ export declare const JoinWorkspaceResultSchema: z.ZodObject<{
821
+ custom_sorting_applied: z.ZodBoolean;
822
+ project_sort_preference: z.ZodString;
823
+ role: z.ZodEnum<{
824
+ ADMIN: "ADMIN";
825
+ MEMBER: "MEMBER";
826
+ GUEST: "GUEST";
827
+ }>;
828
+ user_id: z.ZodString;
829
+ workspace_id: z.ZodString;
830
+ }, z.core.$strip>;
831
+ /**
832
+ * Result returned when successfully joining a workspace.
833
+ */
834
+ export type JoinWorkspaceResult = z.infer<typeof JoinWorkspaceResultSchema>;
716
835
  export {};
@@ -22,9 +22,9 @@ var __rest = (this && this.__rest) || function (s, e) {
22
22
  return t;
23
23
  };
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.ActivityEventSchema = exports.ActivityEventExtraDataSchema = exports.ColorSchema = exports.ProductivityStatsSchema = exports.CurrentUserSchema = exports.TimezoneInfoSchema = exports.UserSchema = exports.CommentSchema = exports.RawCommentSchema = exports.AttachmentSchema = exports.LabelSchema = exports.SectionSchema = exports.WorkspaceProjectSchema = exports.PersonalProjectSchema = exports.BaseProjectSchema = exports.TaskSchema = exports.DeadlineSchema = exports.DurationSchema = exports.DueDateSchema = void 0;
25
+ exports.JoinWorkspaceResultSchema = exports.WorkspacePlanDetailsSchema = exports.FormattedPriceListingSchema = exports.PlanPriceSchema = exports.WorkspaceInvitationSchema = exports.WorkspaceUserSchema = exports.WorkspaceRoleSchema = exports.WORKSPACE_ROLES = exports.ActivityEventSchema = exports.ActivityEventExtraDataSchema = exports.ColorSchema = exports.ProductivityStatsSchema = exports.CurrentUserSchema = exports.TimezoneInfoSchema = exports.UserSchema = exports.CommentSchema = exports.RawCommentSchema = exports.AttachmentSchema = exports.LabelSchema = exports.SectionSchema = exports.WorkspaceProjectSchema = exports.PersonalProjectSchema = exports.BaseProjectSchema = exports.TaskSchema = exports.DeadlineSchema = exports.DurationSchema = exports.DueDateSchema = void 0;
26
26
  var zod_1 = require("zod");
27
- var urlHelpers_1 = require("../utils/urlHelpers");
27
+ var url_helpers_1 = require("../utils/url-helpers");
28
28
  exports.DueDateSchema = zod_1.z
29
29
  .object({
30
30
  isRecurring: zod_1.z.boolean(),
@@ -72,7 +72,7 @@ exports.TaskSchema = zod_1.z
72
72
  isCollapsed: zod_1.z.boolean(),
73
73
  })
74
74
  .transform(function (data) {
75
- return __assign(__assign({}, data), { url: (0, urlHelpers_1.getTaskUrl)(data.id, data.content) });
75
+ return __assign(__assign({}, data), { url: (0, url_helpers_1.getTaskUrl)(data.id, data.content) });
76
76
  });
77
77
  /**
78
78
  * Base schema for all project types in Todoist.
@@ -103,7 +103,7 @@ exports.PersonalProjectSchema = exports.BaseProjectSchema.extend({
103
103
  parentId: zod_1.z.string().nullable(),
104
104
  inboxProject: zod_1.z.boolean().optional().default(false),
105
105
  }).transform(function (data) {
106
- return __assign(__assign({}, data), { url: (0, urlHelpers_1.getProjectUrl)(data.id, data.name) });
106
+ return __assign(__assign({}, data), { url: (0, url_helpers_1.getProjectUrl)(data.id, data.name) });
107
107
  });
108
108
  /**
109
109
  * Schema for workspace projects in Todoist.
@@ -117,7 +117,7 @@ exports.WorkspaceProjectSchema = exports.BaseProjectSchema.extend({
117
117
  status: zod_1.z.string(),
118
118
  workspaceId: zod_1.z.string(),
119
119
  }).transform(function (data) {
120
- return __assign(__assign({}, data), { url: (0, urlHelpers_1.getProjectUrl)(data.id, data.name) });
120
+ return __assign(__assign({}, data), { url: (0, url_helpers_1.getProjectUrl)(data.id, data.name) });
121
121
  });
122
122
  exports.SectionSchema = zod_1.z
123
123
  .object({
@@ -134,7 +134,7 @@ exports.SectionSchema = zod_1.z
134
134
  isCollapsed: zod_1.z.boolean(),
135
135
  })
136
136
  .transform(function (data) {
137
- return __assign(__assign({}, data), { url: (0, urlHelpers_1.getSectionUrl)(data.id, data.name) });
137
+ return __assign(__assign({}, data), { url: (0, url_helpers_1.getSectionUrl)(data.id, data.name) });
138
138
  });
139
139
  exports.LabelSchema = zod_1.z.object({
140
140
  id: zod_1.z.string(),
@@ -320,3 +320,61 @@ exports.ActivityEventSchema = zod_1.z
320
320
  extraData: exports.ActivityEventExtraDataSchema,
321
321
  })
322
322
  .catchall(zod_1.z.any());
323
+ /**
324
+ * Available workspace roles.
325
+ */
326
+ exports.WORKSPACE_ROLES = ['ADMIN', 'MEMBER', 'GUEST'];
327
+ exports.WorkspaceRoleSchema = zod_1.z.enum(exports.WORKSPACE_ROLES);
328
+ exports.WorkspaceUserSchema = zod_1.z.object({
329
+ userId: zod_1.z.string(),
330
+ workspaceId: zod_1.z.string(),
331
+ userEmail: zod_1.z.string(),
332
+ fullName: zod_1.z.string(),
333
+ timezone: zod_1.z.string(),
334
+ role: exports.WorkspaceRoleSchema,
335
+ imageId: zod_1.z.string().nullable(),
336
+ isDeleted: zod_1.z.boolean().default(false),
337
+ });
338
+ exports.WorkspaceInvitationSchema = zod_1.z.object({
339
+ id: zod_1.z.string().default('0'),
340
+ inviterId: zod_1.z.string(),
341
+ userEmail: zod_1.z.string(),
342
+ workspaceId: zod_1.z.string(),
343
+ role: exports.WorkspaceRoleSchema,
344
+ isExistingUser: zod_1.z.boolean(),
345
+ });
346
+ exports.PlanPriceSchema = zod_1.z.object({
347
+ currency: zod_1.z.string(),
348
+ amount: zod_1.z.union([zod_1.z.number(), zod_1.z.string()]),
349
+ interval: zod_1.z.string().optional(),
350
+ });
351
+ exports.FormattedPriceListingSchema = zod_1.z.object({
352
+ currency: zod_1.z.string().optional(),
353
+ amount: zod_1.z.number().optional(),
354
+ interval: zod_1.z.string().optional(),
355
+ formatted: zod_1.z.string().optional(),
356
+ });
357
+ exports.WorkspacePlanDetailsSchema = zod_1.z.object({
358
+ currentMemberCount: zod_1.z.number(),
359
+ currentPlan: zod_1.z.enum(['Business', 'Starter']),
360
+ currentPlanStatus: zod_1.z.enum(['Active', 'Downgraded', 'Cancelled', 'NeverSubscribed']),
361
+ downgradeAt: zod_1.z.string().nullable(),
362
+ currentActiveProjects: zod_1.z.number(),
363
+ maximumActiveProjects: zod_1.z.number(),
364
+ priceList: zod_1.z.array(exports.FormattedPriceListingSchema),
365
+ workspaceId: zod_1.z.number(),
366
+ isTrialing: zod_1.z.boolean(),
367
+ trialEndsAt: zod_1.z.string().nullable(),
368
+ cancelAtPeriodEnd: zod_1.z.boolean(),
369
+ hasTrialed: zod_1.z.boolean(),
370
+ planPrice: exports.PlanPriceSchema.nullable(),
371
+ hasBillingPortal: zod_1.z.boolean(),
372
+ hasBillingPortalSwitchToAnnual: zod_1.z.boolean(),
373
+ });
374
+ exports.JoinWorkspaceResultSchema = zod_1.z.object({
375
+ custom_sorting_applied: zod_1.z.boolean(),
376
+ project_sort_preference: zod_1.z.string(),
377
+ role: exports.WorkspaceRoleSchema,
378
+ user_id: zod_1.z.string(),
379
+ workspace_id: zod_1.z.string(),
380
+ });
@@ -1 +1 @@
1
- export type HttpMethod = 'POST' | 'GET' | 'DELETE';
1
+ export type HttpMethod = 'POST' | 'GET' | 'DELETE' | 'PUT';
@@ -478,4 +478,173 @@ export type GetActivityLogsResponse = {
478
478
  results: ActivityEvent[];
479
479
  nextCursor: string | null;
480
480
  };
481
+ /**
482
+ * Arguments for uploading a file.
483
+ * @see https://todoist.com/api/v1/docs#tag/Uploads/operation/upload_file_api_v1_uploads_post
484
+ */
485
+ export type UploadFileArgs = {
486
+ /**
487
+ * The file content to upload. Can be:
488
+ * - Buffer: File content as a Buffer (requires fileName)
489
+ * - ReadableStream: File content as a stream (requires fileName)
490
+ * - string: Path to a file on the filesystem (fileName is optional, will be inferred from path)
491
+ */
492
+ file: Buffer | NodeJS.ReadableStream | string;
493
+ /**
494
+ * The name of the file. Required for Buffer and Stream inputs.
495
+ * Optional for file path strings (will be inferred from the path if not provided).
496
+ */
497
+ fileName?: string;
498
+ /**
499
+ * The project ID to associate the upload with.
500
+ */
501
+ projectId?: string | null;
502
+ };
503
+ /**
504
+ * Arguments for deleting an uploaded file.
505
+ * @see https://todoist.com/api/v1/docs#tag/Uploads/operation/delete_upload_api_v1_uploads_delete
506
+ */
507
+ export type DeleteUploadArgs = {
508
+ /**
509
+ * The URL of the file to delete.
510
+ */
511
+ fileUrl: string;
512
+ };
513
+ /**
514
+ * Arguments for getting workspace invitations.
515
+ */
516
+ export type GetWorkspaceInvitationsArgs = {
517
+ /**
518
+ * The workspace ID to get invitations for.
519
+ */
520
+ workspaceId: number;
521
+ };
522
+ /**
523
+ * Arguments for deleting a workspace invitation.
524
+ */
525
+ export type DeleteWorkspaceInvitationArgs = {
526
+ /**
527
+ * The workspace ID.
528
+ */
529
+ workspaceId: number;
530
+ /**
531
+ * The email address of the invitation to delete.
532
+ */
533
+ userEmail: string;
534
+ };
535
+ /**
536
+ * Arguments for accepting/rejecting a workspace invitation.
537
+ */
538
+ export type WorkspaceInvitationActionArgs = {
539
+ /**
540
+ * The invitation code from the email.
541
+ */
542
+ inviteCode: string;
543
+ };
544
+ /**
545
+ * Arguments for joining a workspace.
546
+ */
547
+ export type JoinWorkspaceArgs = {
548
+ /**
549
+ * Optional invitation code/link to join via.
550
+ */
551
+ inviteCode?: string | null;
552
+ /**
553
+ * Optional workspace ID to join via domain auto-join.
554
+ */
555
+ workspaceId?: number | null;
556
+ };
557
+ /**
558
+ * Arguments for uploading/updating workspace logo.
559
+ */
560
+ export type WorkspaceLogoArgs = {
561
+ /**
562
+ * The workspace ID.
563
+ */
564
+ workspaceId: number;
565
+ /**
566
+ * The image file to upload (Buffer, Stream, or file path).
567
+ */
568
+ file?: Buffer | NodeJS.ReadableStream | string;
569
+ /**
570
+ * The file name (required for Buffer/Stream uploads).
571
+ */
572
+ fileName?: string;
573
+ /**
574
+ * Whether to delete the logo instead of updating it.
575
+ */
576
+ delete?: boolean;
577
+ };
578
+ /**
579
+ * Arguments for getting workspace plan details.
580
+ */
581
+ export type GetWorkspacePlanDetailsArgs = {
582
+ /**
583
+ * The workspace ID.
584
+ */
585
+ workspaceId: number;
586
+ };
587
+ /**
588
+ * Arguments for getting workspace users (paginated).
589
+ */
590
+ export type GetWorkspaceUsersArgs = {
591
+ /**
592
+ * Optional workspace ID. If not provided, returns users for all workspaces.
593
+ */
594
+ workspaceId?: number | null;
595
+ /**
596
+ * Cursor for pagination.
597
+ */
598
+ cursor?: string | null;
599
+ /**
600
+ * Maximum number of users to return (default: 100).
601
+ */
602
+ limit?: number;
603
+ };
604
+ /**
605
+ * Arguments for getting workspace projects (paginated).
606
+ */
607
+ export type GetWorkspaceProjectsArgs = {
608
+ /**
609
+ * The workspace ID.
610
+ */
611
+ workspaceId: number;
612
+ /**
613
+ * Cursor for pagination.
614
+ */
615
+ cursor?: string | null;
616
+ /**
617
+ * Maximum number of projects to return (default: 100).
618
+ */
619
+ limit?: number;
620
+ };
621
+ /**
622
+ * Paginated response for workspace users.
623
+ */
624
+ export type GetWorkspaceUsersResponse = {
625
+ /**
626
+ * Whether there are more users available.
627
+ */
628
+ hasMore: boolean;
629
+ /**
630
+ * Cursor for the next page of results.
631
+ */
632
+ nextCursor?: string;
633
+ /**
634
+ * Array of workspace users.
635
+ */
636
+ workspaceUsers: import('./entities').WorkspaceUser[];
637
+ };
638
+ /**
639
+ * Response type for workspace invitations endpoint (simple email list).
640
+ */
641
+ export type WorkspaceInvitationsResponse = string[];
642
+ /**
643
+ * Response type for all workspace invitations endpoint (detailed objects).
644
+ */
645
+ export type AllWorkspaceInvitationsResponse = import('./entities').WorkspaceInvitation[];
646
+ /**
647
+ * Response type for workspace logo upload.
648
+ */
649
+ export type WorkspaceLogoResponse = Record<string, unknown> | null;
481
650
  export {};
@@ -1,3 +1,3 @@
1
1
  export * from './colors';
2
2
  export * from './sanitization';
3
- export { getTaskUrl, getProjectUrl, getSectionUrl } from './urlHelpers';
3
+ export { getTaskUrl, getProjectUrl, getSectionUrl } from './url-helpers';
@@ -17,7 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.getSectionUrl = exports.getProjectUrl = exports.getTaskUrl = void 0;
18
18
  __exportStar(require("./colors"), exports);
19
19
  __exportStar(require("./sanitization"), exports);
20
- var urlHelpers_1 = require("./urlHelpers");
21
- Object.defineProperty(exports, "getTaskUrl", { enumerable: true, get: function () { return urlHelpers_1.getTaskUrl; } });
22
- Object.defineProperty(exports, "getProjectUrl", { enumerable: true, get: function () { return urlHelpers_1.getProjectUrl; } });
23
- Object.defineProperty(exports, "getSectionUrl", { enumerable: true, get: function () { return urlHelpers_1.getSectionUrl; } });
20
+ var url_helpers_1 = require("./url-helpers");
21
+ Object.defineProperty(exports, "getTaskUrl", { enumerable: true, get: function () { return url_helpers_1.getTaskUrl; } });
22
+ Object.defineProperty(exports, "getProjectUrl", { enumerable: true, get: function () { return url_helpers_1.getProjectUrl; } });
23
+ Object.defineProperty(exports, "getSectionUrl", { enumerable: true, get: function () { return url_helpers_1.getSectionUrl; } });
@@ -0,0 +1,50 @@
1
+ type UploadMultipartFileArgs = {
2
+ baseUrl: string;
3
+ authToken: string;
4
+ endpoint: string;
5
+ file: Buffer | NodeJS.ReadableStream | string;
6
+ fileName?: string;
7
+ additionalFields: Record<string, string | number | boolean>;
8
+ requestId?: string;
9
+ };
10
+ /**
11
+ * Uploads a file using multipart/form-data.
12
+ *
13
+ * This is a shared utility for uploading files to Todoist endpoints that require
14
+ * multipart/form-data content type (e.g., file uploads, workspace logo uploads).
15
+ *
16
+ * @param baseUrl - The base API URL (e.g., https://api.todoist.com/api/v1/)
17
+ * @param authToken - The authentication token
18
+ * @param endpoint - The relative endpoint path (e.g., 'uploads', 'workspaces/logo')
19
+ * @param file - The file content (Buffer, ReadableStream, or file system path)
20
+ * @param fileName - Optional file name (required for Buffer/Stream, optional for paths)
21
+ * @param additionalFields - Additional form fields to include (e.g., project_id, workspace_id)
22
+ * @param requestId - Optional request ID for idempotency
23
+ * @returns The response data from the server
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // Upload from a file path
28
+ * const result = await uploadMultipartFile(
29
+ * 'https://api.todoist.com/api/v1/',
30
+ * 'my-token',
31
+ * 'uploads',
32
+ * '/path/to/file.pdf',
33
+ * undefined,
34
+ * { project_id: '12345' }
35
+ * )
36
+ *
37
+ * // Upload from a Buffer
38
+ * const buffer = Buffer.from('file content')
39
+ * const result = await uploadMultipartFile(
40
+ * 'https://api.todoist.com/api/v1/',
41
+ * 'my-token',
42
+ * 'uploads',
43
+ * buffer,
44
+ * 'document.pdf',
45
+ * { project_id: '12345' }
46
+ * )
47
+ * ```
48
+ */
49
+ export declare function uploadMultipartFile<T>(args: UploadMultipartFileArgs): Promise<T>;
50
+ export {};
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
24
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ var __importDefault = (this && this.__importDefault) || function (mod) {
50
+ return (mod && mod.__esModule) ? mod : { "default": mod };
51
+ };
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ exports.uploadMultipartFile = uploadMultipartFile;
54
+ var form_data_1 = __importDefault(require("form-data"));
55
+ var fs_1 = require("fs");
56
+ var path_1 = require("path");
57
+ var axios_1 = __importDefault(require("axios"));
58
+ /**
59
+ * Helper function to determine content-type from filename extension.
60
+ * @param fileName - The filename to analyze
61
+ * @returns The appropriate MIME type
62
+ */
63
+ function getContentTypeFromFileName(fileName) {
64
+ var extension = fileName.toLowerCase().split('.').pop();
65
+ switch (extension) {
66
+ case 'png':
67
+ return 'image/png';
68
+ case 'jpg':
69
+ case 'jpeg':
70
+ return 'image/jpeg';
71
+ case 'gif':
72
+ return 'image/gif';
73
+ case 'webp':
74
+ return 'image/webp';
75
+ case 'svg':
76
+ return 'image/svg+xml';
77
+ default:
78
+ return 'application/octet-stream';
79
+ }
80
+ }
81
+ /**
82
+ * Uploads a file using multipart/form-data.
83
+ *
84
+ * This is a shared utility for uploading files to Todoist endpoints that require
85
+ * multipart/form-data content type (e.g., file uploads, workspace logo uploads).
86
+ *
87
+ * @param baseUrl - The base API URL (e.g., https://api.todoist.com/api/v1/)
88
+ * @param authToken - The authentication token
89
+ * @param endpoint - The relative endpoint path (e.g., 'uploads', 'workspaces/logo')
90
+ * @param file - The file content (Buffer, ReadableStream, or file system path)
91
+ * @param fileName - Optional file name (required for Buffer/Stream, optional for paths)
92
+ * @param additionalFields - Additional form fields to include (e.g., project_id, workspace_id)
93
+ * @param requestId - Optional request ID for idempotency
94
+ * @returns The response data from the server
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * // Upload from a file path
99
+ * const result = await uploadMultipartFile(
100
+ * 'https://api.todoist.com/api/v1/',
101
+ * 'my-token',
102
+ * 'uploads',
103
+ * '/path/to/file.pdf',
104
+ * undefined,
105
+ * { project_id: '12345' }
106
+ * )
107
+ *
108
+ * // Upload from a Buffer
109
+ * const buffer = Buffer.from('file content')
110
+ * const result = await uploadMultipartFile(
111
+ * 'https://api.todoist.com/api/v1/',
112
+ * 'my-token',
113
+ * 'uploads',
114
+ * buffer,
115
+ * 'document.pdf',
116
+ * { project_id: '12345' }
117
+ * )
118
+ * ```
119
+ */
120
+ function uploadMultipartFile(args) {
121
+ return __awaiter(this, void 0, void 0, function () {
122
+ var baseUrl, authToken, endpoint, file, fileName, additionalFields, requestId, form, filePath, resolvedFileName, contentType, _i, _a, _b, key, value, url, headers, response;
123
+ return __generator(this, function (_c) {
124
+ switch (_c.label) {
125
+ case 0:
126
+ baseUrl = args.baseUrl, authToken = args.authToken, endpoint = args.endpoint, file = args.file, fileName = args.fileName, additionalFields = args.additionalFields, requestId = args.requestId;
127
+ form = new form_data_1.default();
128
+ // Determine file type and add to form data
129
+ if (typeof file === 'string') {
130
+ filePath = file;
131
+ resolvedFileName = fileName || (0, path_1.basename)(filePath);
132
+ form.append('file', (0, fs_1.createReadStream)(filePath), resolvedFileName);
133
+ }
134
+ else if (Buffer.isBuffer(file)) {
135
+ // Buffer - require fileName
136
+ if (!fileName) {
137
+ throw new Error('fileName is required when uploading from a Buffer');
138
+ }
139
+ contentType = getContentTypeFromFileName(fileName);
140
+ form.append('file', file, {
141
+ filename: fileName,
142
+ contentType: contentType,
143
+ });
144
+ }
145
+ else {
146
+ // Stream - require fileName
147
+ if (!fileName) {
148
+ throw new Error('fileName is required when uploading from a stream');
149
+ }
150
+ form.append('file', file, fileName);
151
+ }
152
+ // Add additional fields to the form
153
+ for (_i = 0, _a = Object.entries(additionalFields); _i < _a.length; _i++) {
154
+ _b = _a[_i], key = _b[0], value = _b[1];
155
+ if (value !== undefined && value !== null) {
156
+ form.append(key, value.toString());
157
+ }
158
+ }
159
+ url = "".concat(baseUrl).concat(endpoint);
160
+ headers = __assign({ Authorization: "Bearer ".concat(authToken) }, form.getHeaders());
161
+ if (requestId) {
162
+ headers['X-Request-Id'] = requestId;
163
+ }
164
+ return [4 /*yield*/, axios_1.default.post(url, form, { headers: headers })];
165
+ case 1:
166
+ response = _c.sent();
167
+ return [2 /*return*/, response.data];
168
+ }
169
+ });
170
+ });
171
+ }
@@ -1,4 +1,4 @@
1
- import { type Task, type Section, type Label, type Comment, type User, type CurrentUser, type ProductivityStats, type WorkspaceProject, type PersonalProject, type ActivityEvent } from '../types/entities';
1
+ import { type Attachment, type Task, type Section, type Label, type Comment, type User, type CurrentUser, type ProductivityStats, type WorkspaceProject, type PersonalProject, type ActivityEvent, type WorkspaceUser, type WorkspaceInvitation, type WorkspacePlanDetails, type JoinWorkspaceResult } from '../types/entities';
2
2
  export declare function validateTask(input: unknown): Task;
3
3
  export declare function validateTaskArray(input: unknown[]): Task[];
4
4
  /**
@@ -32,3 +32,10 @@ export declare function validateProductivityStats(input: unknown): ProductivityS
32
32
  export declare function validateCurrentUser(input: unknown): CurrentUser;
33
33
  export declare function validateActivityEvent(input: unknown): ActivityEvent;
34
34
  export declare function validateActivityEventArray(input: unknown[]): ActivityEvent[];
35
+ export declare function validateAttachment(input: unknown): Attachment;
36
+ export declare function validateWorkspaceUser(input: unknown): WorkspaceUser;
37
+ export declare function validateWorkspaceUserArray(input: unknown): WorkspaceUser[];
38
+ export declare function validateWorkspaceInvitation(input: unknown): WorkspaceInvitation;
39
+ export declare function validateWorkspaceInvitationArray(input: unknown[]): WorkspaceInvitation[];
40
+ export declare function validateWorkspacePlanDetails(input: unknown): WorkspacePlanDetails;
41
+ export declare function validateJoinWorkspaceResult(input: unknown): JoinWorkspaceResult;