huly-mcp-selfhost 1.0.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 (77) hide show
  1. package/.env.example +16 -0
  2. package/README.md +522 -0
  3. package/dist/connection.d.ts +9 -0
  4. package/dist/connection.js +122 -0
  5. package/dist/connection.js.map +1 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +25 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/schemas.d.ts +459 -0
  10. package/dist/schemas.js +196 -0
  11. package/dist/schemas.js.map +1 -0
  12. package/dist/server.d.ts +2 -0
  13. package/dist/server.js +87 -0
  14. package/dist/server.js.map +1 -0
  15. package/dist/tools/attachments.d.ts +28 -0
  16. package/dist/tools/attachments.js +61 -0
  17. package/dist/tools/attachments.js.map +1 -0
  18. package/dist/tools/channels.d.ts +44 -0
  19. package/dist/tools/channels.js +130 -0
  20. package/dist/tools/channels.js.map +1 -0
  21. package/dist/tools/comments.d.ts +27 -0
  22. package/dist/tools/comments.js +60 -0
  23. package/dist/tools/comments.js.map +1 -0
  24. package/dist/tools/components.d.ts +19 -0
  25. package/dist/tools/components.js +57 -0
  26. package/dist/tools/components.js.map +1 -0
  27. package/dist/tools/documents.d.ts +68 -0
  28. package/dist/tools/documents.js +207 -0
  29. package/dist/tools/documents.js.map +1 -0
  30. package/dist/tools/issues.d.ts +56 -0
  31. package/dist/tools/issues.js +262 -0
  32. package/dist/tools/issues.js.map +1 -0
  33. package/dist/tools/labels.d.ts +35 -0
  34. package/dist/tools/labels.js +150 -0
  35. package/dist/tools/labels.js.map +1 -0
  36. package/dist/tools/log-time.d.ts +10 -0
  37. package/dist/tools/log-time.js +31 -0
  38. package/dist/tools/log-time.js.map +1 -0
  39. package/dist/tools/members.d.ts +6 -0
  40. package/dist/tools/members.js +17 -0
  41. package/dist/tools/members.js.map +1 -0
  42. package/dist/tools/milestones.d.ts +19 -0
  43. package/dist/tools/milestones.js +80 -0
  44. package/dist/tools/milestones.js.map +1 -0
  45. package/dist/tools/organizations.d.ts +32 -0
  46. package/dist/tools/organizations.js +86 -0
  47. package/dist/tools/organizations.js.map +1 -0
  48. package/dist/tools/projects.d.ts +24 -0
  49. package/dist/tools/projects.js +64 -0
  50. package/dist/tools/projects.js.map +1 -0
  51. package/dist/tools/relations.d.ts +27 -0
  52. package/dist/tools/relations.js +103 -0
  53. package/dist/tools/relations.js.map +1 -0
  54. package/dist/tools/search.d.ts +9 -0
  55. package/dist/tools/search.js +32 -0
  56. package/dist/tools/search.js.map +1 -0
  57. package/dist/tools/statuses.d.ts +16 -0
  58. package/dist/tools/statuses.js +93 -0
  59. package/dist/tools/statuses.js.map +1 -0
  60. package/dist/utils/errors.d.ts +11 -0
  61. package/dist/utils/errors.js +24 -0
  62. package/dist/utils/errors.js.map +1 -0
  63. package/dist/utils/format.d.ts +4 -0
  64. package/dist/utils/format.js +28 -0
  65. package/dist/utils/format.js.map +1 -0
  66. package/dist/utils/markdown.d.ts +14 -0
  67. package/dist/utils/markdown.js +144 -0
  68. package/dist/utils/markdown.js.map +1 -0
  69. package/dist/utils/storage.d.ts +7 -0
  70. package/dist/utils/storage.js +82 -0
  71. package/dist/utils/storage.js.map +1 -0
  72. package/package.json +68 -0
  73. package/scripts/cleanup-issues.js +132 -0
  74. package/scripts/demo.js +193 -0
  75. package/scripts/import-csv.js +242 -0
  76. package/scripts/sample-tasks.csv +11 -0
  77. package/scripts/setup.js +103 -0
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setParent = exports.addBlockedBy = exports.addRelation = void 0;
7
+ const tracker_1 = __importDefault(require("@hcengineering/tracker"));
8
+ const connection_1 = require("../connection");
9
+ const errors_1 = require("../utils/errors");
10
+ exports.addRelation = (0, errors_1.wrapToolHandler)(async (args) => {
11
+ const client = await (0, connection_1.getConnection)();
12
+ const issueA = await client.findOne(tracker_1.default.class.Issue, { identifier: args.identifier });
13
+ if (issueA == null)
14
+ throw new Error(`Issue '${args.identifier}' not found.`);
15
+ const issueB = await client.findOne(tracker_1.default.class.Issue, { identifier: args.relatedTo });
16
+ if (issueB == null)
17
+ throw new Error(`Issue '${args.relatedTo}' not found.`);
18
+ const relA = { _id: issueB._id, _class: issueB._class };
19
+ const relB = { _id: issueA._id, _class: issueA._class };
20
+ const existingRels = issueA.relations ?? [];
21
+ if (existingRels.some((r) => r._id === issueB._id)) {
22
+ return `**${args.identifier}** is already related to **${args.relatedTo}**.`;
23
+ }
24
+ // Add bidirectional relation
25
+ await client.updateDoc(tracker_1.default.class.Issue, issueA.space, issueA._id, {
26
+ relations: [...existingRels, relA]
27
+ });
28
+ await client.updateDoc(tracker_1.default.class.Issue, issueB.space, issueB._id, {
29
+ relations: [...(issueB.relations ?? []), relB]
30
+ });
31
+ return `✅ **${args.identifier}** is now related to **${args.relatedTo}**`;
32
+ });
33
+ exports.addBlockedBy = (0, errors_1.wrapToolHandler)(async (args) => {
34
+ const client = await (0, connection_1.getConnection)();
35
+ const issue = await client.findOne(tracker_1.default.class.Issue, { identifier: args.identifier });
36
+ if (issue == null)
37
+ throw new Error(`Issue '${args.identifier}' not found.`);
38
+ const blocker = await client.findOne(tracker_1.default.class.Issue, { identifier: args.blockedBy });
39
+ if (blocker == null)
40
+ throw new Error(`Issue '${args.blockedBy}' not found.`);
41
+ const blockerRef = { _id: blocker._id, _class: blocker._class };
42
+ const existing = issue.blockedBy ?? [];
43
+ if (existing.some((r) => r._id === blocker._id)) {
44
+ return `**${args.identifier}** is already blocked by **${args.blockedBy}**.`;
45
+ }
46
+ await client.updateDoc(tracker_1.default.class.Issue, issue.space, issue._id, {
47
+ blockedBy: [...existing, blockerRef]
48
+ });
49
+ return `✅ **${args.identifier}** is now blocked by **${args.blockedBy}**`;
50
+ });
51
+ exports.setParent = (0, errors_1.wrapToolHandler)(async (args) => {
52
+ const client = await (0, connection_1.getConnection)();
53
+ const child = await client.findOne(tracker_1.default.class.Issue, { identifier: args.identifier });
54
+ if (child == null)
55
+ throw new Error(`Issue '${args.identifier}' not found.`);
56
+ // Clear parent if requested
57
+ if (args.parentIdentifier == null) {
58
+ await client.updateDoc(tracker_1.default.class.Issue, child.space, child._id, { parents: [] });
59
+ // Remove from old parent's childInfo if there was one
60
+ if (child.parents.length > 0) {
61
+ const oldParentId = child.parents[0].parentId;
62
+ const oldParent = await client.findOne(tracker_1.default.class.Issue, { _id: oldParentId });
63
+ if (oldParent != null) {
64
+ const newChildInfo = (oldParent.childInfo ?? []).filter((c) => c.childId !== child._id);
65
+ await client.updateDoc(tracker_1.default.class.Issue, oldParent.space, oldParent._id, {
66
+ subIssues: Math.max(0, (oldParent.subIssues ?? 1) - 1),
67
+ childInfo: newChildInfo
68
+ });
69
+ }
70
+ }
71
+ return `✅ Cleared parent from **${args.identifier}**`;
72
+ }
73
+ const parent = await client.findOne(tracker_1.default.class.Issue, { identifier: args.parentIdentifier });
74
+ if (parent == null)
75
+ throw new Error(`Parent issue '${args.parentIdentifier}' not found.`);
76
+ if (parent._id === child._id)
77
+ throw new Error('An issue cannot be its own parent.');
78
+ const parentInfo = {
79
+ parentId: parent._id,
80
+ identifier: parent.identifier,
81
+ parentTitle: parent.title,
82
+ space: parent.space
83
+ };
84
+ const childInfoEntry = {
85
+ childId: child._id,
86
+ estimation: child.estimation ?? 0,
87
+ reportedTime: child.reportedTime ?? 0
88
+ };
89
+ // Update child's parents list
90
+ await client.updateDoc(tracker_1.default.class.Issue, child.space, child._id, {
91
+ parents: [parentInfo, ...child.parents]
92
+ });
93
+ // Update parent's subIssues count and childInfo
94
+ const existingChildInfo = parent.childInfo ?? [];
95
+ if (!existingChildInfo.some((c) => c.childId === child._id)) {
96
+ await client.updateDoc(tracker_1.default.class.Issue, parent.space, parent._id, {
97
+ subIssues: (parent.subIssues ?? 0) + 1,
98
+ childInfo: [...existingChildInfo, childInfoEntry]
99
+ });
100
+ }
101
+ return `✅ **${args.identifier}** is now a sub-issue of **${args.parentIdentifier}**`;
102
+ });
103
+ //# sourceMappingURL=relations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relations.js","sourceRoot":"","sources":["../../src/tools/relations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare const searchIssues: (args: {
2
+ limit: number;
3
+ query: string;
4
+ }) => Promise<{
5
+ content: Array<{
6
+ type: "text";
7
+ text: string;
8
+ }>;
9
+ }>;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.searchIssues = void 0;
7
+ const tracker_1 = __importDefault(require("@hcengineering/tracker"));
8
+ const connection_1 = require("../connection");
9
+ const errors_1 = require("../utils/errors");
10
+ const format_1 = require("../utils/format");
11
+ exports.searchIssues = (0, errors_1.wrapToolHandler)(async (args) => {
12
+ const client = await (0, connection_1.getConnection)();
13
+ const result = await client.searchFulltext({ query: args.query, classes: [tracker_1.default.class.Issue] }, { limit: args.limit });
14
+ if (result.docs.length === 0)
15
+ return `No issues found for query: "${args.query}"`;
16
+ // Enrich each result with full issue data
17
+ const enriched = await Promise.all(result.docs.map(async (r) => {
18
+ const issue = await client.findOne(tracker_1.default.class.Issue, { _id: r.id });
19
+ if (issue == null)
20
+ return null;
21
+ const status = await client.findOne(tracker_1.default.class.IssueStatus, { _id: issue.status });
22
+ return { issue, statusName: status?.name ?? 'Unknown' };
23
+ }));
24
+ const lines = enriched
25
+ .filter((e) => e !== null)
26
+ .map((e) => {
27
+ const due = e.issue.dueDate != null ? ` | Due: ${(0, format_1.formatDate)(e.issue.dueDate)}` : '';
28
+ return `- **${e.issue.identifier}** [${e.statusName}] [${(0, format_1.priorityLabel)(e.issue.priority)}]${due}\n ${e.issue.title}`;
29
+ });
30
+ return `## Search results for "${args.query}" (${lines.length})\n\n${lines.join('\n')}`;
31
+ });
32
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":";;;;;;AAAA,qEAA4C;AAC5C,8CAA6C;AAC7C,4CAAiD;AACjD,4CAA2D;AAI9C,QAAA,YAAY,GAAG,IAAA,wBAAe,EAAqC,KAAK,EAAE,IAAI,EAAE,EAAE;IAC7F,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAa,GAAE,CAAA;IAEpC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CACxC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,iBAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EACrD,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CACtB,CAAA;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,+BAA+B,IAAI,CAAC,KAAK,GAAG,CAAA;IAEjF,0CAA0C;IAC1C,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAO,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,EAAS,EAAE,CAAC,CAAA;QAC7E,IAAI,KAAK,IAAI,IAAI;YAAE,OAAO,IAAI,CAAA;QAC9B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAO,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;QACrF,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,IAAI,SAAS,EAAE,CAAA;IACzD,CAAC,CAAC,CACH,CAAA;IAED,MAAM,KAAK,GAAG,QAAQ;SACnB,MAAM,CAAC,CAAC,CAAC,EAA8B,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;SACrD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,IAAA,mBAAU,EAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QACnF,OAAO,OAAO,CAAC,CAAC,KAAK,CAAC,UAAU,OAAO,CAAC,CAAC,UAAU,MAAM,IAAA,sBAAa,EAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;IACvH,CAAC,CAAC,CAAA;IAEJ,OAAO,0BAA0B,IAAI,CAAC,KAAK,MAAM,KAAK,CAAC,MAAM,QAAQ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;AACzF,CAAC,CAAC,CAAA"}
@@ -0,0 +1,16 @@
1
+ export declare const listIssueStatuses: (args: {}) => Promise<{
2
+ content: Array<{
3
+ type: "text";
4
+ text: string;
5
+ }>;
6
+ }>;
7
+ export declare const createIssueStatus: (args: {
8
+ name: string;
9
+ category: "InProgress" | "Backlog" | "Todo" | "Done" | "Cancelled";
10
+ color?: string | undefined;
11
+ }) => Promise<{
12
+ content: Array<{
13
+ type: "text";
14
+ text: string;
15
+ }>;
16
+ }>;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.createIssueStatus = exports.listIssueStatuses = void 0;
40
+ const tracker_1 = __importDefault(require("@hcengineering/tracker"));
41
+ const task_1 = __importDefault(require("@hcengineering/task"));
42
+ const core_1 = __importStar(require("@hcengineering/core"));
43
+ const connection_1 = require("../connection");
44
+ const errors_1 = require("../utils/errors");
45
+ // Issue statuses are stored globally (not per-project) — a status created
46
+ // here immediately becomes selectable in every tracker project. See
47
+ // tracker:attribute:IssueStatus and task:statusCategory:* for the model.
48
+ const CATEGORY_MAP = {
49
+ Backlog: { ref: task_1.default.statusCategory.UnStarted, label: 'Backlog' },
50
+ Todo: { ref: task_1.default.statusCategory.ToDo, label: 'Todo' },
51
+ InProgress: { ref: task_1.default.statusCategory.Active, label: 'In Progress' },
52
+ Done: { ref: task_1.default.statusCategory.Won, label: 'Done' },
53
+ Cancelled: { ref: task_1.default.statusCategory.Lost, label: 'Cancelled' }
54
+ };
55
+ exports.listIssueStatuses = (0, errors_1.wrapToolHandler)(async () => {
56
+ const client = await (0, connection_1.getConnection)();
57
+ const statuses = await client.findAll(tracker_1.default.class.IssueStatus, {});
58
+ if (statuses.length === 0)
59
+ return 'No issue statuses found.';
60
+ const byCategory = new Map();
61
+ for (const s of statuses) {
62
+ const key = String(s.category ?? 'Unknown');
63
+ if (!byCategory.has(key))
64
+ byCategory.set(key, []);
65
+ byCategory.get(key).push(s);
66
+ }
67
+ const lines = [];
68
+ for (const [category, group] of byCategory) {
69
+ const shortCategory = category.split(':').pop() ?? category;
70
+ lines.push(`**${shortCategory}:**`);
71
+ for (const s of group)
72
+ lines.push(` - ${s.name} (id: \`${s._id}\`)`);
73
+ }
74
+ return `## Issue Statuses (${statuses.length})\n\n${lines.join('\n')}`;
75
+ });
76
+ exports.createIssueStatus = (0, errors_1.wrapToolHandler)(async (args) => {
77
+ const client = await (0, connection_1.getConnection)();
78
+ const existing = await client.findOne(tracker_1.default.class.IssueStatus, { name: args.name });
79
+ if (existing != null)
80
+ return `ℹ️ Status **"${args.name}"** already exists (id: \`${existing._id}\`).`;
81
+ const mapped = CATEGORY_MAP[args.category];
82
+ if (mapped == null)
83
+ throw new Error(`Unknown category '${args.category}'.`);
84
+ const statusId = (0, core_1.generateId)();
85
+ await client.createDoc(tracker_1.default.class.IssueStatus, core_1.default.space.Model, {
86
+ ofAttribute: tracker_1.default.attribute.IssueStatus,
87
+ category: mapped.ref,
88
+ name: args.name,
89
+ color: args.color != null ? parseInt(args.color.replace('#', ''), 16) : undefined
90
+ }, statusId);
91
+ return `✅ Status **"${args.name}"** created in the **${mapped.label}** phase (id: \`${statusId}\`) — available in every project immediately.`;
92
+ });
93
+ //# sourceMappingURL=statuses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statuses.js","sourceRoot":"","sources":["../../src/tools/statuses.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export declare class HulyMcpError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ type ToolResult = {
5
+ content: Array<{
6
+ type: 'text';
7
+ text: string;
8
+ }>;
9
+ };
10
+ export declare function wrapToolHandler<T extends Record<string, unknown>>(handler: (args: T) => Promise<string>): (args: T) => Promise<ToolResult>;
11
+ export {};
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HulyMcpError = void 0;
4
+ exports.wrapToolHandler = wrapToolHandler;
5
+ class HulyMcpError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = 'HulyMcpError';
9
+ }
10
+ }
11
+ exports.HulyMcpError = HulyMcpError;
12
+ function wrapToolHandler(handler) {
13
+ return async (args) => {
14
+ try {
15
+ const text = await handler(args);
16
+ return { content: [{ type: 'text', text }] };
17
+ }
18
+ catch (err) {
19
+ const message = err instanceof Error ? err.message : String(err);
20
+ throw new Error(`Huly MCP: ${message}`);
21
+ }
22
+ };
23
+ }
24
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":";;;AASA,0CAYC;AArBD,MAAa,YAAa,SAAQ,KAAK;IACrC,YAAa,OAAe;QAC1B,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,cAAc,CAAA;IAC5B,CAAC;CACF;AALD,oCAKC;AAID,SAAgB,eAAe,CAC7B,OAAqC;IAErC,OAAO,KAAK,EAAE,IAAO,EAAuB,EAAE;QAC5C,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;YAChC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAA;QAC9C,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAChE,MAAM,IAAI,KAAK,CAAC,aAAa,OAAO,EAAE,CAAC,CAAA;QACzC,CAAC;IACH,CAAC,CAAA;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const PRIORITY_LABELS: Record<number, string>;
2
+ export declare const MILESTONE_STATUS_LABELS: Record<number, string>;
3
+ export declare function formatDate(ts: number | null | undefined): string;
4
+ export declare function priorityLabel(priority: number): string;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MILESTONE_STATUS_LABELS = exports.PRIORITY_LABELS = void 0;
4
+ exports.formatDate = formatDate;
5
+ exports.priorityLabel = priorityLabel;
6
+ const tracker_1 = require("@hcengineering/tracker");
7
+ exports.PRIORITY_LABELS = {
8
+ [tracker_1.IssuePriority.NoPriority]: 'No Priority',
9
+ [tracker_1.IssuePriority.Urgent]: 'Urgent',
10
+ [tracker_1.IssuePriority.High]: 'High',
11
+ [tracker_1.IssuePriority.Medium]: 'Medium',
12
+ [tracker_1.IssuePriority.Low]: 'Low'
13
+ };
14
+ exports.MILESTONE_STATUS_LABELS = {
15
+ 0: 'Planned',
16
+ 1: 'In Progress',
17
+ 2: 'Completed',
18
+ 3: 'Canceled'
19
+ };
20
+ function formatDate(ts) {
21
+ if (ts == null)
22
+ return 'None';
23
+ return new Date(ts).toISOString().split('T')[0];
24
+ }
25
+ function priorityLabel(priority) {
26
+ return exports.PRIORITY_LABELS[priority] ?? 'Unknown';
27
+ }
28
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":";;;AAiBA,gCAGC;AAED,sCAEC;AAxBD,oDAAsD;AAEzC,QAAA,eAAe,GAA2B;IACrD,CAAC,uBAAa,CAAC,UAAU,CAAC,EAAE,aAAa;IACzC,CAAC,uBAAa,CAAC,MAAM,CAAC,EAAE,QAAQ;IAChC,CAAC,uBAAa,CAAC,IAAI,CAAC,EAAE,MAAM;IAC5B,CAAC,uBAAa,CAAC,MAAM,CAAC,EAAE,QAAQ;IAChC,CAAC,uBAAa,CAAC,GAAG,CAAC,EAAE,KAAK;CAC3B,CAAA;AAEY,QAAA,uBAAuB,GAA2B;IAC7D,CAAC,EAAE,SAAS;IACZ,CAAC,EAAE,aAAa;IAChB,CAAC,EAAE,WAAW;IACd,CAAC,EAAE,UAAU;CACd,CAAA;AAED,SAAgB,UAAU,CAAE,EAA6B;IACvD,IAAI,EAAE,IAAI,IAAI;QAAE,OAAO,MAAM,CAAA;IAC7B,OAAO,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AACjD,CAAC;AAED,SAAgB,aAAa,CAAE,QAAgB;IAC7C,OAAO,uBAAe,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAA;AAC/C,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface PMNode {
2
+ type: string;
3
+ attrs?: Record<string, any>;
4
+ content?: PMNode[];
5
+ marks?: Array<{
6
+ type: string;
7
+ attrs?: Record<string, any>;
8
+ }>;
9
+ text?: string;
10
+ }
11
+ export declare function markdownToProseMirror(md: string): PMNode;
12
+ export declare function parseInline(text: string): PMNode[];
13
+ export declare function buildTable(rows: string[][]): PMNode;
14
+ export declare function extractText(node: any): string;
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ // Minimal Markdown → Huly ProseMirror JSON converter.
3
+ // Extracted from tools/documents.ts so it can be shared with tools/issues.ts
4
+ // (issue descriptions use the exact same MarkupBlobRef storage mechanism as
5
+ // document content).
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.markdownToProseMirror = markdownToProseMirror;
8
+ exports.parseInline = parseInline;
9
+ exports.buildTable = buildTable;
10
+ exports.extractText = extractText;
11
+ function markdownToProseMirror(md) {
12
+ const lines = md.split('\n');
13
+ const nodes = [];
14
+ let i = 0;
15
+ while (i < lines.length) {
16
+ const line = lines[i];
17
+ // Fenced code block
18
+ if (line.startsWith('```')) {
19
+ const lang = line.slice(3).trim();
20
+ const codeLines = [];
21
+ i++;
22
+ while (i < lines.length && !lines[i].startsWith('```')) {
23
+ codeLines.push(lines[i]);
24
+ i++;
25
+ }
26
+ i++; // skip closing ```
27
+ // Use Huly's native 'mermaid' node type so diagrams render properly
28
+ const nodeType = lang === 'mermaid' ? 'mermaid' : 'codeBlock';
29
+ nodes.push({
30
+ type: nodeType,
31
+ attrs: { language: lang !== '' ? lang : null },
32
+ content: [{ type: 'text', text: codeLines.join('\n') }]
33
+ });
34
+ continue;
35
+ }
36
+ // Heading
37
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
38
+ if (headingMatch != null) {
39
+ nodes.push({
40
+ type: 'heading',
41
+ attrs: { level: headingMatch[1].length },
42
+ content: parseInline(headingMatch[2])
43
+ });
44
+ i++;
45
+ continue;
46
+ }
47
+ // Table (Markdown pipe table)
48
+ if (line.includes('|') && line.trim().startsWith('|')) {
49
+ const tableRows = [];
50
+ while (i < lines.length && lines[i].includes('|') && lines[i].trim().startsWith('|')) {
51
+ const row = lines[i].trim().replace(/^\||\|$/g, '').split('|').map((c) => c.trim());
52
+ // Skip separator rows like |---|---|
53
+ if (!row.every((c) => /^[-:]+$/.test(c))) {
54
+ tableRows.push(row);
55
+ }
56
+ i++;
57
+ }
58
+ if (tableRows.length > 0) {
59
+ nodes.push(buildTable(tableRows));
60
+ }
61
+ continue;
62
+ }
63
+ // Bullet list
64
+ if (/^(\s*[-*+])\s/.test(line)) {
65
+ const items = [];
66
+ while (i < lines.length && /^(\s*[-*+])\s/.test(lines[i])) {
67
+ const text = lines[i].replace(/^\s*[-*+]\s/, '');
68
+ items.push({
69
+ type: 'listItem',
70
+ content: [{ type: 'paragraph', content: parseInline(text) }]
71
+ });
72
+ i++;
73
+ }
74
+ nodes.push({ type: 'bulletList', content: items });
75
+ continue;
76
+ }
77
+ // Blank line → skip
78
+ if (line.trim() === '') {
79
+ i++;
80
+ continue;
81
+ }
82
+ // Default paragraph
83
+ nodes.push({ type: 'paragraph', content: parseInline(line) });
84
+ i++;
85
+ }
86
+ if (nodes.length === 0) {
87
+ nodes.push({ type: 'paragraph', content: [] });
88
+ }
89
+ return { type: 'doc', content: nodes };
90
+ }
91
+ function parseInline(text) {
92
+ const nodes = [];
93
+ // Handle **bold**, `code`, plain text
94
+ const re = /\*\*(.+?)\*\*|`(.+?)`|([^`*]+)/g;
95
+ let m;
96
+ while ((m = re.exec(text)) !== null) {
97
+ if (m[1] != null) {
98
+ nodes.push({ type: 'text', text: m[1], marks: [{ type: 'bold' }] });
99
+ }
100
+ else if (m[2] != null) {
101
+ nodes.push({ type: 'text', text: m[2], marks: [{ type: 'code' }] });
102
+ }
103
+ else if (m[3] != null && m[3].length > 0) {
104
+ nodes.push({ type: 'text', text: m[3] });
105
+ }
106
+ }
107
+ return nodes.length > 0 ? nodes : [{ type: 'text', text }];
108
+ }
109
+ function buildTable(rows) {
110
+ const [headerRow, ...bodyRows] = rows;
111
+ const tableRows = [];
112
+ if (headerRow != null) {
113
+ tableRows.push({
114
+ type: 'tableRow',
115
+ content: headerRow.map((cell) => ({
116
+ type: 'tableHeader',
117
+ content: [{ type: 'paragraph', content: parseInline(cell) }]
118
+ }))
119
+ });
120
+ }
121
+ for (const row of bodyRows) {
122
+ tableRows.push({
123
+ type: 'tableRow',
124
+ content: row.map((cell) => ({
125
+ type: 'tableCell',
126
+ content: [{ type: 'paragraph', content: parseInline(cell) }]
127
+ }))
128
+ });
129
+ }
130
+ return { type: 'table', content: tableRows };
131
+ }
132
+ // Extract plain text from Huly's ProseMirror JSON markup (inverse-ish of
133
+ // markdownToProseMirror, used for get_document / get_issue content reads).
134
+ function extractText(node) {
135
+ if (typeof node === 'string')
136
+ return node;
137
+ if (node == null || typeof node !== 'object')
138
+ return '';
139
+ if (node.type === 'text' && typeof node.text === 'string')
140
+ return node.text;
141
+ const children = node.content ?? node.children ?? [];
142
+ return children.map(extractText).join(node.type === 'paragraph' || node.type === 'heading' ? '\n' : '');
143
+ }
144
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/utils/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface UploadResult {
2
+ id: string;
3
+ size: number;
4
+ }
5
+ export declare function uploadMarkupBlob(wsToken: string, workspaceUuid: string, blobId: string, content: string): Promise<string>;
6
+ export declare function uploadBlob(wsToken: string, workspaceUuid: string, blobId: string, blob: Blob): Promise<UploadResult>;
7
+ export declare function deleteBlob(wsToken: string, workspaceUuid: string, blobId: string): Promise<void>;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ // Blob upload — used for MarkupBlobRef content (document bodies, issue
3
+ // descriptions) as well as generic file attachments.
4
+ //
5
+ // Huly Cloud uses a dedicated "datalake" microservice (see
6
+ // foundations/core/packages/storage-client/src/client/datalake.ts in
7
+ // hcengineering/platform) reachable at a fixed URL like https://dl-eu.huly.app,
8
+ // with the contract POST {datalakeUrl}/upload/form-data/{workspaceUuid}.
9
+ //
10
+ // huly-selfhost (v0.7.x) does NOT run that microservice — blob storage is
11
+ // wired directly into the `front` service via STORAGE_CONFIG (typically
12
+ // MinIO), exposed through front's own, older /files endpoint (see
13
+ // server/front/src/index.ts, handleUpload). Contract differs:
14
+ // POST {frontUrl}/files (workspace resolved server-side from token)
15
+ // multipart field name: "file"
16
+ // Authorization: Bearer <workspace token>
17
+ // 200 response: [{ key: "file", id: <blobId>, metadata: {...} }]
18
+ //
19
+ // Which one to use is auto-detected: if HULY_FRONT_URL is set (already
20
+ // required for self-hosted get_document reads per the README), we use the
21
+ // self-hosted /files contract. Otherwise we fall back to Huly Cloud's
22
+ // datalake, preserving the original behavior for huly.app users.
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.uploadMarkupBlob = uploadMarkupBlob;
25
+ exports.uploadBlob = uploadBlob;
26
+ exports.deleteBlob = deleteBlob;
27
+ const CLOUD_DATALAKE_URL = 'https://dl-eu.huly.app';
28
+ async function uploadMarkupBlob(wsToken, workspaceUuid, blobId, content) {
29
+ const result = await uploadBlob(wsToken, workspaceUuid, blobId, new Blob([content], { type: 'application/json' }));
30
+ return result.id;
31
+ }
32
+ async function uploadBlob(wsToken, workspaceUuid, blobId, blob) {
33
+ const frontUrl = process.env.HULY_FRONT_URL;
34
+ if (frontUrl != null && frontUrl !== '') {
35
+ return await uploadViaSelfHostedFront(frontUrl, wsToken, blobId, blob);
36
+ }
37
+ return await uploadViaCloudDatalake(workspaceUuid, wsToken, blobId, blob);
38
+ }
39
+ async function uploadViaSelfHostedFront(frontUrl, wsToken, blobId, blob) {
40
+ const form = new FormData();
41
+ form.append('file', blob, blobId);
42
+ const uploadUrl = `${frontUrl.replace(/\/$/, '')}/files`;
43
+ const uploadRes = await fetch(uploadUrl, {
44
+ method: 'POST',
45
+ headers: { Authorization: `Bearer ${wsToken}` },
46
+ body: form
47
+ });
48
+ if (!uploadRes.ok) {
49
+ const body = await uploadRes.text().catch(() => '');
50
+ throw new Error(`Self-hosted file upload failed (${uploadRes.status}) at ${uploadUrl}: ${body}`);
51
+ }
52
+ const uploadJson = await uploadRes.json();
53
+ const uploadedId = uploadJson[0]?.id;
54
+ if (uploadedId == null) {
55
+ throw new Error(`Self-hosted file upload: no blob id in response: ${JSON.stringify(uploadJson)}`);
56
+ }
57
+ return { id: uploadedId, size: uploadJson[0]?.metadata?.size ?? blob.size };
58
+ }
59
+ async function uploadViaCloudDatalake(workspaceUuid, wsToken, blobId, blob) {
60
+ const form = new FormData();
61
+ form.append('file', blob, blobId);
62
+ const uploadUrl = `${CLOUD_DATALAKE_URL}/upload/form-data/${workspaceUuid}`;
63
+ const uploadRes = await fetch(uploadUrl, {
64
+ method: 'POST',
65
+ headers: { Authorization: `Bearer ${wsToken}` },
66
+ body: form
67
+ });
68
+ if (!uploadRes.ok) {
69
+ const body = await uploadRes.text().catch(() => '');
70
+ throw new Error(`Datalake upload failed (${uploadRes.status}): ${body}`);
71
+ }
72
+ const uploadJson = await uploadRes.json();
73
+ return { id: uploadJson[0]?.id ?? blobId, size: uploadJson[0]?.metadata?.size ?? blob.size };
74
+ }
75
+ async function deleteBlob(wsToken, workspaceUuid, blobId) {
76
+ const frontUrl = process.env.HULY_FRONT_URL;
77
+ const url = frontUrl != null && frontUrl !== ''
78
+ ? `${frontUrl.replace(/\/$/, '')}/files?file=${encodeURIComponent(blobId)}`
79
+ : `${CLOUD_DATALAKE_URL}/blob/${encodeURIComponent(workspaceUuid)}/${encodeURIComponent(blobId)}`;
80
+ await fetch(url, { method: 'DELETE', headers: { Authorization: `Bearer ${wsToken}` } }).catch(() => { });
81
+ }
82
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":";AAAA,uEAAuE;AACvE,qDAAqD;AACrD,EAAE;AACF,2DAA2D;AAC3D,qEAAqE;AACrE,gFAAgF;AAChF,yEAAyE;AACzE,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,kEAAkE;AAClE,8DAA8D;AAC9D,iFAAiF;AACjF,iCAAiC;AACjC,4CAA4C;AAC5C,mEAAmE;AACnE,EAAE;AACF,uEAAuE;AACvE,0EAA0E;AAC1E,sEAAsE;AACtE,iEAAiE;;AASjE,4CAaC;AAED,gCAYC;AAwDD,gCAOC;AAjGD,MAAM,kBAAkB,GAAG,wBAAwB,CAAA;AAO5C,KAAK,UAAU,gBAAgB,CACpC,OAAe,EACf,aAAqB,EACrB,MAAc,EACd,OAAe;IAEf,MAAM,MAAM,GAAG,MAAM,UAAU,CAC7B,OAAO,EACP,aAAa,EACb,MAAM,EACN,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAClD,CAAA;IACD,OAAO,MAAM,CAAC,EAAE,CAAA;AAClB,CAAC;AAEM,KAAK,UAAU,UAAU,CAC9B,OAAe,EACf,aAAqB,EACrB,MAAc,EACd,IAAU;IAEV,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;IAE3C,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;QACxC,OAAO,MAAM,wBAAwB,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;IACxE,CAAC;IACD,OAAO,MAAM,sBAAsB,CAAC,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;AAC3E,CAAC;AAED,KAAK,UAAU,wBAAwB,CACrC,QAAgB,EAChB,OAAe,EACf,MAAc,EACd,IAAU;IAEV,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAA;IAC3B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;IAEjC,MAAM,SAAS,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAA;IACxD,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE;QACvC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,OAAO,EAAE,EAAE;QAC/C,IAAI,EAAE,IAAI;KACX,CAAC,CAAA;IAEF,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;QACnD,MAAM,IAAI,KAAK,CAAC,mCAAmC,SAAS,CAAC,MAAM,QAAQ,SAAS,KAAK,IAAI,EAAE,CAAC,CAAA;IAClG,CAAC;IAED,MAAM,UAAU,GAAqE,MAAM,SAAS,CAAC,IAAI,EAAE,CAAA;IAC3G,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;IACpC,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,oDAAoD,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IACnG,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAA;AAC7E,CAAC;AAED,KAAK,UAAU,sBAAsB,CACnC,aAAqB,EACrB,OAAe,EACf,MAAc,EACd,IAAU;IAEV,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAA;IAC3B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;IAEjC,MAAM,SAAS,GAAG,GAAG,kBAAkB,qBAAqB,aAAa,EAAE,CAAA;IAC3E,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE;QACvC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,OAAO,EAAE,EAAE;QAC/C,IAAI,EAAE,IAAI;KACX,CAAC,CAAA;IAEF,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;QACnD,MAAM,IAAI,KAAK,CAAC,2BAA2B,SAAS,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAA;IAC1E,CAAC;IAED,MAAM,UAAU,GAAqE,MAAM,SAAS,CAAC,IAAI,EAAE,CAAA;IAC3G,OAAO,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAA;AAC9F,CAAC;AAEM,KAAK,UAAU,UAAU,CAAE,OAAe,EAAE,aAAqB,EAAE,MAAc;IACtF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;IAC3C,MAAM,GAAG,GAAG,QAAQ,IAAI,IAAI,IAAI,QAAQ,KAAK,EAAE;QAC7C,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,kBAAkB,CAAC,MAAM,CAAC,EAAE;QAC3E,CAAC,CAAC,GAAG,kBAAkB,SAAS,kBAAkB,CAAC,aAAa,CAAC,IAAI,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAA;IAEnG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;AACzG,CAAC"}