@meridianjs/meridian 1.23.0 → 1.25.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/dist/api/admin/issues/[id]/route.d.ts.map +1 -1
- package/dist/api/admin/issues/[id]/route.js +24 -0
- package/dist/api/admin/issues/[id]/route.js.map +1 -1
- package/dist/api/admin/issues/route.d.ts.map +1 -1
- package/dist/api/admin/issues/route.js +56 -6
- package/dist/api/admin/issues/route.js.map +1 -1
- package/dist/subscribers/_email-helper.d.ts +34 -0
- package/dist/subscribers/_email-helper.d.ts.map +1 -1
- package/dist/subscribers/_email-helper.js +145 -6
- package/dist/subscribers/_email-helper.js.map +1 -1
- package/dist/subscribers/comment-created.d.ts.map +1 -1
- package/dist/subscribers/comment-created.js +41 -18
- package/dist/subscribers/comment-created.js.map +1 -1
- package/dist/subscribers/issue-assigned.d.ts.map +1 -1
- package/dist/subscribers/issue-assigned.js +24 -3
- package/dist/subscribers/issue-assigned.js.map +1 -1
- package/dist/subscribers/issue-created.d.ts.map +1 -1
- package/dist/subscribers/issue-created.js +22 -6
- package/dist/subscribers/issue-created.js.map +1 -1
- package/dist/subscribers/issue-mentioned.d.ts +12 -0
- package/dist/subscribers/issue-mentioned.d.ts.map +1 -0
- package/dist/subscribers/issue-mentioned.js +89 -0
- package/dist/subscribers/issue-mentioned.js.map +1 -0
- package/dist/subscribers/project-member-added.d.ts.map +1 -1
- package/dist/subscribers/project-member-added.js +19 -3
- package/dist/subscribers/project-member-added.js.map +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/api/admin/issues/[id]/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAMrD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAYhD,CAAA;AAED,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/api/admin/issues/[id]/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAMrD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAYhD,CAAA;AAED,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBAqFpE,CAAA;AAED,eAAO,MAAM,MAAM,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBAUvE,CAAA"}
|
|
@@ -36,6 +36,25 @@ export const PUT = async (req, res, next) => {
|
|
|
36
36
|
updates.recurrence_end_date = updates.recurrence_end_date ? new Date(updates.recurrence_end_date) : null;
|
|
37
37
|
if (updates.next_occurrence_date !== undefined)
|
|
38
38
|
updates.next_occurrence_date = updates.next_occurrence_date ? new Date(updates.next_occurrence_date) : null;
|
|
39
|
+
// Extract mention IDs — not a model field, used only for notifications
|
|
40
|
+
const mentionedUserIds = Array.isArray(req.body.mentioned_user_ids)
|
|
41
|
+
? req.body.mentioned_user_ids.filter((id) => typeof id === "string")
|
|
42
|
+
: [];
|
|
43
|
+
const emitMentions = (issue) => {
|
|
44
|
+
if (mentionedUserIds.length > 0 && req.body.description !== undefined) {
|
|
45
|
+
const eventBus = req.scope.resolve("eventBus");
|
|
46
|
+
eventBus.emit({
|
|
47
|
+
name: "issue.mentioned",
|
|
48
|
+
data: {
|
|
49
|
+
issue_id: issue.id,
|
|
50
|
+
actor_id: req.user?.id ?? "system",
|
|
51
|
+
mentioned_user_ids: mentionedUserIds,
|
|
52
|
+
workspace_id: issue.workspace_id,
|
|
53
|
+
project_id: issue.project_id,
|
|
54
|
+
},
|
|
55
|
+
}).catch(() => { });
|
|
56
|
+
}
|
|
57
|
+
};
|
|
39
58
|
if (updates.status !== undefined) {
|
|
40
59
|
const { result: issue, errors, transaction_status } = await updateIssueStatusWorkflow(req.scope).run({
|
|
41
60
|
input: { issueId: req.params.id, status: updates.status, actor_id: req.user?.id ?? null },
|
|
@@ -47,10 +66,12 @@ export const PUT = async (req, res, next) => {
|
|
|
47
66
|
}
|
|
48
67
|
delete updates.status;
|
|
49
68
|
if (Object.keys(updates).length === 0) {
|
|
69
|
+
emitMentions(issue);
|
|
50
70
|
res.json({ issue });
|
|
51
71
|
return;
|
|
52
72
|
}
|
|
53
73
|
const finalIssue = await issueService.updateIssue(req.params.id, updates);
|
|
74
|
+
emitMentions(finalIssue);
|
|
54
75
|
res.json({ issue: finalIssue });
|
|
55
76
|
return;
|
|
56
77
|
}
|
|
@@ -65,15 +86,18 @@ export const PUT = async (req, res, next) => {
|
|
|
65
86
|
}
|
|
66
87
|
delete updates.assignee_ids;
|
|
67
88
|
if (Object.keys(updates).length === 0) {
|
|
89
|
+
emitMentions(issue);
|
|
68
90
|
res.json({ issue });
|
|
69
91
|
return;
|
|
70
92
|
}
|
|
71
93
|
const finalIssue = await issueService.updateIssue(req.params.id, updates);
|
|
94
|
+
emitMentions(finalIssue);
|
|
72
95
|
res.json({ issue: finalIssue });
|
|
73
96
|
return;
|
|
74
97
|
}
|
|
75
98
|
const currentIssue = await issueService.retrieveIssue(req.params.id);
|
|
76
99
|
const issue = await issueService.updateIssue(req.params.id, updates);
|
|
100
|
+
emitMentions(issue);
|
|
77
101
|
await activityService.recordActivity({
|
|
78
102
|
entity_type: "issue", entity_id: req.params.id,
|
|
79
103
|
actor_id: req.user?.id ?? "system", action: "updated", workspace_id: issue.workspace_id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../src/api/admin/issues/[id]/route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,8CAA8C,CAAA;AACxF,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAA;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAEnE,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,EAAE;IACnD,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAQ,CAAA;IACnE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAC7D,IAAI,KAAK,EAAE,UAAU,EAAE,CAAC;QACtB,MAAM,cAAc,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,sBAAsB,CAAQ,CAAA;QACvE,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,eAAe,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;QACxF,IAAI,OAAO,IAAI,CAAC,MAAM,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC;YACrD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC,CAAA;YACzD,OAAM;QACR,CAAC;IACH,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;AACrB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IACvE,iBAAiB,CAAC,cAAc,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE;QACrD,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAQ,CAAA;YACnE,MAAM,eAAe,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,uBAAuB,CAAQ,CAAA;YACzE,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM;gBACpD,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;gBAC1G,sBAAsB,EAAE,qBAAqB,EAAE,sBAAsB,CAAC,CAAA;YACvF,MAAM,OAAO,GAA4B,EAAE,CAAA;YAC3C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,SAAS;oBAAE,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACrE,CAAC;YACD,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS;gBAAE,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,UAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YAC7H,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS;gBAAE,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,QAAkB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YACrH,IAAI,OAAO,CAAC,mBAAmB,KAAK,SAAS;gBAAE,OAAO,CAAC,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,mBAA6B,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YACjK,IAAI,OAAO,CAAC,oBAAoB,KAAK,SAAS;gBAAE,OAAO,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,oBAA8B,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YAErK,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,yBAAyB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC;oBACnG,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAgB,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,IAAI,EAAE;iBACpG,CAAC,CAAA;gBACF,IAAI,kBAAkB,KAAK,UAAU,EAAE,CAAC;oBACtC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;oBACrB,GAAG,CAAC,MAAM,CAAE,GAAW,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;oBAChF,OAAM;gBACR,CAAC;gBACD,OAAO,OAAO,CAAC,MAAM,CAAA;gBACrB,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAAC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;oBAAC,OAAM;gBAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../src/api/admin/issues/[id]/route.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/admin/issues/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAKrD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/admin/issues/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAKrD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBA6EhD,CAAA;AAED,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBAoDrE,CAAA"}
|
|
@@ -27,6 +27,24 @@ export const GET = async (req, res) => {
|
|
|
27
27
|
filters.task_list_id = null;
|
|
28
28
|
else if (req.query.task_list_id)
|
|
29
29
|
filters.task_list_id = req.query.task_list_id;
|
|
30
|
+
// parent_id filter: "none" = top-level only, else filter by specific parent
|
|
31
|
+
if (req.query.parent_id === "none")
|
|
32
|
+
filters.parent_id = null;
|
|
33
|
+
else if (req.query.parent_id)
|
|
34
|
+
filters.parent_id = req.query.parent_id;
|
|
35
|
+
// assignee_id — filter using raw SQL on the jsonb column
|
|
36
|
+
if (req.query.assignee_id) {
|
|
37
|
+
const aid = req.query.assignee_id;
|
|
38
|
+
filters.assignee_ids = { $contains: aid };
|
|
39
|
+
}
|
|
40
|
+
// search — text search on title and identifier
|
|
41
|
+
if (req.query.search) {
|
|
42
|
+
const term = `%${req.query.search}%`;
|
|
43
|
+
filters.$or = [
|
|
44
|
+
{ title: { $ilike: term } },
|
|
45
|
+
{ identifier: { $ilike: term } },
|
|
46
|
+
];
|
|
47
|
+
}
|
|
30
48
|
// When scoped to a project, verify the caller has access to that project
|
|
31
49
|
if (req.query.project_id) {
|
|
32
50
|
const projectService = req.scope.resolve("projectModuleService");
|
|
@@ -40,18 +58,33 @@ export const GET = async (req, res) => {
|
|
|
40
58
|
return;
|
|
41
59
|
}
|
|
42
60
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
61
|
+
// sort_by + sort_order
|
|
62
|
+
const allowedSortColumns = ["created_at", "updated_at", "title", "priority", "due_date", "number"];
|
|
63
|
+
const sortBy = allowedSortColumns.includes(req.query.sort_by) ? req.query.sort_by : "created_at";
|
|
64
|
+
const sortOrder = req.query.sort_order === "desc" ? "DESC" : "ASC";
|
|
65
|
+
const [issues, count] = await issueService.listAndCountIssues(filters, { limit, offset, orderBy: { [sortBy]: sortOrder } });
|
|
66
|
+
// When fetching top-level issues, enrich with child_count so the UI
|
|
67
|
+
// knows which rows have expandable children without a separate request.
|
|
68
|
+
if (req.query.parent_id === "none" && issues.length > 0) {
|
|
69
|
+
const issueIds = issues.map((i) => i.id);
|
|
70
|
+
const [children] = await issueService.listAndCountIssues({ parent_id: { $in: issueIds } }, { limit: 10000 });
|
|
71
|
+
const childCountMap = {};
|
|
72
|
+
for (const child of children) {
|
|
73
|
+
const pid = child.parent_id;
|
|
74
|
+
if (pid)
|
|
75
|
+
childCountMap[pid] = (childCountMap[pid] ?? 0) + 1;
|
|
76
|
+
}
|
|
77
|
+
for (const issue of issues) {
|
|
78
|
+
;
|
|
79
|
+
issue.child_count = childCountMap[issue.id] ?? 0;
|
|
80
|
+
}
|
|
48
81
|
}
|
|
49
82
|
res.json({ issues, count, limit, offset });
|
|
50
83
|
};
|
|
51
84
|
export const POST = async (req, res, next) => {
|
|
52
85
|
requirePermission("issue:create")(req, res, async () => {
|
|
53
86
|
try {
|
|
54
|
-
const { title, project_id, workspace_id, description, type, priority, status, assignee_ids, reporter_id, parent_id, start_date, due_date, estimate, sprint_id, task_list_id, metadata, recurrence_frequency, recurrence_end_date } = req.body;
|
|
87
|
+
const { title, project_id, workspace_id, description, type, priority, status, assignee_ids, reporter_id, parent_id, start_date, due_date, estimate, sprint_id, task_list_id, metadata, recurrence_frequency, recurrence_end_date, mentioned_user_ids } = req.body;
|
|
55
88
|
if (!title || !project_id || !workspace_id) {
|
|
56
89
|
res.status(400).json({ error: { message: "title, project_id and workspace_id are required" } });
|
|
57
90
|
return;
|
|
@@ -76,6 +109,23 @@ export const POST = async (req, res, next) => {
|
|
|
76
109
|
res.status(err.status ?? 500).json({ error: { message: err.message } });
|
|
77
110
|
return;
|
|
78
111
|
}
|
|
112
|
+
// Emit mention notifications if description has @mentions
|
|
113
|
+
const validMentionIds = Array.isArray(mentioned_user_ids)
|
|
114
|
+
? mentioned_user_ids.filter((id) => typeof id === "string")
|
|
115
|
+
: [];
|
|
116
|
+
if (validMentionIds.length > 0 && description) {
|
|
117
|
+
const eventBus = req.scope.resolve("eventBus");
|
|
118
|
+
eventBus.emit({
|
|
119
|
+
name: "issue.mentioned",
|
|
120
|
+
data: {
|
|
121
|
+
issue_id: issue.id,
|
|
122
|
+
actor_id: req.user?.id ?? "system",
|
|
123
|
+
mentioned_user_ids: validMentionIds,
|
|
124
|
+
workspace_id: issue.workspace_id,
|
|
125
|
+
project_id: issue.project_id,
|
|
126
|
+
},
|
|
127
|
+
}).catch(() => { });
|
|
128
|
+
}
|
|
79
129
|
res.status(201).json({ issue });
|
|
80
130
|
}
|
|
81
131
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/admin/issues/route.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/admin/issues/route.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,38 @@
|
|
|
1
1
|
import type { EmailTemplateOverride } from "@meridianjs/types";
|
|
2
|
+
export interface EmailOptions {
|
|
3
|
+
/** Short preview text shown in inbox lists */
|
|
4
|
+
preheader?: string;
|
|
5
|
+
heading: string;
|
|
6
|
+
/** Main body — may contain <strong>, <em>, <br> */
|
|
7
|
+
body: string;
|
|
8
|
+
/** Optional quoted block (comment body, description, etc.) */
|
|
9
|
+
quote?: {
|
|
10
|
+
label: string;
|
|
11
|
+
html: string;
|
|
12
|
+
};
|
|
13
|
+
/** Optional pill metadata below the body */
|
|
14
|
+
meta?: Array<{
|
|
15
|
+
label: string;
|
|
16
|
+
value: string;
|
|
17
|
+
}>;
|
|
18
|
+
ctaText: string;
|
|
19
|
+
ctaUrl: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function buildEmail(opts: EmailOptions): string;
|
|
22
|
+
/**
|
|
23
|
+
* Prepare Tiptap-generated HTML for use inside an email quote block.
|
|
24
|
+
* Converts @mention spans to styled text and strips unsafe/unknown tags.
|
|
25
|
+
*/
|
|
26
|
+
export declare function htmlToEmailSafe(html: string): string;
|
|
27
|
+
/** Derive a human-readable display name from a user object */
|
|
28
|
+
export declare function userDisplayName(user: any): string;
|
|
29
|
+
/** Title-case a snake_case string — e.g. "no_priority" → "No Priority" */
|
|
30
|
+
export declare function capitalize(str: string): string;
|
|
31
|
+
/** Build a deep link to an issue, with graceful fallback */
|
|
32
|
+
export declare function buildIssueUrl(container: any, appUrl: string, issue: any): Promise<string>;
|
|
33
|
+
/** Build a deep link to a project */
|
|
34
|
+
export declare function buildProjectUrl(container: any, appUrl: string, projectId: string, workspaceId: string): Promise<string>;
|
|
35
|
+
/** @deprecated Use buildEmail() for new subscribers */
|
|
2
36
|
export declare function emailHtml(message: string): string;
|
|
3
37
|
export declare function resolveTemplate(container: any, event: string, data: unknown): EmailTemplateOverride | null;
|
|
4
38
|
//# sourceMappingURL=_email-helper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_email-helper.d.ts","sourceRoot":"","sources":["../../src/subscribers/_email-helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAyB,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"_email-helper.d.ts","sourceRoot":"","sources":["../../src/subscribers/_email-helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAyB,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAIrF,MAAM,WAAW,YAAY;IAC3B,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,8DAA8D;IAC9D,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,4CAA4C;IAC5C,IAAI,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC9C,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAiFrD;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAapD;AAED,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAGjD;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG9C;AAED,4DAA4D;AAC5D,wBAAsB,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAa/F;AAED,qCAAqC;AACrC,wBAAsB,eAAe,CACnC,SAAS,EAAE,GAAG,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAajB;AAID,uDAAuD;AACvD,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED,wBAAgB,eAAe,CAC7B,SAAS,EAAE,GAAG,EACd,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,OAAO,GACZ,qBAAqB,GAAG,IAAI,CAO9B"}
|
|
@@ -1,9 +1,148 @@
|
|
|
1
|
+
export function buildEmail(opts) {
|
|
2
|
+
const { preheader, heading, body, quote, meta, ctaText, ctaUrl } = opts;
|
|
3
|
+
const metaHtml = meta && meta.length > 0
|
|
4
|
+
? `<table cellpadding="0" cellspacing="0" border="0" role="presentation" style="margin:16px 0 4px;">
|
|
5
|
+
<tr>
|
|
6
|
+
${meta.map(m => `<td style="padding:0 8px 0 0;">
|
|
7
|
+
<span style="display:inline-block;padding:4px 10px;background:#f3f4f6;border-radius:5px;font-size:12px;color:#374151;white-space:nowrap;">
|
|
8
|
+
<span style="color:#9ca3af;">${m.label}:</span> ${m.value}
|
|
9
|
+
</span>
|
|
10
|
+
</td>`).join("")}
|
|
11
|
+
</tr>
|
|
12
|
+
</table>`
|
|
13
|
+
: "";
|
|
14
|
+
const quoteHtml = quote
|
|
15
|
+
? `<div style="margin:20px 0;border-left:3px solid #4f46e5;border-radius:0 6px 6px 0;background:#f8fafc;padding:14px 16px;">
|
|
16
|
+
<p style="margin:0 0 8px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:#6b7280;">${quote.label}</p>
|
|
17
|
+
<div style="font-size:14px;color:#374151;line-height:1.65;">${quote.html}</div>
|
|
18
|
+
</div>`
|
|
19
|
+
: "";
|
|
20
|
+
const btnMarginTop = quote || meta ? "8px" : "24px";
|
|
21
|
+
return `<!DOCTYPE html>
|
|
22
|
+
<html lang="en">
|
|
23
|
+
<head>
|
|
24
|
+
<meta charset="UTF-8">
|
|
25
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
26
|
+
<meta name="color-scheme" content="light">
|
|
27
|
+
<title>${heading}</title>
|
|
28
|
+
</head>
|
|
29
|
+
<body style="margin:0;padding:0;background-color:#f3f4f6;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;">
|
|
30
|
+
${preheader ? `<div style="display:none;font-size:1px;color:#f3f4f6;line-height:1px;max-height:0;max-width:0;opacity:0;overflow:hidden;">${preheader} ‌ ‌ ‌ ‌</div>` : ""}
|
|
31
|
+
<table width="100%" cellpadding="0" cellspacing="0" border="0" role="presentation">
|
|
32
|
+
<tr>
|
|
33
|
+
<td align="center" style="padding:40px 16px;">
|
|
34
|
+
<table width="600" cellpadding="0" cellspacing="0" border="0" role="presentation" style="max-width:600px;width:100%;">
|
|
35
|
+
|
|
36
|
+
<!-- Brand bar -->
|
|
37
|
+
<tr>
|
|
38
|
+
<td style="background:#4f46e5;border-radius:12px 12px 0 0;padding:18px 28px;">
|
|
39
|
+
<span style="font-size:15px;font-weight:700;color:#ffffff;letter-spacing:-0.2px;">◆ Meridian</span>
|
|
40
|
+
</td>
|
|
41
|
+
</tr>
|
|
42
|
+
|
|
43
|
+
<!-- Main content -->
|
|
44
|
+
<tr>
|
|
45
|
+
<td style="background:#ffffff;padding:32px 32px 28px;">
|
|
46
|
+
<h1 style="margin:0 0 10px;font-size:21px;font-weight:700;color:#111827;line-height:1.3;letter-spacing:-0.4px;">${heading}</h1>
|
|
47
|
+
<p style="margin:0;font-size:15px;color:#374151;line-height:1.65;">${body}</p>
|
|
48
|
+
${metaHtml}
|
|
49
|
+
${quoteHtml}
|
|
50
|
+
<table cellpadding="0" cellspacing="0" border="0" role="presentation" style="margin-top:${btnMarginTop};">
|
|
51
|
+
<tr>
|
|
52
|
+
<td style="background:#4f46e5;border-radius:8px;" align="center">
|
|
53
|
+
<a href="${ctaUrl}" target="_blank" rel="noopener noreferrer"
|
|
54
|
+
style="display:inline-block;padding:11px 22px;color:#ffffff;font-size:14px;font-weight:600;text-decoration:none;letter-spacing:-0.1px;white-space:nowrap;">${ctaText} →</a>
|
|
55
|
+
</td>
|
|
56
|
+
</tr>
|
|
57
|
+
</table>
|
|
58
|
+
</td>
|
|
59
|
+
</tr>
|
|
60
|
+
|
|
61
|
+
<!-- Footer -->
|
|
62
|
+
<tr>
|
|
63
|
+
<td style="background:#f9fafb;border:1px solid #f3f4f6;border-top:none;border-radius:0 0 12px 12px;padding:16px 32px;">
|
|
64
|
+
<p style="margin:0;font-size:12px;color:#9ca3af;line-height:1.5;">
|
|
65
|
+
Sent by <strong style="color:#6b7280;">Meridian</strong> · You received this because you're a member of this workspace.
|
|
66
|
+
</p>
|
|
67
|
+
</td>
|
|
68
|
+
</tr>
|
|
69
|
+
|
|
70
|
+
</table>
|
|
71
|
+
</td>
|
|
72
|
+
</tr>
|
|
73
|
+
</table>
|
|
74
|
+
</body>
|
|
75
|
+
</html>`;
|
|
76
|
+
}
|
|
77
|
+
// ── Content helpers ───────────────────────────────────────────────────────────
|
|
78
|
+
/**
|
|
79
|
+
* Prepare Tiptap-generated HTML for use inside an email quote block.
|
|
80
|
+
* Converts @mention spans to styled text and strips unsafe/unknown tags.
|
|
81
|
+
*/
|
|
82
|
+
export function htmlToEmailSafe(html) {
|
|
83
|
+
if (!html)
|
|
84
|
+
return "";
|
|
85
|
+
return html
|
|
86
|
+
// Mentions → @Name in indigo bold
|
|
87
|
+
.replace(/<span[^>]*data-type="mention"[^>]*data-label="([^"]*)"[^>]*>[\s\S]*?<\/span>/g, '<strong style="color:#4f46e5;">@$1</strong>')
|
|
88
|
+
// Strip attributes from known safe block/inline tags
|
|
89
|
+
.replace(/<(\/?(p|ul|ol|li|blockquote|h[1-6]|pre|code|strong|b|em|i|u|s|strike|br))\s[^>]*>/gi, "<$1>")
|
|
90
|
+
// Remove all unknown tags (keep their text content)
|
|
91
|
+
.replace(/<(?!\/?(?:p|ul|ol|li|blockquote|h[1-6]|pre|code|strong|b|em|i|u|s|strike|br)\b)[^>]+>/gi, "")
|
|
92
|
+
.trim();
|
|
93
|
+
}
|
|
94
|
+
/** Derive a human-readable display name from a user object */
|
|
95
|
+
export function userDisplayName(user) {
|
|
96
|
+
const name = `${user?.first_name ?? ""} ${user?.last_name ?? ""}`.trim();
|
|
97
|
+
return name || user?.email || "Someone";
|
|
98
|
+
}
|
|
99
|
+
/** Title-case a snake_case string — e.g. "no_priority" → "No Priority" */
|
|
100
|
+
export function capitalize(str) {
|
|
101
|
+
if (!str)
|
|
102
|
+
return "";
|
|
103
|
+
return str.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
104
|
+
}
|
|
105
|
+
/** Build a deep link to an issue, with graceful fallback */
|
|
106
|
+
export async function buildIssueUrl(container, appUrl, issue) {
|
|
107
|
+
try {
|
|
108
|
+
const projectService = container.resolve("projectModuleService");
|
|
109
|
+
const workspaceService = container.resolve("workspaceModuleService");
|
|
110
|
+
const [project, workspace] = await Promise.all([
|
|
111
|
+
projectService.retrieveProject(issue.project_id),
|
|
112
|
+
workspaceService.retrieveWorkspace(issue.workspace_id),
|
|
113
|
+
]);
|
|
114
|
+
if (project?.identifier && workspace?.slug) {
|
|
115
|
+
return `${appUrl}/${workspace.slug}/projects/${project.identifier}/issues/${issue.id}`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch { /* fall through */ }
|
|
119
|
+
return `${appUrl}/issues/${issue.id}`;
|
|
120
|
+
}
|
|
121
|
+
/** Build a deep link to a project */
|
|
122
|
+
export async function buildProjectUrl(container, appUrl, projectId, workspaceId) {
|
|
123
|
+
try {
|
|
124
|
+
const projectService = container.resolve("projectModuleService");
|
|
125
|
+
const workspaceService = container.resolve("workspaceModuleService");
|
|
126
|
+
const [project, workspace] = await Promise.all([
|
|
127
|
+
projectService.retrieveProject(projectId),
|
|
128
|
+
workspaceService.retrieveWorkspace(workspaceId),
|
|
129
|
+
]);
|
|
130
|
+
if (project?.identifier && workspace?.slug) {
|
|
131
|
+
return `${appUrl}/${workspace.slug}/projects/${project.identifier}`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch { /* fall through */ }
|
|
135
|
+
return `${appUrl}/projects/${projectId}`;
|
|
136
|
+
}
|
|
137
|
+
// ── Legacy shim ───────────────────────────────────────────────────────────────
|
|
138
|
+
/** @deprecated Use buildEmail() for new subscribers */
|
|
1
139
|
export function emailHtml(message) {
|
|
2
|
-
return
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
140
|
+
return buildEmail({
|
|
141
|
+
heading: "Meridian Notification",
|
|
142
|
+
body: message,
|
|
143
|
+
ctaText: "Open Meridian",
|
|
144
|
+
ctaUrl: process.env.APP_URL ?? "http://localhost:9001",
|
|
145
|
+
});
|
|
7
146
|
}
|
|
8
147
|
export function resolveTemplate(container, event, data) {
|
|
9
148
|
try {
|
|
@@ -11,7 +150,7 @@ export function resolveTemplate(container, event, data) {
|
|
|
11
150
|
return svc.render(event, data) ?? null;
|
|
12
151
|
}
|
|
13
152
|
catch {
|
|
14
|
-
return null;
|
|
153
|
+
return null;
|
|
15
154
|
}
|
|
16
155
|
}
|
|
17
156
|
//# sourceMappingURL=_email-helper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_email-helper.js","sourceRoot":"","sources":["../../src/subscribers/_email-helper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"_email-helper.js","sourceRoot":"","sources":["../../src/subscribers/_email-helper.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comment-created.d.ts","sourceRoot":"","sources":["../../src/subscribers/comment-created.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC9B;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"comment-created.d.ts","sourceRoot":"","sources":["../../src/subscribers/comment-created.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC9B;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAgJ7G;AAED,eAAO,MAAM,MAAM,EAAE,gBAA+C,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sseManager } from "@meridianjs/framework";
|
|
2
|
-
import {
|
|
2
|
+
import { buildEmail, buildIssueUrl, htmlToEmailSafe, capitalize, userDisplayName, resolveTemplate } from "./_email-helper.js";
|
|
3
3
|
export default async function handler({ event, container }) {
|
|
4
4
|
const data = event.data;
|
|
5
5
|
const issueService = container.resolve("issueModuleService");
|
|
@@ -66,17 +66,29 @@ export default async function handler({ event, container }) {
|
|
|
66
66
|
const userService = container.resolve("userModuleService");
|
|
67
67
|
const config = container.resolve("config");
|
|
68
68
|
const appUrl = config?.appUrl ?? process.env.APP_URL ?? "http://localhost:9001";
|
|
69
|
-
const
|
|
70
|
-
// Fetch comment body
|
|
71
|
-
let
|
|
72
|
-
let
|
|
69
|
+
const issueUrl = await buildIssueUrl(container, appUrl, issue);
|
|
70
|
+
// Fetch comment body + author name
|
|
71
|
+
let commentSafeHtml = "";
|
|
72
|
+
let commentPlainText = "";
|
|
73
|
+
let authorName = "Someone";
|
|
73
74
|
try {
|
|
74
75
|
const comment = await issueService.retrieveComment(data.comment_id);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
commentBodyText = commentBody.replace(/<[^>]+>/g, "").trim();
|
|
76
|
+
commentSafeHtml = comment?.body ? htmlToEmailSafe(comment.body) : "";
|
|
77
|
+
commentPlainText = comment?.body?.replace(/<[^>]+>/g, "").trim() ?? "";
|
|
78
78
|
}
|
|
79
|
-
catch { /* comment fetch optional
|
|
79
|
+
catch { /* comment fetch optional */ }
|
|
80
|
+
try {
|
|
81
|
+
const author = await userService.retrieveUser(data.author_id);
|
|
82
|
+
authorName = userDisplayName(author);
|
|
83
|
+
}
|
|
84
|
+
catch { /* fallback */ }
|
|
85
|
+
const meta = [
|
|
86
|
+
...(issue.priority ? [{ label: "Priority", value: capitalize(issue.priority) }] : []),
|
|
87
|
+
...(issue.type ? [{ label: "Type", value: capitalize(issue.type) }] : []),
|
|
88
|
+
];
|
|
89
|
+
const commentQuote = commentSafeHtml
|
|
90
|
+
? { label: `Comment by ${authorName}`, html: commentSafeHtml }
|
|
91
|
+
: undefined;
|
|
80
92
|
// Email existing recipients (assignees / reporter)
|
|
81
93
|
await Promise.allSettled([...recipients].map(async (userId) => {
|
|
82
94
|
const user = await userService.retrieveUser(userId);
|
|
@@ -86,9 +98,16 @@ export default async function handler({ event, container }) {
|
|
|
86
98
|
await emailService.send({
|
|
87
99
|
to: user.email,
|
|
88
100
|
subject: tpl?.subject ?? `New comment on [${issue.identifier}]: ${issue.title}`,
|
|
89
|
-
text: tpl?.text ??
|
|
90
|
-
html: tpl?.html ??
|
|
91
|
-
|
|
101
|
+
text: tpl?.text ?? `${authorName} left a comment on ${issue.identifier}: "${issue.title}".\n\n${commentPlainText}\n\nView it here: ${issueUrl}`,
|
|
102
|
+
html: tpl?.html ?? buildEmail({
|
|
103
|
+
preheader: `${authorName} commented on ${issue.identifier}: ${issue.title}`,
|
|
104
|
+
heading: `New comment on ${issue.identifier}`,
|
|
105
|
+
body: `<strong>${authorName}</strong> left a comment on: <em>${issue.title}</em>`,
|
|
106
|
+
meta,
|
|
107
|
+
quote: commentQuote,
|
|
108
|
+
ctaText: "View Issue",
|
|
109
|
+
ctaUrl: issueUrl,
|
|
110
|
+
}),
|
|
92
111
|
});
|
|
93
112
|
}));
|
|
94
113
|
// Email mentioned users
|
|
@@ -99,12 +118,16 @@ export default async function handler({ event, container }) {
|
|
|
99
118
|
await emailService.send({
|
|
100
119
|
to: user.email,
|
|
101
120
|
subject: `You were mentioned in [${issue.identifier}]: ${issue.title}`,
|
|
102
|
-
text:
|
|
103
|
-
html:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
121
|
+
text: `${authorName} mentioned you in a comment on ${issue.identifier}: "${issue.title}".\n\n${commentPlainText}\n\nView it here: ${issueUrl}`,
|
|
122
|
+
html: buildEmail({
|
|
123
|
+
preheader: `${authorName} mentioned you in ${issue.identifier}: ${issue.title}`,
|
|
124
|
+
heading: `You were mentioned in ${issue.identifier}`,
|
|
125
|
+
body: `<strong>${authorName}</strong> mentioned you in a comment on: <em>${issue.title}</em>`,
|
|
126
|
+
meta,
|
|
127
|
+
quote: commentQuote,
|
|
128
|
+
ctaText: "View Comment",
|
|
129
|
+
ctaUrl: issueUrl,
|
|
130
|
+
}),
|
|
108
131
|
});
|
|
109
132
|
}));
|
|
110
133
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comment-created.js","sourceRoot":"","sources":["../../src/subscribers/comment-created.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"comment-created.js","sourceRoot":"","sources":["../../src/subscribers/comment-created.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue-assigned.d.ts","sourceRoot":"","sources":["../../src/subscribers/issue-assigned.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"issue-assigned.d.ts","sourceRoot":"","sources":["../../src/subscribers/issue-assigned.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAsF5G;AAED,eAAO,MAAM,MAAM,EAAE,gBAA8C,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sseManager } from "@meridianjs/framework";
|
|
2
|
-
import {
|
|
2
|
+
import { buildEmail, buildIssueUrl, capitalize, userDisplayName, resolveTemplate } from "./_email-helper.js";
|
|
3
3
|
export default async function handler({ event, container }) {
|
|
4
4
|
const data = event.data;
|
|
5
5
|
if (!data.assignee_ids?.length)
|
|
@@ -35,7 +35,21 @@ export default async function handler({ event, container }) {
|
|
|
35
35
|
const emailService = container.resolve("emailService");
|
|
36
36
|
const userService = container.resolve("userModuleService");
|
|
37
37
|
const issueService = container.resolve("issueModuleService");
|
|
38
|
+
const config = container.resolve("config");
|
|
39
|
+
const appUrl = config?.appUrl ?? process.env.APP_URL ?? "http://localhost:9001";
|
|
38
40
|
const issue = await issueService.retrieveIssue(data.issue_id);
|
|
41
|
+
const issueUrl = await buildIssueUrl(container, appUrl, issue);
|
|
42
|
+
// Fetch actor name (who did the assignment)
|
|
43
|
+
let actorName = "A team member";
|
|
44
|
+
try {
|
|
45
|
+
const actor = await userService.retrieveUser(data.actor_id);
|
|
46
|
+
actorName = userDisplayName(actor);
|
|
47
|
+
}
|
|
48
|
+
catch { /* fallback */ }
|
|
49
|
+
const meta = [
|
|
50
|
+
...(issue.priority ? [{ label: "Priority", value: capitalize(issue.priority) }] : []),
|
|
51
|
+
...(issue.type ? [{ label: "Type", value: capitalize(issue.type) }] : []),
|
|
52
|
+
];
|
|
39
53
|
await Promise.allSettled(data.assignee_ids
|
|
40
54
|
.filter(id => id !== data.actor_id)
|
|
41
55
|
.map(async (userId) => {
|
|
@@ -46,8 +60,15 @@ export default async function handler({ event, container }) {
|
|
|
46
60
|
await emailService.send({
|
|
47
61
|
to: user.email,
|
|
48
62
|
subject: tpl?.subject ?? `[${issue.identifier}] You've been assigned: ${issue.title}`,
|
|
49
|
-
text: tpl?.text ??
|
|
50
|
-
html: tpl?.html ??
|
|
63
|
+
text: tpl?.text ?? `${actorName} assigned you to issue ${issue.identifier}: "${issue.title}".\n\nView it here: ${issueUrl}`,
|
|
64
|
+
html: tpl?.html ?? buildEmail({
|
|
65
|
+
preheader: `${actorName} assigned you to ${issue.identifier}: ${issue.title}`,
|
|
66
|
+
heading: `You've been assigned to ${issue.identifier}`,
|
|
67
|
+
body: `<strong>${actorName}</strong> assigned you to: <em>${issue.title}</em>`,
|
|
68
|
+
meta,
|
|
69
|
+
ctaText: "View Issue",
|
|
70
|
+
ctaUrl: issueUrl,
|
|
71
|
+
}),
|
|
51
72
|
});
|
|
52
73
|
}));
|
|
53
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue-assigned.js","sourceRoot":"","sources":["../../src/subscribers/issue-assigned.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"issue-assigned.js","sourceRoot":"","sources":["../../src/subscribers/issue-assigned.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue-created.d.ts","sourceRoot":"","sources":["../../src/subscribers/issue-created.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"issue-created.d.ts","sourceRoot":"","sources":["../../src/subscribers/issue-created.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAmF3G;AAED,eAAO,MAAM,MAAM,EAAE,gBAA6C,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sseManager } from "@meridianjs/framework";
|
|
2
|
-
import {
|
|
2
|
+
import { buildEmail, buildIssueUrl, capitalize, resolveTemplate } from "./_email-helper.js";
|
|
3
3
|
export default async function handler({ event, container }) {
|
|
4
4
|
const notifService = container.resolve("notificationModuleService");
|
|
5
5
|
const userService = container.resolve("userModuleService");
|
|
@@ -37,12 +37,19 @@ export default async function handler({ event, container }) {
|
|
|
37
37
|
const emailService = container.resolve("emailService");
|
|
38
38
|
const userService = container.resolve("userModuleService");
|
|
39
39
|
const issueService = container.resolve("issueModuleService");
|
|
40
|
+
const config = container.resolve("config");
|
|
41
|
+
const appUrl = config?.appUrl ?? process.env.APP_URL ?? "http://localhost:9001";
|
|
40
42
|
const issue = await issueService.retrieveIssue(data.issue_id);
|
|
43
|
+
const issueUrl = await buildIssueUrl(container, appUrl, issue);
|
|
41
44
|
const recipientIds = new Set();
|
|
42
45
|
if (data.assignee_ids)
|
|
43
46
|
data.assignee_ids.forEach(id => recipientIds.add(id));
|
|
44
47
|
if (data.reporter_id && data.reporter_id !== data.actor_id)
|
|
45
48
|
recipientIds.add(data.reporter_id);
|
|
49
|
+
const meta = [
|
|
50
|
+
...(issue.priority ? [{ label: "Priority", value: capitalize(issue.priority) }] : []),
|
|
51
|
+
...(issue.type ? [{ label: "Type", value: capitalize(issue.type) }] : []),
|
|
52
|
+
];
|
|
46
53
|
await Promise.allSettled([...recipientIds].map(async (userId) => {
|
|
47
54
|
const user = await userService.retrieveUser(userId);
|
|
48
55
|
if (!user?.email)
|
|
@@ -53,11 +60,20 @@ export default async function handler({ event, container }) {
|
|
|
53
60
|
to: user.email,
|
|
54
61
|
subject: tpl?.subject ?? `New issue: [${issue.identifier}] ${issue.title}`,
|
|
55
62
|
text: tpl?.text ?? (isAssignee
|
|
56
|
-
? `You've been assigned to new issue ${issue.identifier}: "${issue.title}"
|
|
57
|
-
: `A new issue ${issue.identifier} was created: "${issue.title}"
|
|
58
|
-
html: tpl?.html ??
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
? `You've been assigned to new issue ${issue.identifier}: "${issue.title}".\n\nView it here: ${issueUrl}`
|
|
64
|
+
: `A new issue ${issue.identifier} was created: "${issue.title}".\n\nView it here: ${issueUrl}`),
|
|
65
|
+
html: tpl?.html ?? buildEmail({
|
|
66
|
+
preheader: isAssignee
|
|
67
|
+
? `You've been assigned to ${issue.identifier}: ${issue.title}`
|
|
68
|
+
: `New issue ${issue.identifier}: ${issue.title}`,
|
|
69
|
+
heading: isAssignee ? `You've been assigned to ${issue.identifier}` : `New issue: ${issue.identifier}`,
|
|
70
|
+
body: isAssignee
|
|
71
|
+
? `You've been assigned to: <em>${issue.title}</em>`
|
|
72
|
+
: `A new issue was created: <em>${issue.title}</em>`,
|
|
73
|
+
meta,
|
|
74
|
+
ctaText: "View Issue",
|
|
75
|
+
ctaUrl: issueUrl,
|
|
76
|
+
}),
|
|
61
77
|
});
|
|
62
78
|
}));
|
|
63
79
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue-created.js","sourceRoot":"","sources":["../../src/subscribers/issue-created.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"issue-created.js","sourceRoot":"","sources":["../../src/subscribers/issue-created.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SubscriberArgs, SubscriberConfig } from "@meridianjs/types";
|
|
2
|
+
interface IssueMentionedData {
|
|
3
|
+
issue_id: string;
|
|
4
|
+
actor_id: string;
|
|
5
|
+
mentioned_user_ids: string[];
|
|
6
|
+
workspace_id: string;
|
|
7
|
+
project_id: string;
|
|
8
|
+
}
|
|
9
|
+
export default function handler({ event, container }: SubscriberArgs<IssueMentionedData>): Promise<void>;
|
|
10
|
+
export declare const config: SubscriberConfig;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=issue-mentioned.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-mentioned.d.ts","sourceRoot":"","sources":["../../src/subscribers/issue-mentioned.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,kBAAkB,EAAE,MAAM,EAAE,CAAA;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA+F7G;AAED,eAAO,MAAM,MAAM,EAAE,gBAA+C,CAAA"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { sseManager } from "@meridianjs/framework";
|
|
2
|
+
import { buildEmail, buildIssueUrl, htmlToEmailSafe, capitalize, userDisplayName } from "./_email-helper.js";
|
|
3
|
+
export default async function handler({ event, container }) {
|
|
4
|
+
const data = event.data;
|
|
5
|
+
if (!data.mentioned_user_ids?.length)
|
|
6
|
+
return;
|
|
7
|
+
const issueService = container.resolve("issueModuleService");
|
|
8
|
+
const notifService = container.resolve("notificationModuleService");
|
|
9
|
+
const userService = container.resolve("userModuleService");
|
|
10
|
+
let issue;
|
|
11
|
+
try {
|
|
12
|
+
issue = await issueService.retrieveIssue(data.issue_id);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
// Filter out the actor and deactivated users
|
|
18
|
+
const candidates = data.mentioned_user_ids.filter((id) => id !== data.actor_id);
|
|
19
|
+
if (candidates.length === 0)
|
|
20
|
+
return;
|
|
21
|
+
const activeUserMap = await userService.listUsersByIds(candidates);
|
|
22
|
+
const validMentions = candidates.filter((id) => activeUserMap.has(id));
|
|
23
|
+
if (validMentions.length === 0)
|
|
24
|
+
return;
|
|
25
|
+
try {
|
|
26
|
+
await Promise.all(validMentions.map((userId) => notifService.createNotification({
|
|
27
|
+
user_id: userId,
|
|
28
|
+
entity_type: "issue",
|
|
29
|
+
entity_id: data.issue_id,
|
|
30
|
+
action: "mentioned",
|
|
31
|
+
message: `You were mentioned in the description of [${issue.identifier}]: ${issue.title}`,
|
|
32
|
+
workspace_id: issue.workspace_id,
|
|
33
|
+
metadata: { project_id: issue.project_id },
|
|
34
|
+
})));
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
const logger = container.resolve("logger");
|
|
38
|
+
logger.error(`[notification] issue.mentioned: ${err instanceof Error ? err.message : String(err)}`);
|
|
39
|
+
}
|
|
40
|
+
sseManager.broadcast(issue.workspace_id, "notification.created", {});
|
|
41
|
+
// ── Email ──────────────────────────────────────────────────────────────────
|
|
42
|
+
try {
|
|
43
|
+
const emailService = container.resolve("emailService");
|
|
44
|
+
const config = container.resolve("config");
|
|
45
|
+
const appUrl = config?.appUrl ?? process.env.APP_URL ?? "http://localhost:9001";
|
|
46
|
+
const issueUrl = await buildIssueUrl(container, appUrl, issue);
|
|
47
|
+
// Fetch actor name (who mentioned them) and sanitize description
|
|
48
|
+
let actorName = "Someone";
|
|
49
|
+
try {
|
|
50
|
+
const actor = await userService.retrieveUser(data.actor_id);
|
|
51
|
+
actorName = userDisplayName(actor);
|
|
52
|
+
}
|
|
53
|
+
catch { /* fallback */ }
|
|
54
|
+
const descSafeHtml = issue.description ? htmlToEmailSafe(issue.description) : "";
|
|
55
|
+
const descPlainText = issue.description?.replace(/<[^>]+>/g, "").trim() ?? "";
|
|
56
|
+
const meta = [
|
|
57
|
+
...(issue.priority ? [{ label: "Priority", value: capitalize(issue.priority) }] : []),
|
|
58
|
+
...(issue.type ? [{ label: "Type", value: capitalize(issue.type) }] : []),
|
|
59
|
+
];
|
|
60
|
+
const descQuote = descSafeHtml
|
|
61
|
+
? { label: `Description of ${issue.identifier}`, html: descSafeHtml }
|
|
62
|
+
: undefined;
|
|
63
|
+
await Promise.allSettled(validMentions.map(async (userId) => {
|
|
64
|
+
const user = await userService.retrieveUser(userId);
|
|
65
|
+
if (!user?.email)
|
|
66
|
+
return;
|
|
67
|
+
await emailService.send({
|
|
68
|
+
to: user.email,
|
|
69
|
+
subject: `You were mentioned in [${issue.identifier}]: ${issue.title}`,
|
|
70
|
+
text: `${actorName} mentioned you in the description of ${issue.identifier}: "${issue.title}".\n\n${descPlainText}\n\nView it here: ${issueUrl}`,
|
|
71
|
+
html: buildEmail({
|
|
72
|
+
preheader: `${actorName} mentioned you in ${issue.identifier}: ${issue.title}`,
|
|
73
|
+
heading: `You were mentioned in ${issue.identifier}`,
|
|
74
|
+
body: `<strong>${actorName}</strong> mentioned you in the description of: <em>${issue.title}</em>`,
|
|
75
|
+
meta,
|
|
76
|
+
quote: descQuote,
|
|
77
|
+
ctaText: "View Issue",
|
|
78
|
+
ctaUrl: issueUrl,
|
|
79
|
+
}),
|
|
80
|
+
});
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
const logger = container.resolve("logger");
|
|
85
|
+
logger.error(`[email] issue.mentioned: ${err instanceof Error ? err.message : String(err)}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export const config = { event: "issue.mentioned" };
|
|
89
|
+
//# sourceMappingURL=issue-mentioned.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-mentioned.js","sourceRoot":"","sources":["../../src/subscribers/issue-mentioned.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-member-added.d.ts","sourceRoot":"","sources":["../../src/subscribers/project-member-added.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,sBAAsB;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,sBAAsB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"project-member-added.d.ts","sourceRoot":"","sources":["../../src/subscribers/project-member-added.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,sBAAsB;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,sBAAsB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAoEjH;AAED,eAAO,MAAM,MAAM,EAAE,gBAAoD,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sseManager } from "@meridianjs/framework";
|
|
2
|
-
import {
|
|
2
|
+
import { buildEmail, buildProjectUrl, userDisplayName, resolveTemplate } from "./_email-helper.js";
|
|
3
3
|
export default async function handler({ event, container }) {
|
|
4
4
|
const data = event.data;
|
|
5
5
|
if (!data.user_id || data.user_id === data.actor_id)
|
|
@@ -34,14 +34,30 @@ export default async function handler({ event, container }) {
|
|
|
34
34
|
try {
|
|
35
35
|
const emailService = container.resolve("emailService");
|
|
36
36
|
const userService = container.resolve("userModuleService");
|
|
37
|
+
const config = container.resolve("config");
|
|
38
|
+
const appUrl = config?.appUrl ?? process.env.APP_URL ?? "http://localhost:9001";
|
|
39
|
+
const projectUrl = await buildProjectUrl(container, appUrl, data.project_id, data.workspace_id);
|
|
40
|
+
// Fetch actor name (who added the member)
|
|
41
|
+
let actorName = "A team member";
|
|
42
|
+
try {
|
|
43
|
+
const actor = await userService.retrieveUser(data.actor_id);
|
|
44
|
+
actorName = userDisplayName(actor);
|
|
45
|
+
}
|
|
46
|
+
catch { /* fallback */ }
|
|
37
47
|
const user = await userService.retrieveUser(data.user_id);
|
|
38
48
|
if (user?.email) {
|
|
39
49
|
const tpl = resolveTemplate(container, "project.member_added", { project: { name: data.project_name }, user });
|
|
40
50
|
await emailService.send({
|
|
41
51
|
to: user.email,
|
|
42
52
|
subject: tpl?.subject ?? `You've been added to project "${data.project_name}"`,
|
|
43
|
-
text: tpl?.text ??
|
|
44
|
-
html: tpl?.html ??
|
|
53
|
+
text: tpl?.text ?? `${actorName} added you to the project "${data.project_name}".\n\nView it here: ${projectUrl}`,
|
|
54
|
+
html: tpl?.html ?? buildEmail({
|
|
55
|
+
preheader: `${actorName} added you to ${data.project_name}`,
|
|
56
|
+
heading: `You've been added to "${data.project_name}"`,
|
|
57
|
+
body: `<strong>${actorName}</strong> added you as a member of the project: <em>${data.project_name}</em>`,
|
|
58
|
+
ctaText: "View Project",
|
|
59
|
+
ctaUrl: projectUrl,
|
|
60
|
+
}),
|
|
45
61
|
});
|
|
46
62
|
}
|
|
47
63
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-member-added.js","sourceRoot":"","sources":["../../src/subscribers/project-member-added.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"project-member-added.js","sourceRoot":"","sources":["../../src/subscribers/project-member-added.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meridianjs/meridian",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.0",
|
|
4
4
|
"description": "Default API routes, workflows, links, and subscribers for Meridian applications",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
"prepublishOnly": "cd ../.. && npm run check:routes && cd packages/meridian && npm run build"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@meridianjs/framework": "^1.
|
|
24
|
-
"@meridianjs/framework-utils": "^1.
|
|
25
|
-
"@meridianjs/workflow-engine": "^1.
|
|
26
|
-
"@meridianjs/types": "^1.
|
|
23
|
+
"@meridianjs/framework": "^1.25.0",
|
|
24
|
+
"@meridianjs/framework-utils": "^1.25.0",
|
|
25
|
+
"@meridianjs/workflow-engine": "^1.25.0",
|
|
26
|
+
"@meridianjs/types": "^1.25.0",
|
|
27
27
|
"@meridianjs/user": "^1.0.0",
|
|
28
28
|
"@meridianjs/workspace": "^1.2.0",
|
|
29
|
-
"@meridianjs/auth": "^1.
|
|
29
|
+
"@meridianjs/auth": "^1.25.0",
|
|
30
30
|
"@meridianjs/project": "^1.1.0",
|
|
31
31
|
"@meridianjs/issue": "^1.5.0",
|
|
32
32
|
"@meridianjs/sprint": "^1.0.0",
|