@vitalyostanin/youtrack-mcp 0.2.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 (39) hide show
  1. package/README-ru.md +283 -0
  2. package/README.md +290 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.js +13 -0
  5. package/dist/src/config.d.ts +10 -0
  6. package/dist/src/config.js +68 -0
  7. package/dist/src/server.d.ts +8 -0
  8. package/dist/src/server.js +48 -0
  9. package/dist/src/tools/article-search-tools.d.ts +4 -0
  10. package/dist/src/tools/article-search-tools.js +31 -0
  11. package/dist/src/tools/article-tools.d.ts +4 -0
  12. package/dist/src/tools/article-tools.js +98 -0
  13. package/dist/src/tools/attachment-tools.d.ts +4 -0
  14. package/dist/src/tools/attachment-tools.js +100 -0
  15. package/dist/src/tools/issue-search-tools.d.ts +4 -0
  16. package/dist/src/tools/issue-search-tools.js +56 -0
  17. package/dist/src/tools/issue-tools.d.ts +4 -0
  18. package/dist/src/tools/issue-tools.js +190 -0
  19. package/dist/src/tools/project-tools.d.ts +4 -0
  20. package/dist/src/tools/project-tools.js +35 -0
  21. package/dist/src/tools/service-info.d.ts +4 -0
  22. package/dist/src/tools/service-info.js +61 -0
  23. package/dist/src/tools/user-tools.d.ts +4 -0
  24. package/dist/src/tools/user-tools.js +46 -0
  25. package/dist/src/tools/workitem-report-tools.d.ts +4 -0
  26. package/dist/src/tools/workitem-report-tools.js +62 -0
  27. package/dist/src/tools/workitem-tools.d.ts +4 -0
  28. package/dist/src/tools/workitem-tools.js +247 -0
  29. package/dist/src/types.d.ts +433 -0
  30. package/dist/src/types.js +2 -0
  31. package/dist/src/utils/date.d.ts +34 -0
  32. package/dist/src/utils/date.js +147 -0
  33. package/dist/src/utils/mappers.d.ts +76 -0
  34. package/dist/src/utils/mappers.js +126 -0
  35. package/dist/src/utils/tool-response.d.ts +4 -0
  36. package/dist/src/utils/tool-response.js +61 -0
  37. package/dist/src/youtrack-client.d.ts +86 -0
  38. package/dist/src/youtrack-client.js +1220 -0
  39. package/package.json +65 -0
