@meridianjs/issue 0.1.3 → 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 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
 
@@ -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
 
@@ -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");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meridianjs/issue",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Meridian issue module — Issue and Comment domain models",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",