@meridianjs/issue 0.1.2 → 0.1.4
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/dist/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +39 -6
- package/dist/index.mjs +39 -6
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -33,6 +33,7 @@ interface CreateManualTimeLogInput {
|
|
|
33
33
|
issue_id: string;
|
|
34
34
|
user_id: string;
|
|
35
35
|
workspace_id: string;
|
|
36
|
+
project_id?: string;
|
|
36
37
|
duration_minutes: number;
|
|
37
38
|
description?: string;
|
|
38
39
|
logged_date?: Date;
|
|
@@ -76,7 +77,7 @@ declare class IssueModuleService extends IssueModuleService_base {
|
|
|
76
77
|
* Start a timer for a user on an issue.
|
|
77
78
|
* Throws if the user already has an active timer on this issue.
|
|
78
79
|
*/
|
|
79
|
-
startTimer(issueId: string, userId: string, workspaceId: string): Promise<any>;
|
|
80
|
+
startTimer(issueId: string, userId: string, workspaceId: string, projectId?: string): Promise<any>;
|
|
80
81
|
/**
|
|
81
82
|
* Stop the active timer for a user on an issue.
|
|
82
83
|
* Calculates duration from started_at and finalises the entry.
|
|
@@ -84,6 +85,14 @@ declare class IssueModuleService extends IssueModuleService_base {
|
|
|
84
85
|
stopTimer(issueId: string, userId: string): Promise<any>;
|
|
85
86
|
/** Return the running timer entry for a user on an issue, or null if none. */
|
|
86
87
|
getActiveTimer(issueId: string, userId: string): Promise<any | null>;
|
|
88
|
+
/** Query time logs for reporting — supports filtering by user, project, workspace, and date range.
|
|
89
|
+
* Each returned entry is enriched with `issue_identifier` and `issue_title`. */
|
|
90
|
+
listTimeLogsForReporting(filters: {
|
|
91
|
+
user_id?: string;
|
|
92
|
+
workspace_id?: string;
|
|
93
|
+
project_id?: string;
|
|
94
|
+
logged_date?: Record<string, unknown>;
|
|
95
|
+
}): Promise<any[]>;
|
|
87
96
|
/** Delete a time log entry by ID. */
|
|
88
97
|
deleteTimeLog(id: string): Promise<any>;
|
|
89
98
|
/** List all task lists for a project, ordered by position. */
|
package/dist/index.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ interface CreateManualTimeLogInput {
|
|
|
33
33
|
issue_id: string;
|
|
34
34
|
user_id: string;
|
|
35
35
|
workspace_id: string;
|
|
36
|
+
project_id?: string;
|
|
36
37
|
duration_minutes: number;
|
|
37
38
|
description?: string;
|
|
38
39
|
logged_date?: Date;
|
|
@@ -76,7 +77,7 @@ declare class IssueModuleService extends IssueModuleService_base {
|
|
|
76
77
|
* Start a timer for a user on an issue.
|
|
77
78
|
* Throws if the user already has an active timer on this issue.
|
|
78
79
|
*/
|
|
79
|
-
startTimer(issueId: string, userId: string, workspaceId: string): Promise<any>;
|
|
80
|
+
startTimer(issueId: string, userId: string, workspaceId: string, projectId?: string): Promise<any>;
|
|
80
81
|
/**
|
|
81
82
|
* Stop the active timer for a user on an issue.
|
|
82
83
|
* Calculates duration from started_at and finalises the entry.
|
|
@@ -84,6 +85,14 @@ declare class IssueModuleService extends IssueModuleService_base {
|
|
|
84
85
|
stopTimer(issueId: string, userId: string): Promise<any>;
|
|
85
86
|
/** Return the running timer entry for a user on an issue, or null if none. */
|
|
86
87
|
getActiveTimer(issueId: string, userId: string): Promise<any | null>;
|
|
88
|
+
/** Query time logs for reporting — supports filtering by user, project, workspace, and date range.
|
|
89
|
+
* Each returned entry is enriched with `issue_identifier` and `issue_title`. */
|
|
90
|
+
listTimeLogsForReporting(filters: {
|
|
91
|
+
user_id?: string;
|
|
92
|
+
workspace_id?: string;
|
|
93
|
+
project_id?: string;
|
|
94
|
+
logged_date?: Record<string, unknown>;
|
|
95
|
+
}): Promise<any[]>;
|
|
87
96
|
/** Delete a time log entry by ID. */
|
|
88
97
|
deleteTimeLog(id: string): Promise<any>;
|
|
89
98
|
/** List all task lists for a project, ordered by position. */
|
package/dist/index.js
CHANGED
|
@@ -112,6 +112,7 @@ var TimeLog = import_framework_utils4.model.define("time_log", {
|
|
|
112
112
|
issue_id: import_framework_utils4.model.text(),
|
|
113
113
|
user_id: import_framework_utils4.model.text(),
|
|
114
114
|
workspace_id: import_framework_utils4.model.text(),
|
|
115
|
+
project_id: import_framework_utils4.model.text().nullable(),
|
|
115
116
|
/** Total duration in minutes. null when a timer is still running. */
|
|
116
117
|
duration_minutes: import_framework_utils4.model.number().nullable(),
|
|
117
118
|
description: import_framework_utils4.model.text().nullable(),
|
|
@@ -124,7 +125,9 @@ var TimeLog = import_framework_utils4.model.define("time_log", {
|
|
|
124
125
|
source: import_framework_utils4.model.enum(["manual", "timer"]).default("manual")
|
|
125
126
|
}, [
|
|
126
127
|
{ columns: ["issue_id"] },
|
|
127
|
-
{ columns: ["user_id"] }
|
|
128
|
+
{ columns: ["user_id"] },
|
|
129
|
+
{ columns: ["project_id"] },
|
|
130
|
+
{ columns: ["workspace_id"] }
|
|
128
131
|
]);
|
|
129
132
|
var time_log_default = TimeLog;
|
|
130
133
|
|
|
@@ -166,11 +169,11 @@ var IssueModuleService = class extends (0, import_framework_utils6.MeridianServi
|
|
|
166
169
|
if (!project) {
|
|
167
170
|
throw Object.assign(new Error(`Project ${input.project_id} not found`), { status: 404 });
|
|
168
171
|
}
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
0
|
|
172
|
+
const [highest] = await issueRepo.find(
|
|
173
|
+
{ project_id: input.project_id },
|
|
174
|
+
{ orderBy: { number: "DESC" }, limit: 1 }
|
|
173
175
|
);
|
|
176
|
+
const maxNumber = highest?.number ?? 0;
|
|
174
177
|
const nextNumber = maxNumber + 1;
|
|
175
178
|
const identifier = `${project.identifier}-${nextNumber}`;
|
|
176
179
|
const issue = issueRepo.create({
|
|
@@ -252,7 +255,7 @@ var IssueModuleService = class extends (0, import_framework_utils6.MeridianServi
|
|
|
252
255
|
* Start a timer for a user on an issue.
|
|
253
256
|
* Throws if the user already has an active timer on this issue.
|
|
254
257
|
*/
|
|
255
|
-
async startTimer(issueId, userId, workspaceId) {
|
|
258
|
+
async startTimer(issueId, userId, workspaceId, projectId) {
|
|
256
259
|
const repo = this.container.resolve("timeLogRepository");
|
|
257
260
|
const active = await repo.findOne({
|
|
258
261
|
issue_id: issueId,
|
|
@@ -270,6 +273,7 @@ var IssueModuleService = class extends (0, import_framework_utils6.MeridianServi
|
|
|
270
273
|
issue_id: issueId,
|
|
271
274
|
user_id: userId,
|
|
272
275
|
workspace_id: workspaceId,
|
|
276
|
+
project_id: projectId ?? null,
|
|
273
277
|
source: "timer",
|
|
274
278
|
started_at: /* @__PURE__ */ new Date()
|
|
275
279
|
});
|
|
@@ -313,6 +317,35 @@ var IssueModuleService = class extends (0, import_framework_utils6.MeridianServi
|
|
|
313
317
|
stopped_at: null
|
|
314
318
|
}) ?? null;
|
|
315
319
|
}
|
|
320
|
+
/** Query time logs for reporting — supports filtering by user, project, workspace, and date range.
|
|
321
|
+
* Each returned entry is enriched with `issue_identifier` and `issue_title`. */
|
|
322
|
+
async listTimeLogsForReporting(filters) {
|
|
323
|
+
const repo = this.container.resolve("timeLogRepository");
|
|
324
|
+
const issueRepo = this.container.resolve("issueRepository");
|
|
325
|
+
const where = {};
|
|
326
|
+
if (filters.user_id) where.user_id = filters.user_id;
|
|
327
|
+
if (filters.workspace_id) where.workspace_id = filters.workspace_id;
|
|
328
|
+
if (filters.logged_date) where.logged_date = filters.logged_date;
|
|
329
|
+
let issueCache = null;
|
|
330
|
+
if (filters.project_id) {
|
|
331
|
+
const issues = await issueRepo.find({ project_id: filters.project_id });
|
|
332
|
+
if (issues.length === 0) return [];
|
|
333
|
+
issueCache = new Map(issues.map((i) => [i.id, i]));
|
|
334
|
+
where.issue_id = { $in: [...issueCache.keys()] };
|
|
335
|
+
}
|
|
336
|
+
const logs = await repo.find(where, { orderBy: { logged_date: "DESC" } });
|
|
337
|
+
if (logs.length === 0) return [];
|
|
338
|
+
if (!issueCache) {
|
|
339
|
+
const uniqueIssueIds = [...new Set(logs.map((l) => l.issue_id))];
|
|
340
|
+
const issues = await issueRepo.find({ id: { $in: uniqueIssueIds } });
|
|
341
|
+
issueCache = new Map(issues.map((i) => [i.id, i]));
|
|
342
|
+
}
|
|
343
|
+
return logs.map((l) => ({
|
|
344
|
+
...l,
|
|
345
|
+
issue_identifier: issueCache.get(l.issue_id)?.identifier ?? null,
|
|
346
|
+
issue_title: issueCache.get(l.issue_id)?.title ?? null
|
|
347
|
+
}));
|
|
348
|
+
}
|
|
316
349
|
/** Delete a time log entry by ID. */
|
|
317
350
|
async deleteTimeLog(id) {
|
|
318
351
|
const repo = this.container.resolve("timeLogRepository");
|
package/dist/index.mjs
CHANGED
|
@@ -86,6 +86,7 @@ var TimeLog = model4.define("time_log", {
|
|
|
86
86
|
issue_id: model4.text(),
|
|
87
87
|
user_id: model4.text(),
|
|
88
88
|
workspace_id: model4.text(),
|
|
89
|
+
project_id: model4.text().nullable(),
|
|
89
90
|
/** Total duration in minutes. null when a timer is still running. */
|
|
90
91
|
duration_minutes: model4.number().nullable(),
|
|
91
92
|
description: model4.text().nullable(),
|
|
@@ -98,7 +99,9 @@ var TimeLog = model4.define("time_log", {
|
|
|
98
99
|
source: model4.enum(["manual", "timer"]).default("manual")
|
|
99
100
|
}, [
|
|
100
101
|
{ columns: ["issue_id"] },
|
|
101
|
-
{ columns: ["user_id"] }
|
|
102
|
+
{ columns: ["user_id"] },
|
|
103
|
+
{ columns: ["project_id"] },
|
|
104
|
+
{ columns: ["workspace_id"] }
|
|
102
105
|
]);
|
|
103
106
|
var time_log_default = TimeLog;
|
|
104
107
|
|
|
@@ -140,11 +143,11 @@ var IssueModuleService = class extends MeridianService({
|
|
|
140
143
|
if (!project) {
|
|
141
144
|
throw Object.assign(new Error(`Project ${input.project_id} not found`), { status: 404 });
|
|
142
145
|
}
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
0
|
|
146
|
+
const [highest] = await issueRepo.find(
|
|
147
|
+
{ project_id: input.project_id },
|
|
148
|
+
{ orderBy: { number: "DESC" }, limit: 1 }
|
|
147
149
|
);
|
|
150
|
+
const maxNumber = highest?.number ?? 0;
|
|
148
151
|
const nextNumber = maxNumber + 1;
|
|
149
152
|
const identifier = `${project.identifier}-${nextNumber}`;
|
|
150
153
|
const issue = issueRepo.create({
|
|
@@ -226,7 +229,7 @@ var IssueModuleService = class extends MeridianService({
|
|
|
226
229
|
* Start a timer for a user on an issue.
|
|
227
230
|
* Throws if the user already has an active timer on this issue.
|
|
228
231
|
*/
|
|
229
|
-
async startTimer(issueId, userId, workspaceId) {
|
|
232
|
+
async startTimer(issueId, userId, workspaceId, projectId) {
|
|
230
233
|
const repo = this.container.resolve("timeLogRepository");
|
|
231
234
|
const active = await repo.findOne({
|
|
232
235
|
issue_id: issueId,
|
|
@@ -244,6 +247,7 @@ var IssueModuleService = class extends MeridianService({
|
|
|
244
247
|
issue_id: issueId,
|
|
245
248
|
user_id: userId,
|
|
246
249
|
workspace_id: workspaceId,
|
|
250
|
+
project_id: projectId ?? null,
|
|
247
251
|
source: "timer",
|
|
248
252
|
started_at: /* @__PURE__ */ new Date()
|
|
249
253
|
});
|
|
@@ -287,6 +291,35 @@ var IssueModuleService = class extends MeridianService({
|
|
|
287
291
|
stopped_at: null
|
|
288
292
|
}) ?? null;
|
|
289
293
|
}
|
|
294
|
+
/** Query time logs for reporting — supports filtering by user, project, workspace, and date range.
|
|
295
|
+
* Each returned entry is enriched with `issue_identifier` and `issue_title`. */
|
|
296
|
+
async listTimeLogsForReporting(filters) {
|
|
297
|
+
const repo = this.container.resolve("timeLogRepository");
|
|
298
|
+
const issueRepo = this.container.resolve("issueRepository");
|
|
299
|
+
const where = {};
|
|
300
|
+
if (filters.user_id) where.user_id = filters.user_id;
|
|
301
|
+
if (filters.workspace_id) where.workspace_id = filters.workspace_id;
|
|
302
|
+
if (filters.logged_date) where.logged_date = filters.logged_date;
|
|
303
|
+
let issueCache = null;
|
|
304
|
+
if (filters.project_id) {
|
|
305
|
+
const issues = await issueRepo.find({ project_id: filters.project_id });
|
|
306
|
+
if (issues.length === 0) return [];
|
|
307
|
+
issueCache = new Map(issues.map((i) => [i.id, i]));
|
|
308
|
+
where.issue_id = { $in: [...issueCache.keys()] };
|
|
309
|
+
}
|
|
310
|
+
const logs = await repo.find(where, { orderBy: { logged_date: "DESC" } });
|
|
311
|
+
if (logs.length === 0) return [];
|
|
312
|
+
if (!issueCache) {
|
|
313
|
+
const uniqueIssueIds = [...new Set(logs.map((l) => l.issue_id))];
|
|
314
|
+
const issues = await issueRepo.find({ id: { $in: uniqueIssueIds } });
|
|
315
|
+
issueCache = new Map(issues.map((i) => [i.id, i]));
|
|
316
|
+
}
|
|
317
|
+
return logs.map((l) => ({
|
|
318
|
+
...l,
|
|
319
|
+
issue_identifier: issueCache.get(l.issue_id)?.identifier ?? null,
|
|
320
|
+
issue_title: issueCache.get(l.issue_id)?.title ?? null
|
|
321
|
+
}));
|
|
322
|
+
}
|
|
290
323
|
/** Delete a time log entry by ID. */
|
|
291
324
|
async deleteTimeLog(id) {
|
|
292
325
|
const repo = this.container.resolve("timeLogRepository");
|