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.
- package/.env.example +16 -0
- package/README.md +522 -0
- package/dist/connection.d.ts +9 -0
- package/dist/connection.js +122 -0
- package/dist/connection.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas.d.ts +459 -0
- package/dist/schemas.js +196 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +87 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/attachments.d.ts +28 -0
- package/dist/tools/attachments.js +61 -0
- package/dist/tools/attachments.js.map +1 -0
- package/dist/tools/channels.d.ts +44 -0
- package/dist/tools/channels.js +130 -0
- package/dist/tools/channels.js.map +1 -0
- package/dist/tools/comments.d.ts +27 -0
- package/dist/tools/comments.js +60 -0
- package/dist/tools/comments.js.map +1 -0
- package/dist/tools/components.d.ts +19 -0
- package/dist/tools/components.js +57 -0
- package/dist/tools/components.js.map +1 -0
- package/dist/tools/documents.d.ts +68 -0
- package/dist/tools/documents.js +207 -0
- package/dist/tools/documents.js.map +1 -0
- package/dist/tools/issues.d.ts +56 -0
- package/dist/tools/issues.js +262 -0
- package/dist/tools/issues.js.map +1 -0
- package/dist/tools/labels.d.ts +35 -0
- package/dist/tools/labels.js +150 -0
- package/dist/tools/labels.js.map +1 -0
- package/dist/tools/log-time.d.ts +10 -0
- package/dist/tools/log-time.js +31 -0
- package/dist/tools/log-time.js.map +1 -0
- package/dist/tools/members.d.ts +6 -0
- package/dist/tools/members.js +17 -0
- package/dist/tools/members.js.map +1 -0
- package/dist/tools/milestones.d.ts +19 -0
- package/dist/tools/milestones.js +80 -0
- package/dist/tools/milestones.js.map +1 -0
- package/dist/tools/organizations.d.ts +32 -0
- package/dist/tools/organizations.js +86 -0
- package/dist/tools/organizations.js.map +1 -0
- package/dist/tools/projects.d.ts +24 -0
- package/dist/tools/projects.js +64 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/relations.d.ts +27 -0
- package/dist/tools/relations.js +103 -0
- package/dist/tools/relations.js.map +1 -0
- package/dist/tools/search.d.ts +9 -0
- package/dist/tools/search.js +32 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/statuses.d.ts +16 -0
- package/dist/tools/statuses.js +93 -0
- package/dist/tools/statuses.js.map +1 -0
- package/dist/utils/errors.d.ts +11 -0
- package/dist/utils/errors.js +24 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/format.d.ts +4 -0
- package/dist/utils/format.js +28 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/markdown.d.ts +14 -0
- package/dist/utils/markdown.js +144 -0
- package/dist/utils/markdown.js.map +1 -0
- package/dist/utils/storage.d.ts +7 -0
- package/dist/utils/storage.js +82 -0
- package/dist/utils/storage.js.map +1 -0
- package/package.json +68 -0
- package/scripts/cleanup-issues.js +132 -0
- package/scripts/demo.js +193 -0
- package/scripts/import-csv.js +242 -0
- package/scripts/sample-tasks.csv +11 -0
- 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,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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qEAAkE;AAClE,+DAAsC;AACtC,4DAAsD;AACtD,8CAA6C;AAC7C,4CAAiD;AAIjD,0EAA0E;AAC1E,oEAAoE;AACpE,yEAAyE;AACzE,MAAM,YAAY,GAAgD;IAChE,OAAO,EAAE,EAAE,GAAG,EAAE,cAAI,CAAC,cAAc,CAAC,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;IACjE,IAAI,EAAE,EAAE,GAAG,EAAE,cAAI,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE;IACtD,UAAU,EAAE,EAAE,GAAG,EAAE,cAAI,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE;IACrE,IAAI,EAAE,EAAE,GAAG,EAAE,cAAI,CAAC,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE;IACrD,SAAS,EAAE,EAAE,GAAG,EAAE,cAAI,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE;CACjE,CAAA;AAEY,QAAA,iBAAiB,GAAG,IAAA,wBAAe,EAA0C,KAAK,IAAI,EAAE;IACnG,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAa,GAAE,CAAA;IACpC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAO,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;IACpE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,0BAA0B,CAAA;IAE5D,MAAM,UAAU,GAAG,IAAI,GAAG,EAA2B,CAAA;IACrD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,SAAS,CAAC,CAAA;QAC3C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,EAAS,CAAC,CAAA;QACxD,UAAU,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC9B,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3C,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,QAAQ,CAAA;QAC3D,KAAK,CAAC,IAAI,CAAC,KAAK,aAAa,KAAK,CAAC,CAAA;QACnC,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,GAAG,KAAK,CAAC,CAAA;IACvE,CAAC;IAED,OAAO,sBAAsB,QAAQ,CAAC,MAAM,QAAQ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;AACxE,CAAC,CAAC,CAAA;AAEW,QAAA,iBAAiB,GAAG,IAAA,wBAAe,EAA0C,KAAK,EAAE,IAAI,EAAE,EAAE;IACvG,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAa,GAAE,CAAA;IAEpC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAO,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;IACrF,IAAI,QAAQ,IAAI,IAAI;QAAE,OAAO,gBAAgB,IAAI,CAAC,IAAI,6BAA6B,QAAQ,CAAC,GAAG,MAAM,CAAA;IAErG,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC1C,IAAI,MAAM,IAAI,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAA;IAE3E,MAAM,QAAQ,GAAG,IAAA,iBAAU,GAAe,CAAA;IAC1C,MAAM,MAAM,CAAC,SAAS,CACpB,iBAAO,CAAC,KAAK,CAAC,WAAW,EACzB,cAAI,CAAC,KAAK,CAAC,KAAK,EAChB;QACE,WAAW,EAAE,iBAAO,CAAC,SAAS,CAAC,WAAW;QAC1C,QAAQ,EAAE,MAAM,CAAC,GAAG;QACpB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;KAC3E,EACR,QAAQ,CACT,CAAA;IAED,OAAO,eAAe,IAAI,CAAC,IAAI,wBAAwB,MAAM,CAAC,KAAK,mBAAmB,QAAQ,+CAA+C,CAAA;AAC/I,CAAC,CAAC,CAAA"}
|
|
@@ -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":"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"}
|