@@ -0,0 +1,433 @@
1
+ import type { MappedYoutrackIssue, MappedYoutrackIssueComment, MappedYoutrackIssueDetails, MappedYoutrackWorkItem } from "./utils/mappers.js";
2
+ export interface ServiceInfo {
3
+ name: string;
4
+ version: string;
5
+ description?: string;
6
+ }
7
+ export type UserAliasMap = Record<string, string>;
8
+ export interface YoutrackConfig {
9
+ baseUrl: string;
10
+ token: string;
11
+ timezone: string;
12
+ holidays?: string[];
13
+ preHolidays?: string[];
14
+ userAliases?: UserAliasMap;
15
+ }
16
+ export interface DurationValue {
17
+ minutes?: number;
18
+ presentation?: string;
19
+ $type?: string;
20
+ }
21
+ export interface YoutrackProject {
22
+ id: string;
23
+ shortName: string;
24
+ name?: string;
25
+ }
26
+ export interface YoutrackIssue {
27
+ id: string;
28
+ idReadable: string;
29
+ summary?: string;
30
+ description?: string;
31
+ wikifiedDescription?: string;
32
+ usesMarkdown?: boolean;
33
+ project?: YoutrackProject;
34
+ parent?: {
35
+ idReadable: string;
36
+ id?: string;
37
+ } | null;
38
+ assignee?: YoutrackUser | null;
39
+ }
40
+ export interface YoutrackIssueCreateInput {
41
+ project: string;
42
+ summary: string;
43
+ description?: string;
44
+ parentIssueId?: string;
45
+ assigneeLogin?: string;
46
+ usesMarkdown?: boolean;
47
+ }
48
+ export interface YoutrackIssueUpdateInput {
49
+ issueId: string;
50
+ summary?: string;
51
+ description?: string;
52
+ parentIssueId?: string | null;
53
+ usesMarkdown?: boolean;
54
+ }
55
+ export interface YoutrackIssueAssignInput {
56
+ issueId: string;
57
+ assigneeLogin: string;
58
+ }
59
+ export interface YoutrackUser {
60
+ id: string;
61
+ login: string;
62
+ name?: string;
63
+ fullName?: string;
64
+ email?: string;
65
+ }
66
+ export interface YoutrackUserListPayload {
67
+ users: YoutrackUser[];
68
+ }
69
+ export interface YoutrackProjectListPayload {
70
+ projects: YoutrackProject[];
71
+ }
72
+ export interface YoutrackWorkItem {
73
+ id: string;
74
+ date: number;
75
+ updated?: number;
76
+ duration: DurationValue;
77
+ text?: string;
78
+ textPreview?: string;
79
+ usesMarkdown?: boolean;
80
+ description?: string;
81
+ issue: {
82
+ idReadable: string;
83
+ id?: string;
84
+ };
85
+ author?: YoutrackUser;
86
+ }
87
+ export interface YoutrackWorkItemCreateInput {
88
+ issueId: string;
89
+ date: string | number | Date;
90
+ minutes: number;
91
+ summary?: string;
92
+ description?: string;
93
+ usesMarkdown?: boolean;
94
+ }
95
+ export interface YoutrackWorkItemUpdateInput {
96
+ issueId: string;
97
+ workItemId: string;
98
+ date?: string | number | Date;
99
+ minutes?: number;
100
+ summary?: string;
101
+ description?: string;
102
+ usesMarkdown?: boolean;
103
+ }
104
+ export interface YoutrackWorkItemPeriodCreateInput {
105
+ issueId: string;
106
+ startDate: string | number | Date;
107
+ endDate: string | number | Date;
108
+ minutes: number;
109
+ summary?: string;
110
+ description?: string;
111
+ usesMarkdown?: boolean;
112
+ excludeWeekends?: boolean;
113
+ excludeHolidays?: boolean;
114
+ holidays?: Array<string | number | Date>;
115
+ preHolidays?: Array<string | number | Date>;
116
+ }
117
+ export interface YoutrackWorkItemIdempotentCreateInput {
118
+ issueId: string;
119
+ date: string | number | Date;
120
+ minutes: number;
121
+ description: string;
122
+ usesMarkdown?: boolean;
123
+ }
124
+ export interface YoutrackWorkItemReportOptions {
125
+ author?: string;
126
+ startDate?: string | number | Date;
127
+ endDate?: string | number | Date;
128
+ issueId?: string;
129
+ expectedDailyMinutes?: number;
130
+ excludeWeekends?: boolean;
131
+ excludeHolidays?: boolean;
132
+ holidays?: Array<string | number | Date>;
133
+ preHolidays?: Array<string | number | Date>;
134
+ allUsers?: boolean;
135
+ }
136
+ export interface ServiceStatusPayload {
137
+ service: ServiceInfo;
138
+ configuration: {
139
+ hasToken: boolean;
140
+ baseUrl: string | null;
141
+ holidays?: string[];
142
+ preHolidays?: string[];
143
+ };
144
+ }
145
+ export interface IssueLookupPayload {
146
+ issue: MappedYoutrackIssue;
147
+ }
148
+ export interface WorkItemsPayload {
149
+ items: MappedYoutrackWorkItem[];
150
+ }
151
+ export interface WorkItemCreatePayload {
152
+ item: MappedYoutrackWorkItem;
153
+ }
154
+ export interface WorkItemUpdatePayload {
155
+ item: MappedYoutrackWorkItem;
156
+ }
157
+ export interface WorkItemDeletePayload {
158
+ issueId: string;
159
+ workItemId: string;
160
+ deleted: true;
161
+ }
162
+ export interface YoutrackIssueDetails extends YoutrackIssue {
163
+ created?: number | null;
164
+ updated?: number | null;
165
+ resolved?: number | null;
166
+ reporter?: YoutrackUser;
167
+ updater?: YoutrackUser;
168
+ }
169
+ export interface IssueDetailsPayload {
170
+ issue: MappedYoutrackIssueDetails;
171
+ }
172
+ export interface YoutrackIssueComment {
173
+ id: string;
174
+ text?: string;
175
+ textPreview?: string;
176
+ usesMarkdown?: boolean;
177
+ author?: YoutrackUser;
178
+ created: number;
179
+ updated?: number;
180
+ }
181
+ export interface IssueCommentsPayload {
182
+ comments: MappedYoutrackIssueComment[];
183
+ }
184
+ export interface IssueCommentCreateInput {
185
+ issueId: string;
186
+ text: string;
187
+ usesMarkdown?: boolean;
188
+ }
189
+ export interface YoutrackActivityItem {
190
+ id: string;
191
+ timestamp: number;
192
+ author?: YoutrackUser;
193
+ category?: {
194
+ id: string;
195
+ };
196
+ target?: {
197
+ text?: string;
198
+ };
199
+ added?: Array<{
200
+ name?: string;
201
+ id?: string;
202
+ login?: string;
203
+ }>;
204
+ removed?: Array<{
205
+ name?: string;
206
+ id?: string;
207
+ login?: string;
208
+ }>;
209
+ $type?: string;
210
+ }
211
+ export interface IssueCommentCreatePayload {
212
+ comment: MappedYoutrackIssueComment;
213
+ }
214
+ export interface WorkItemReportDay {
215
+ date: string;
216
+ expectedMinutes: number;
217
+ actualMinutes: number;
218
+ difference: number;
219
+ percent: number;
220
+ items: MappedYoutrackWorkItem[];
221
+ }
222
+ export interface WorkItemSummary {
223
+ totalMinutes: number;
224
+ totalHours: number;
225
+ expectedMinutes: number;
226
+ expectedHours: number;
227
+ workDays: number;
228
+ averageHoursPerDay: number;
229
+ }
230
+ export interface WorkItemReportPayload {
231
+ summary: WorkItemSummary;
232
+ days: WorkItemReportDay[];
233
+ period: {
234
+ startDate: string;
235
+ endDate: string;
236
+ };
237
+ invalidDays: WorkItemInvalidDay[];
238
+ }
239
+ export interface WorkItemBulkResultPayload {
240
+ created: MappedYoutrackWorkItem[];
241
+ failed: Array<{
242
+ date: string;
243
+ reason: string;
244
+ }>;
245
+ }
246
+ export interface WorkItemInvalidDay {
247
+ date: string;
248
+ expectedMinutes: number;
249
+ actualMinutes: number;
250
+ difference: number;
251
+ percent: number;
252
+ items: MappedYoutrackWorkItem[];
253
+ }
254
+ export interface WorkItemUsersReportPayload {
255
+ reports: Array<{
256
+ userLogin: string;
257
+ summary: WorkItemSummary;
258
+ invalidDays: WorkItemInvalidDay[];
259
+ period: {
260
+ startDate: string;
261
+ endDate: string;
262
+ };
263
+ }>;
264
+ }
265
+ export interface WorkItemsForUsersPayload {
266
+ items: MappedYoutrackWorkItem[];
267
+ users: string[];
268
+ }
269
+ export interface WorkItemsAllUsersPayload {
270
+ items: MappedYoutrackWorkItem[];
271
+ }
272
+ export interface WorkItemIdempotentCreatePayload {
273
+ created: boolean;
274
+ item: MappedYoutrackWorkItem | null;
275
+ }
276
+ export interface YoutrackArticle {
277
+ id: string;
278
+ idReadable: string;
279
+ summary: string;
280
+ content?: string;
281
+ contentPreview?: string;
282
+ usesMarkdown?: boolean;
283
+ parentArticle?: {
284
+ id: string;
285
+ idReadable: string;
286
+ };
287
+ childArticles?: Array<{
288
+ id: string;
289
+ idReadable: string;
290
+ summary: string;
291
+ }>;
292
+ project?: {
293
+ id: string;
294
+ shortName: string;
295
+ name?: string;
296
+ };
297
+ }
298
+ export interface ArticlePayload {
299
+ article: YoutrackArticle;
300
+ }
301
+ export interface ArticleListPayload {
302
+ articles: YoutrackArticle[];
303
+ }
304
+ export interface ArticleCreateInput {
305
+ summary: string;
306
+ content?: string;
307
+ parentArticleId?: string;
308
+ projectId?: string;
309
+ usesMarkdown?: boolean;
310
+ returnRendered?: boolean;
311
+ }
312
+ export interface ArticleUpdateInput {
313
+ articleId: string;
314
+ summary?: string;
315
+ content?: string;
316
+ usesMarkdown?: boolean;
317
+ returnRendered?: boolean;
318
+ }
319
+ export interface ArticleSearchInput {
320
+ query: string;
321
+ projectId?: string;
322
+ parentArticleId?: string;
323
+ limit?: number;
324
+ returnRendered?: boolean;
325
+ }
326
+ export interface ArticleSearchPayload {
327
+ articles: YoutrackArticle[];
328
+ query: string;
329
+ }
330
+ export interface IssueSearchInput {
331
+ userLogins: string[];
332
+ startDate?: string | number | Date;
333
+ endDate?: string | number | Date;
334
+ dateFilterMode?: "issue_updated" | "user_activity";
335
+ limit?: number;
336
+ skip?: number;
337
+ }
338
+ export interface IssueSearchPayload {
339
+ issues: Array<MappedYoutrackIssue & {
340
+ lastActivityDate?: string;
341
+ }>;
342
+ userLogins: string[];
343
+ period?: {
344
+ startDate?: string;
345
+ endDate?: string;
346
+ };
347
+ pagination: {
348
+ returned: number;
349
+ limit: number;
350
+ skip: number;
351
+ };
352
+ }
353
+ export interface IssueError {
354
+ issueId: string;
355
+ error: string;
356
+ }
357
+ export interface IssuesLookupPayload {
358
+ issues: MappedYoutrackIssue[];
359
+ errors?: IssueError[];
360
+ }
361
+ export interface IssuesDetailsPayload {
362
+ issues: MappedYoutrackIssueDetails[];
363
+ errors?: IssueError[];
364
+ }
365
+ export interface IssuesCommentsPayload {
366
+ commentsByIssue: Record<string, MappedYoutrackIssueComment[]>;
367
+ errors?: IssueError[];
368
+ }
369
+ export interface YoutrackAttachment {
370
+ id: string;
371
+ name: string;
372
+ author?: YoutrackUser;
373
+ created: number;
374
+ updated?: number;
375
+ size: number;
376
+ mimeType?: string;
377
+ url?: string;
378
+ thumbnailURL?: string;
379
+ extension?: string;
380
+ charset?: string;
381
+ base64Content?: string;
382
+ }
383
+ export interface MappedYoutrackAttachment {
384
+ id: string;
385
+ name: string;
386
+ author?: {
387
+ id: string;
388
+ login: string;
389
+ name?: string;
390
+ };
391
+ created: string;
392
+ updated?: string;
393
+ size: number;
394
+ sizeFormatted: string;
395
+ mimeType?: string;
396
+ extension?: string;
397
+ url?: string;
398
+ thumbnailURL?: string;
399
+ }
400
+ export interface AttachmentsListPayload {
401
+ attachments: MappedYoutrackAttachment[];
402
+ issueId: string;
403
+ }
404
+ export interface AttachmentPayload {
405
+ attachment: MappedYoutrackAttachment;
406
+ issueId: string;
407
+ }
408
+ export interface AttachmentDownloadPayload {
409
+ attachment: MappedYoutrackAttachment;
410
+ downloadUrl: string;
411
+ issueId: string;
412
+ }
413
+ export interface AttachmentUploadInput {
414
+ issueId: string;
415
+ filePaths: string[];
416
+ muteUpdateNotifications?: boolean;
417
+ }
418
+ export interface AttachmentUploadPayload {
419
+ uploaded: MappedYoutrackAttachment[];
420
+ issueId: string;
421
+ }
422
+ export interface AttachmentDeleteInput {
423
+ issueId: string;
424
+ attachmentId: string;
425
+ confirmation: boolean;
426
+ }
427
+ export interface AttachmentDeletePayload {
428
+ deleted: true;
429
+ issueId: string;
430
+ attachmentId: string;
431
+ attachmentName: string;
432
+ }
433
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,34 @@
1
+ export declare function initializeTimezone(timezone: string): void;
2
+ export declare function getTimezone(): string;
3
+ export declare function parseDateInput(value: string | number | Date): number;
4
+ export declare function toIsoDateString(value: string | number | Date): string;
5
+ export declare function enumerateDateRange(start: string | number | Date, end: string | number | Date): string[];
6
+ export declare function isWeekend(dateIso: string): boolean;
7
+ export declare function isHoliday(date: string | number | Date, holidays?: Array<string | number | Date>): boolean;
8
+ export declare function filterWorkingDays(dates: Array<string | Date | number>, excludeWeekends?: boolean, excludeHolidays?: boolean, holidays?: Array<string | Date | number>): string[];
9
+ export declare function getDayBounds(value: string | number | Date): {
10
+ start: number;
11
+ end: number;
12
+ };
13
+ export declare function minutesToHours(minutes: number): number;
14
+ export declare function hoursToMinutes(hours: number): number;
15
+ export declare function calculateTotalMinutes(items: Array<{
16
+ duration: {
17
+ minutes?: number;
18
+ };
19
+ }>): number;
20
+ export declare function groupWorkItemsByDate<T extends {
21
+ date: number;
22
+ }>(items: T[]): Map<string, T[]>;
23
+ export declare function validateDateRange(start: string | number | Date, end: string | number | Date): void;
24
+ export declare function isWorkingDay(value: string | number | Date): boolean;
25
+ export declare function dateToUnixMs(value: string | Date, timezone?: string): number;
26
+ export declare function unixMsToDate(timestamp: number): Date;
27
+ export declare function formatDate(value: string | number | Date): string;
28
+ export declare function formatDateInTimezone(value: string | number | Date, timezone: string): string;
29
+ export declare function generateDateRange(start: string | number | Date, end: string | number | Date): Date[];
30
+ export declare function filterWorkingDates(dates: Date[], excludeWeekends?: boolean, excludeHolidays?: boolean, holidays?: Date[]): Date[];
31
+ export declare function isSameDay(left: string | number | Date, right: string | number | Date): boolean;
32
+ export declare function getCurrentTimestamp(): number;
33
+ export declare function getCurrentDate(timezone?: string): Date;
34
+ //# sourceMappingURL=date.d.ts.map
@@ -0,0 +1,147 @@
1
+ import { DateTime, Settings } from "luxon";
2
+ let currentTimezone = "Europe/Moscow";
3
+ export function initializeTimezone(timezone) {
4
+ currentTimezone = timezone;
5
+ Settings.defaultZone = timezone;
6
+ }
7
+ export function getTimezone() {
8
+ return currentTimezone;
9
+ }
10
+ export function parseDateInput(value) {
11
+ if (value instanceof Date) {
12
+ return DateTime.fromJSDate(value).toMillis();
13
+ }
14
+ if (typeof value === "number") {
15
+ if (!Number.isFinite(value)) {
16
+ throw new Error("Date value must be a finite number");
17
+ }
18
+ return value;
19
+ }
20
+ const parsed = DateTime.fromISO(value, { zone: currentTimezone });
21
+ if (!parsed.isValid) {
22
+ throw new Error(`Invalid date value: ${value}`);
23
+ }
24
+ return parsed.toMillis();
25
+ }
26
+ export function toIsoDateString(value) {
27
+ const timestamp = parseDateInput(value);
28
+ return DateTime.fromMillis(timestamp).toFormat("yyyy-MM-dd");
29
+ }
30
+ export function enumerateDateRange(start, end) {
31
+ const startTime = DateTime.fromMillis(parseDateInput(start)).startOf("day");
32
+ const endTime = DateTime.fromMillis(parseDateInput(end)).startOf("day");
33
+ if (endTime < startTime) {
34
+ throw new Error("End date cannot be earlier than start date");
35
+ }
36
+ const dates = [];
37
+ for (let current = startTime; current <= endTime; current = current.plus({ days: 1 })) {
38
+ dates.push(current.toFormat("yyyy-MM-dd"));
39
+ }
40
+ return dates;
41
+ }
42
+ export function isWeekend(dateIso) {
43
+ const date = DateTime.fromISO(dateIso);
44
+ return date.weekday === 6 || date.weekday === 7;
45
+ }
46
+ export function isHoliday(date, holidays = []) {
47
+ const target = toIsoDateString(date);
48
+ return holidays.some((holiday) => toIsoDateString(holiday) === target);
49
+ }
50
+ export function filterWorkingDays(dates, excludeWeekends = true, excludeHolidays = true, holidays = []) {
51
+ return dates
52
+ .map((value) => toIsoDateString(value))
53
+ .filter((dateIso) => {
54
+ if (excludeWeekends && isWeekend(dateIso)) {
55
+ return false;
56
+ }
57
+ if (excludeHolidays && isHoliday(dateIso, holidays)) {
58
+ return false;
59
+ }
60
+ return true;
61
+ });
62
+ }
63
+ export function getDayBounds(value) {
64
+ const date = DateTime.fromMillis(parseDateInput(value));
65
+ const start = date.startOf("day");
66
+ const end = date.endOf("day");
67
+ return { start: start.toMillis(), end: end.toMillis() };
68
+ }
69
+ export function minutesToHours(minutes) {
70
+ return Math.round((minutes / 60) * 100) / 100;
71
+ }
72
+ export function hoursToMinutes(hours) {
73
+ return Math.round(hours * 60);
74
+ }
75
+ export function calculateTotalMinutes(items) {
76
+ return items.reduce((total, item) => total + (item.duration.minutes ?? 0), 0);
77
+ }
78
+ export function groupWorkItemsByDate(items) {
79
+ const map = new Map();
80
+ for (const item of items) {
81
+ const dateIso = toIsoDateString(item.date);
82
+ const bucket = map.get(dateIso) ?? [];
83
+ bucket.push(item);
84
+ map.set(dateIso, bucket);
85
+ }
86
+ return map;
87
+ }
88
+ export function validateDateRange(start, end) {
89
+ const startTime = DateTime.fromMillis(parseDateInput(start));
90
+ const endTime = DateTime.fromMillis(parseDateInput(end));
91
+ if (endTime < startTime) {
92
+ throw new Error("Start date must be before or equal to end date");
93
+ }
94
+ }
95
+ export function isWorkingDay(value) {
96
+ return !isWeekend(toIsoDateString(value));
97
+ }
98
+ export function dateToUnixMs(value, timezone = currentTimezone) {
99
+ const source = value instanceof Date ? DateTime.fromJSDate(value) : DateTime.fromISO(value);
100
+ const zoned = source.setZone(timezone);
101
+ const normalized = zoned.set({ hour: 12, minute: 0, second: 0, millisecond: 0 });
102
+ return normalized.toMillis();
103
+ }
104
+ export function unixMsToDate(timestamp) {
105
+ return DateTime.fromMillis(timestamp).toJSDate();
106
+ }
107
+ export function formatDate(value) {
108
+ return toIsoDateString(value);
109
+ }
110
+ export function formatDateInTimezone(value, timezone) {
111
+ const timestamp = parseDateInput(value);
112
+ const formatted = DateTime.fromMillis(timestamp).setZone(timezone).toFormat("yyyy-MM-dd");
113
+ return formatted;
114
+ }
115
+ export function generateDateRange(start, end) {
116
+ const startDate = DateTime.fromMillis(parseDateInput(start)).startOf("day");
117
+ const endDate = DateTime.fromMillis(parseDateInput(end)).startOf("day");
118
+ if (endDate < startDate) {
119
+ throw new Error("End date cannot be earlier than start date");
120
+ }
121
+ const dates = [];
122
+ for (let current = startDate; current <= endDate; current = current.plus({ days: 1 })) {
123
+ dates.push(current.toJSDate());
124
+ }
125
+ return dates;
126
+ }
127
+ export function filterWorkingDates(dates, excludeWeekends = true, excludeHolidays = true, holidays = []) {
128
+ return dates.filter((date) => {
129
+ if (excludeWeekends && !isWorkingDay(date)) {
130
+ return false;
131
+ }
132
+ if (excludeHolidays && holidays.some((holiday) => formatDate(holiday) === formatDate(date))) {
133
+ return false;
134
+ }
135
+ return true;
136
+ });
137
+ }
138
+ export function isSameDay(left, right) {
139
+ return formatDate(left) === formatDate(right);
140
+ }
141
+ export function getCurrentTimestamp() {
142
+ return DateTime.now().toMillis();
143
+ }
144
+ export function getCurrentDate(timezone = currentTimezone) {
145
+ return DateTime.now().setZone(timezone).toJSDate();
146
+ }
147
+ //# sourceMappingURL=date.js.map
@@ -0,0 +1,76 @@
1
+ import type { YoutrackAttachment, YoutrackIssue, YoutrackIssueComment, YoutrackIssueDetails, YoutrackWorkItem, MappedYoutrackAttachment } from "../types.js";
2
+ /**
3
+ * Convert timestamp in milliseconds to ISO date string (YYYY-MM-DD)
4
+ */
5
+ export declare function timestampToIsoDate(timestamp: number | null | undefined): string | undefined;
6
+ /**
7
+ * Convert timestamp in milliseconds to ISO datetime string (YYYY-MM-DDTHH:mm:ss.sssZ)
8
+ */
9
+ export declare function timestampToIsoDateTime(timestamp: number | null | undefined): string | undefined;
10
+ /**
11
+ * Mapped issue with ISO date strings
12
+ * Issue type doesn't have date fields, so it's the same as YoutrackIssue
13
+ */
14
+ export type MappedYoutrackIssue = YoutrackIssue;
15
+ /**
16
+ * Mapped issue details with ISO date strings
17
+ */
18
+ export interface MappedYoutrackIssueDetails extends Omit<YoutrackIssueDetails, "created" | "updated" | "resolved"> {
19
+ created?: string;
20
+ updated?: string;
21
+ resolved?: string;
22
+ }
23
+ /**
24
+ * Mapped work item with ISO date strings
25
+ */
26
+ export interface MappedYoutrackWorkItem extends Omit<YoutrackWorkItem, "date"> {
27
+ date: string;
28
+ }
29
+ /**
30
+ * Mapped comment with ISO date strings
31
+ */
32
+ export interface MappedYoutrackIssueComment extends Omit<YoutrackIssueComment, "created" | "updated"> {
33
+ created: string;
34
+ updated?: string;
35
+ }
36
+ /**
37
+ * Map YoutrackIssue to MappedYoutrackIssue
38
+ */
39
+ export declare function mapIssue(issue: YoutrackIssue): MappedYoutrackIssue;
40
+ /**
41
+ * Map YoutrackIssueDetails to MappedYoutrackIssueDetails
42
+ */
43
+ export declare function mapIssueDetails(issue: YoutrackIssueDetails): MappedYoutrackIssueDetails;
44
+ /**
45
+ * Map YoutrackWorkItem to MappedYoutrackWorkItem
46
+ */
47
+ export declare function mapWorkItem(item: YoutrackWorkItem): MappedYoutrackWorkItem;
48
+ /**
49
+ * Map YoutrackIssueComment to MappedYoutrackIssueComment
50
+ */
51
+ export declare function mapComment(comment: YoutrackIssueComment): MappedYoutrackIssueComment;
52
+ /**
53
+ * Map array of issues
54
+ */
55
+ export declare function mapIssues(issues: YoutrackIssue[]): MappedYoutrackIssue[];
56
+ /**
57
+ * Map array of work items
58
+ */
59
+ export declare function mapWorkItems(items: YoutrackWorkItem[]): MappedYoutrackWorkItem[];
60
+ /**
61
+ * Map array of comments
62
+ */
63
+ export declare function mapComments(comments: YoutrackIssueComment[]): MappedYoutrackIssueComment[];
64
+ /**
65
+ * Format file size in bytes to human-readable format
66
+ */
67
+ export declare function formatFileSize(bytes: number): string;
68
+ /**
69
+ * Map YoutrackAttachment to MappedYoutrackAttachment
70
+ */
71
+ export declare function mapAttachment(attachment: YoutrackAttachment): MappedYoutrackAttachment;
72
+ /**
73
+ * Map array of attachments
74
+ */
75
+ export declare function mapAttachments(attachments: YoutrackAttachment[]): MappedYoutrackAttachment[];
76
+ //# sourceMappingURL=mappers.d.ts.map