@gongrzhe/server-jira 0.1.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/README.md +374 -0
- package/dist/common/context.d.ts +15 -0
- package/dist/common/context.d.ts.map +1 -0
- package/dist/common/context.js +33 -0
- package/dist/common/context.js.map +1 -0
- package/dist/common/errors.d.ts +26 -0
- package/dist/common/errors.d.ts.map +1 -0
- package/dist/common/errors.js +71 -0
- package/dist/common/errors.js.map +1 -0
- package/dist/common/token-parser.d.ts +53 -0
- package/dist/common/token-parser.d.ts.map +1 -0
- package/dist/common/token-parser.js +117 -0
- package/dist/common/token-parser.js.map +1 -0
- package/dist/common/types.d.ts +151 -0
- package/dist/common/types.d.ts.map +1 -0
- package/dist/common/types.js +2 -0
- package/dist/common/types.js.map +1 -0
- package/dist/common/utils.d.ts +9 -0
- package/dist/common/utils.d.ts.map +1 -0
- package/dist/common/utils.js +116 -0
- package/dist/common/utils.js.map +1 -0
- package/dist/common/version.d.ts +2 -0
- package/dist/common/version.d.ts.map +1 -0
- package/dist/common/version.js +3 -0
- package/dist/common/version.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +505 -0
- package/dist/index.js.map +1 -0
- package/dist/operations/atlassian.d.ts +27 -0
- package/dist/operations/atlassian.d.ts.map +1 -0
- package/dist/operations/atlassian.js +27 -0
- package/dist/operations/atlassian.js.map +1 -0
- package/dist/operations/comments.d.ts +117 -0
- package/dist/operations/comments.d.ts.map +1 -0
- package/dist/operations/comments.js +153 -0
- package/dist/operations/comments.js.map +1 -0
- package/dist/operations/issues.d.ts +146 -0
- package/dist/operations/issues.d.ts.map +1 -0
- package/dist/operations/issues.js +250 -0
- package/dist/operations/issues.js.map +1 -0
- package/dist/operations/metadata.d.ts +176 -0
- package/dist/operations/metadata.d.ts.map +1 -0
- package/dist/operations/metadata.js +143 -0
- package/dist/operations/metadata.js.map +1 -0
- package/dist/operations/projects.d.ts +159 -0
- package/dist/operations/projects.d.ts.map +1 -0
- package/dist/operations/projects.js +175 -0
- package/dist/operations/projects.js.map +1 -0
- package/dist/operations/users.d.ts +130 -0
- package/dist/operations/users.d.ts.map +1 -0
- package/dist/operations/users.js +214 -0
- package/dist/operations/users.js.map +1 -0
- package/dist/operations/workflow.d.ts +110 -0
- package/dist/operations/workflow.d.ts.map +1 -0
- package/dist/operations/workflow.js +203 -0
- package/dist/operations/workflow.js.map +1 -0
- package/dist/operations/worklog.d.ts +175 -0
- package/dist/operations/worklog.d.ts.map +1 -0
- package/dist/operations/worklog.js +322 -0
- package/dist/operations/worklog.js.map +1 -0
- package/dist/test-token-discovery.d.ts +6 -0
- package/dist/test-token-discovery.d.ts.map +1 -0
- package/dist/test-token-discovery.js +26 -0
- package/dist/test-token-discovery.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jira Token Parser
|
|
3
|
+
*
|
|
4
|
+
* Extracts Jira site information from API tokens by making a discovery call
|
|
5
|
+
* to the Jira API to determine the accessible sites for the given token.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Get accessible Jira sites for the given API token
|
|
9
|
+
* This calls the Atlassian API to discover which Jira instances the token has access to
|
|
10
|
+
*/
|
|
11
|
+
export async function getAccessibleSites(apiToken) {
|
|
12
|
+
try {
|
|
13
|
+
// Use Atlassian's OAuth 2.0 accessible resources endpoint
|
|
14
|
+
const response = await fetch('https://api.atlassian.com/oauth/token/accessible-resources', {
|
|
15
|
+
method: 'GET',
|
|
16
|
+
headers: {
|
|
17
|
+
'Authorization': `Bearer ${apiToken}`,
|
|
18
|
+
'Accept': 'application/json',
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
const errorText = await response.text();
|
|
23
|
+
throw new Error(`Failed to get accessible sites: ${response.status} ${errorText}`);
|
|
24
|
+
}
|
|
25
|
+
const sites = await response.json();
|
|
26
|
+
return sites;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
throw new Error(`Failed to discover Jira sites from token: ${error instanceof Error ? error.message : String(error)}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the primary/first Jira site URL from the API token
|
|
34
|
+
* This is the recommended approach for single-site users
|
|
35
|
+
*/
|
|
36
|
+
export async function getJiraUrlFromToken(apiToken) {
|
|
37
|
+
const sites = await getAccessibleSites(apiToken);
|
|
38
|
+
if (!sites || sites.length === 0) {
|
|
39
|
+
throw new Error('No accessible Jira sites found for this token. Please verify your token has Jira access.');
|
|
40
|
+
}
|
|
41
|
+
// Return the first site's URL
|
|
42
|
+
const primarySite = sites[0];
|
|
43
|
+
return primarySite.url;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the cloud ID from the API token
|
|
47
|
+
* Cloud ID is required for OAuth 2.0 tokens to use the Atlassian API Gateway
|
|
48
|
+
*/
|
|
49
|
+
export async function getCloudIdFromToken(apiToken) {
|
|
50
|
+
const sites = await getAccessibleSites(apiToken);
|
|
51
|
+
if (!sites || sites.length === 0) {
|
|
52
|
+
throw new Error('No accessible Jira sites found for this token. Please verify your token has Jira access.');
|
|
53
|
+
}
|
|
54
|
+
// Return the first site's cloud ID
|
|
55
|
+
const primarySite = sites[0];
|
|
56
|
+
return primarySite.id;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get both URL and cloud ID from token
|
|
60
|
+
*/
|
|
61
|
+
export async function getSiteInfoFromToken(apiToken) {
|
|
62
|
+
const sites = await getAccessibleSites(apiToken);
|
|
63
|
+
if (!sites || sites.length === 0) {
|
|
64
|
+
throw new Error('No accessible Jira sites found for this token. Please verify your token has Jira access.');
|
|
65
|
+
}
|
|
66
|
+
const primarySite = sites[0];
|
|
67
|
+
return {
|
|
68
|
+
url: primarySite.url,
|
|
69
|
+
cloudId: primarySite.id,
|
|
70
|
+
name: primarySite.name,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Cache for storing token -> site info mappings to avoid repeated API calls
|
|
75
|
+
*/
|
|
76
|
+
const tokenCache = new Map();
|
|
77
|
+
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
78
|
+
/**
|
|
79
|
+
* Get Jira site info from token with caching
|
|
80
|
+
*/
|
|
81
|
+
export async function getCachedSiteInfo(apiToken) {
|
|
82
|
+
// Check cache first
|
|
83
|
+
const cached = tokenCache.get(apiToken);
|
|
84
|
+
const now = Date.now();
|
|
85
|
+
if (cached && (now - cached.timestamp) < CACHE_TTL) {
|
|
86
|
+
return cached.siteInfo;
|
|
87
|
+
}
|
|
88
|
+
// Fetch fresh site info
|
|
89
|
+
const siteInfo = await getSiteInfoFromToken(apiToken);
|
|
90
|
+
// Update cache
|
|
91
|
+
tokenCache.set(apiToken, { siteInfo, timestamp: now });
|
|
92
|
+
// Clean old cache entries (simple cleanup)
|
|
93
|
+
if (tokenCache.size > 1000) {
|
|
94
|
+
const entriesToDelete = [];
|
|
95
|
+
tokenCache.forEach((value, key) => {
|
|
96
|
+
if (now - value.timestamp > CACHE_TTL) {
|
|
97
|
+
entriesToDelete.push(key);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
entriesToDelete.forEach(key => tokenCache.delete(key));
|
|
101
|
+
}
|
|
102
|
+
return siteInfo;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get Jira URL from token with caching (backward compatibility)
|
|
106
|
+
*/
|
|
107
|
+
export async function getCachedJiraUrl(apiToken) {
|
|
108
|
+
const siteInfo = await getCachedSiteInfo(apiToken);
|
|
109
|
+
return siteInfo.url;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Clear the token cache (useful for testing)
|
|
113
|
+
*/
|
|
114
|
+
export function clearTokenCache() {
|
|
115
|
+
tokenCache.clear();
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=token-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-parser.js","sourceRoot":"","sources":["../../common/token-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
export interface JiraIssue {
|
|
2
|
+
id: string;
|
|
3
|
+
key: string;
|
|
4
|
+
self: string;
|
|
5
|
+
fields: {
|
|
6
|
+
summary: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
status: {
|
|
9
|
+
name: string;
|
|
10
|
+
id: string;
|
|
11
|
+
statusCategory: {
|
|
12
|
+
key: string;
|
|
13
|
+
name: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
issuetype: {
|
|
17
|
+
name: string;
|
|
18
|
+
id: string;
|
|
19
|
+
iconUrl?: string;
|
|
20
|
+
};
|
|
21
|
+
priority?: {
|
|
22
|
+
name: string;
|
|
23
|
+
id: string;
|
|
24
|
+
};
|
|
25
|
+
assignee?: {
|
|
26
|
+
displayName: string;
|
|
27
|
+
accountId: string;
|
|
28
|
+
emailAddress?: string;
|
|
29
|
+
};
|
|
30
|
+
reporter: {
|
|
31
|
+
displayName: string;
|
|
32
|
+
accountId: string;
|
|
33
|
+
emailAddress?: string;
|
|
34
|
+
};
|
|
35
|
+
created: string;
|
|
36
|
+
updated: string;
|
|
37
|
+
project: {
|
|
38
|
+
key: string;
|
|
39
|
+
name: string;
|
|
40
|
+
id: string;
|
|
41
|
+
};
|
|
42
|
+
labels?: string[];
|
|
43
|
+
components?: Array<{
|
|
44
|
+
name: string;
|
|
45
|
+
id: string;
|
|
46
|
+
}>;
|
|
47
|
+
fixVersions?: Array<{
|
|
48
|
+
name: string;
|
|
49
|
+
id: string;
|
|
50
|
+
}>;
|
|
51
|
+
[key: string]: any;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export interface JiraProject {
|
|
55
|
+
id: string;
|
|
56
|
+
key: string;
|
|
57
|
+
name: string;
|
|
58
|
+
projectTypeKey: string;
|
|
59
|
+
simplified: boolean;
|
|
60
|
+
style: string;
|
|
61
|
+
isPrivate: boolean;
|
|
62
|
+
lead?: {
|
|
63
|
+
displayName: string;
|
|
64
|
+
accountId: string;
|
|
65
|
+
};
|
|
66
|
+
description?: string;
|
|
67
|
+
url?: string;
|
|
68
|
+
avatarUrls?: {
|
|
69
|
+
[size: string]: string;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export interface JiraComment {
|
|
73
|
+
id: string;
|
|
74
|
+
author: {
|
|
75
|
+
displayName: string;
|
|
76
|
+
accountId: string;
|
|
77
|
+
emailAddress?: string;
|
|
78
|
+
};
|
|
79
|
+
body: string;
|
|
80
|
+
created: string;
|
|
81
|
+
updated: string;
|
|
82
|
+
visibility?: {
|
|
83
|
+
type: string;
|
|
84
|
+
value: string;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
export interface JiraTransition {
|
|
88
|
+
id: string;
|
|
89
|
+
name: string;
|
|
90
|
+
to: {
|
|
91
|
+
name: string;
|
|
92
|
+
id: string;
|
|
93
|
+
statusCategory: {
|
|
94
|
+
key: string;
|
|
95
|
+
name: string;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
fields?: {
|
|
99
|
+
[key: string]: {
|
|
100
|
+
required: boolean;
|
|
101
|
+
schema: any;
|
|
102
|
+
name: string;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export interface JiraUser {
|
|
107
|
+
accountId: string;
|
|
108
|
+
displayName: string;
|
|
109
|
+
emailAddress?: string;
|
|
110
|
+
avatarUrls?: {
|
|
111
|
+
[size: string]: string;
|
|
112
|
+
};
|
|
113
|
+
active: boolean;
|
|
114
|
+
}
|
|
115
|
+
export interface JiraSearchResults {
|
|
116
|
+
startAt: number;
|
|
117
|
+
maxResults: number;
|
|
118
|
+
total: number;
|
|
119
|
+
issues: JiraIssue[];
|
|
120
|
+
}
|
|
121
|
+
export interface JiraWorklog {
|
|
122
|
+
id: string;
|
|
123
|
+
author: {
|
|
124
|
+
displayName: string;
|
|
125
|
+
accountId: string;
|
|
126
|
+
};
|
|
127
|
+
timeSpent: string;
|
|
128
|
+
timeSpentSeconds: number;
|
|
129
|
+
started: string;
|
|
130
|
+
comment?: string;
|
|
131
|
+
}
|
|
132
|
+
export interface JiraFieldOption {
|
|
133
|
+
id: string;
|
|
134
|
+
value: string;
|
|
135
|
+
self?: string;
|
|
136
|
+
}
|
|
137
|
+
export interface JiraField {
|
|
138
|
+
id: string;
|
|
139
|
+
name: string;
|
|
140
|
+
custom: boolean;
|
|
141
|
+
schema: {
|
|
142
|
+
type: string;
|
|
143
|
+
system?: string;
|
|
144
|
+
custom?: string;
|
|
145
|
+
customId?: number;
|
|
146
|
+
};
|
|
147
|
+
searchable: boolean;
|
|
148
|
+
navigable: boolean;
|
|
149
|
+
orderable: boolean;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../common/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../common/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function normalizeJiraUrl(url: string): string;
|
|
2
|
+
export declare function createAuthHeaders(): Record<string, string>;
|
|
3
|
+
export declare function jiraRequest<T = any>(endpoint: string, options?: RequestInit): Promise<T>;
|
|
4
|
+
export declare function formatJQL(jql: string): string;
|
|
5
|
+
export declare function validateIssueKey(issueKey: string): boolean;
|
|
6
|
+
export declare function formatJiraDate(date: Date | string): string;
|
|
7
|
+
export declare function parseJiraErrors(errors: any): string[];
|
|
8
|
+
export declare function truncateText(text: string, maxLength?: number): string;
|
|
9
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../common/utils.ts"],"names":[],"mappings":"AAIA,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiBpD;AAGD,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAS1D;AAyBD,wBAAsB,WAAW,CAAC,CAAC,GAAG,GAAG,EACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,CAAC,CAAC,CAoCZ;AAGD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAGD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1D;AAGD,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAE1D;AAGD,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,EAAE,CAcrD;AAGD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAY,GAAG,MAAM,CAG1E"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { requireAuthToken, requireJiraUrl, getCloudId } from './context.js';
|
|
2
|
+
import { createJiraErrorFromResponse, JiraError } from './errors.js';
|
|
3
|
+
// Validate and normalize JIRA URL
|
|
4
|
+
export function normalizeJiraUrl(url) {
|
|
5
|
+
if (!url) {
|
|
6
|
+
throw new Error("JIRA URL is required");
|
|
7
|
+
}
|
|
8
|
+
// Basic URL validation
|
|
9
|
+
try {
|
|
10
|
+
const urlObj = new URL(url);
|
|
11
|
+
if (!urlObj.protocol.startsWith('http')) {
|
|
12
|
+
throw new Error("JIRA URL must use http or https protocol");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
throw new Error(`Invalid JIRA URL: ${url}`);
|
|
17
|
+
}
|
|
18
|
+
// Remove trailing slash
|
|
19
|
+
return url.replace(/\/$/, '');
|
|
20
|
+
}
|
|
21
|
+
// Create authenticated headers for JIRA API requests
|
|
22
|
+
export function createAuthHeaders() {
|
|
23
|
+
const token = requireAuthToken();
|
|
24
|
+
return {
|
|
25
|
+
'Content-Type': 'application/json',
|
|
26
|
+
'Accept': 'application/json',
|
|
27
|
+
'User-Agent': 'mcp-server-jira/0.1.0',
|
|
28
|
+
'Authorization': `Bearer ${token}`,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Build the correct Jira API URL
|
|
33
|
+
*
|
|
34
|
+
* For OAuth 2.0 tokens (when cloudId is available):
|
|
35
|
+
* Uses Atlassian API Gateway: https://api.atlassian.com/ex/jira/{cloudId}/rest/api/2/...
|
|
36
|
+
*
|
|
37
|
+
* For API tokens (no cloudId):
|
|
38
|
+
* Uses direct URL: https://your-instance.atlassian.net/rest/api/2/...
|
|
39
|
+
*/
|
|
40
|
+
function buildJiraApiUrl(endpoint) {
|
|
41
|
+
const cloudId = getCloudId();
|
|
42
|
+
if (cloudId) {
|
|
43
|
+
// OAuth 2.0 - use Atlassian API Gateway
|
|
44
|
+
return `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/2/${endpoint}`;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// API Token - use direct instance URL
|
|
48
|
+
const baseUrl = normalizeJiraUrl(requireJiraUrl());
|
|
49
|
+
return `${baseUrl}/rest/api/2/${endpoint}`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Generic JIRA API request wrapper
|
|
53
|
+
export async function jiraRequest(endpoint, options = {}) {
|
|
54
|
+
const url = buildJiraApiUrl(endpoint);
|
|
55
|
+
const headers = {
|
|
56
|
+
...createAuthHeaders(),
|
|
57
|
+
...options.headers,
|
|
58
|
+
};
|
|
59
|
+
try {
|
|
60
|
+
const response = await fetch(url, {
|
|
61
|
+
...options,
|
|
62
|
+
headers,
|
|
63
|
+
});
|
|
64
|
+
let responseBody;
|
|
65
|
+
const contentType = response.headers.get('content-type');
|
|
66
|
+
if (contentType?.includes('application/json')) {
|
|
67
|
+
responseBody = await response.json();
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
responseBody = await response.text();
|
|
71
|
+
}
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
throw createJiraErrorFromResponse(response, responseBody);
|
|
74
|
+
}
|
|
75
|
+
return responseBody;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (error instanceof JiraError) {
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
// Network or other errors
|
|
82
|
+
throw new Error(`Failed to make JIRA API request: ${error instanceof Error ? error.message : String(error)}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Format JQL query safely
|
|
86
|
+
export function formatJQL(jql) {
|
|
87
|
+
return jql.trim();
|
|
88
|
+
}
|
|
89
|
+
// Validate issue key format
|
|
90
|
+
export function validateIssueKey(issueKey) {
|
|
91
|
+
return /^[A-Z][A-Z0-9]*-\d+$/.test(issueKey);
|
|
92
|
+
}
|
|
93
|
+
// Format JIRA date (ISO format)
|
|
94
|
+
export function formatJiraDate(date) {
|
|
95
|
+
return date instanceof Date ? date.toISOString() : date;
|
|
96
|
+
}
|
|
97
|
+
// Parse JIRA error messages
|
|
98
|
+
export function parseJiraErrors(errors) {
|
|
99
|
+
const errorMessages = [];
|
|
100
|
+
if (errors.errorMessages && Array.isArray(errors.errorMessages)) {
|
|
101
|
+
errorMessages.push(...errors.errorMessages);
|
|
102
|
+
}
|
|
103
|
+
if (errors.errors && typeof errors.errors === 'object') {
|
|
104
|
+
for (const [field, message] of Object.entries(errors.errors)) {
|
|
105
|
+
errorMessages.push(`${field}: ${message}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return errorMessages.length > 0 ? errorMessages : ['Unknown error occurred'];
|
|
109
|
+
}
|
|
110
|
+
// Truncate long text for display
|
|
111
|
+
export function truncateText(text, maxLength = 200) {
|
|
112
|
+
if (text.length <= maxLength)
|
|
113
|
+
return text;
|
|
114
|
+
return text.substring(0, maxLength - 3) + '...';
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../common/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../common/version.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../common/version.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":""}
|