helpdesk-app-framework-sdk 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/LICENSE +177 -0
- package/README.md +587 -0
- package/build/baf_sdk.js +2107 -0
- package/build/baf_sdk.js.map +1 -0
- package/build/baf_sdk.min.js +1 -0
- package/lib/apis/context.js +172 -0
- package/lib/apis/instance.js +225 -0
- package/lib/apis/metadata.js +156 -0
- package/lib/apis/request.js +196 -0
- package/lib/client.js +422 -0
- package/lib/index.js +99 -0
- package/lib/utils.js +202 -0
- package/package.json +95 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BoldDesk App Framework - Metadata API
|
|
3
|
+
* Provides app and installation metadata information
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class MetadataAPI {
|
|
7
|
+
constructor (data = {}) {
|
|
8
|
+
this._data = {
|
|
9
|
+
appId: data.appId || null,
|
|
10
|
+
installationId: data.installationId || null,
|
|
11
|
+
appName: data.appName || null,
|
|
12
|
+
version: data.version || null,
|
|
13
|
+
locations: data.locations || [],
|
|
14
|
+
hasAllBrandAccess: data.hasAllBrandAccess || false,
|
|
15
|
+
hasReadAccess: data.hasReadAccess || false,
|
|
16
|
+
hasWriteAccess: data.hasWriteAccess || false,
|
|
17
|
+
isActive: data.isActive || false,
|
|
18
|
+
isEnabled: data.isEnabled || false,
|
|
19
|
+
frameworkVersion: data.frameworkVersion || null,
|
|
20
|
+
installDate: data.installDate || null,
|
|
21
|
+
developer: data.developer || null
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get app ID
|
|
27
|
+
* @returns {string} App ID
|
|
28
|
+
*/
|
|
29
|
+
getAppId () {
|
|
30
|
+
return this._data.appId
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get installation ID (unique per installation)
|
|
35
|
+
* @returns {string} Installation ID
|
|
36
|
+
*/
|
|
37
|
+
getInstallationId () {
|
|
38
|
+
return this._data.installationId
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get app name
|
|
43
|
+
* @returns {string} App name
|
|
44
|
+
*/
|
|
45
|
+
getAppName () {
|
|
46
|
+
return this._data.appName
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get app version
|
|
51
|
+
* @returns {string} Version (semantic versioning)
|
|
52
|
+
*/
|
|
53
|
+
getVersion () {
|
|
54
|
+
return this._data.version
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get widget locations where app is available
|
|
59
|
+
* @returns {Array} Array of location strings
|
|
60
|
+
*/
|
|
61
|
+
getLocations () {
|
|
62
|
+
return Array.from(this._data.locations)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Check if app has all brand access
|
|
67
|
+
* @returns {boolean}
|
|
68
|
+
*/
|
|
69
|
+
hasAllBrandAccess () {
|
|
70
|
+
return this._data.hasAllBrandAccess === true
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Check if app has read permissions
|
|
75
|
+
* @returns {boolean}
|
|
76
|
+
*/
|
|
77
|
+
hasReadAccess () {
|
|
78
|
+
return this._data.hasReadAccess === true
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Check if app has write permissions
|
|
83
|
+
* @returns {boolean}
|
|
84
|
+
*/
|
|
85
|
+
hasWriteAccess () {
|
|
86
|
+
return this._data.hasWriteAccess === true
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Check if app is active
|
|
91
|
+
* @returns {boolean}
|
|
92
|
+
*/
|
|
93
|
+
isActive () {
|
|
94
|
+
return this._data.isActive === true
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Check if app is enabled
|
|
99
|
+
* @returns {boolean}
|
|
100
|
+
*/
|
|
101
|
+
isEnabled () {
|
|
102
|
+
return this._data.isEnabled === true
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Get framework version
|
|
107
|
+
* @returns {string} Framework version
|
|
108
|
+
*/
|
|
109
|
+
getFrameworkVersion () {
|
|
110
|
+
return this._data.frameworkVersion
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get installation date
|
|
115
|
+
* @returns {string} ISO date string
|
|
116
|
+
*/
|
|
117
|
+
getInstallDate () {
|
|
118
|
+
return this._data.installDate
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get developer information
|
|
123
|
+
* @returns {Object} Developer object
|
|
124
|
+
*/
|
|
125
|
+
getDeveloper () {
|
|
126
|
+
return this._data.developer ? JSON.parse(JSON.stringify(this._data.developer)) : null
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Check if location is supported
|
|
131
|
+
* @param {string} location - Location to check
|
|
132
|
+
* @returns {boolean}
|
|
133
|
+
*/
|
|
134
|
+
isLocationSupported (location) {
|
|
135
|
+
return this._data.locations.includes(location)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get all metadata
|
|
140
|
+
* @returns {Object} Full metadata object
|
|
141
|
+
*/
|
|
142
|
+
getAll () {
|
|
143
|
+
return JSON.parse(JSON.stringify(this._data))
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Update metadata (internal use)
|
|
148
|
+
* @param {Object} data - New data to merge
|
|
149
|
+
* @internal
|
|
150
|
+
*/
|
|
151
|
+
_updateData (data) {
|
|
152
|
+
Object.assign(this._data, data)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export default MetadataAPI
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BoldDesk App Framework - Request API (Proxy)
|
|
3
|
+
* Provides secure HTTP request capability through server-side proxy
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { isObject, isString, isValidUrl } from '../utils'
|
|
7
|
+
|
|
8
|
+
class RequestAPI {
|
|
9
|
+
constructor (client) {
|
|
10
|
+
this._client = client
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Make an HTTP request through BoldDesk proxy
|
|
15
|
+
* Prevents exposing sensitive data and handles CORS automatically
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} options - Request options
|
|
18
|
+
* @param {string} options.url - Full URL of the API endpoint (required)
|
|
19
|
+
* @param {string} options.method - HTTP method (GET, POST, PUT, DELETE, PATCH) (required)
|
|
20
|
+
* @param {Object} options.headers - HTTP headers (optional)
|
|
21
|
+
* @param {Object} options.params - Query parameters (optional)
|
|
22
|
+
* @param {Object|string} options.body - Request payload (optional, for POST/PUT/PATCH)
|
|
23
|
+
* @param {number} options.timeout - Request timeout in ms (optional, default: 15000, max: 30000)
|
|
24
|
+
* @param {boolean} options.autoRetry - Auto-retry on 429/5xx (optional, default: true)
|
|
25
|
+
* @param {number} options.maxRetry - Max retry attempts (optional, default: 3)
|
|
26
|
+
* @param {number} options.retryDelay - Delay between retries in ms (optional, default: 1000)
|
|
27
|
+
*
|
|
28
|
+
* @returns {Promise} Resolves with response object { status, statusText, headers, data, body }
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // Simple GET request
|
|
32
|
+
* sdk.request({
|
|
33
|
+
* url: 'https://api.example.com/users',
|
|
34
|
+
* method: 'GET'
|
|
35
|
+
* }).then(response => console.log(response.data))
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // POST with data
|
|
39
|
+
* sdk.request({
|
|
40
|
+
* url: 'https://api.example.com/tickets',
|
|
41
|
+
* method: 'POST',
|
|
42
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
43
|
+
* body: JSON.stringify({ subject: 'Help needed', priority: 'high' })
|
|
44
|
+
* })
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // Using secure settings placeholders
|
|
48
|
+
* sdk.request({
|
|
49
|
+
* url: 'https://api.example.com/secure-endpoint',
|
|
50
|
+
* method: 'GET',
|
|
51
|
+
* headers: { 'Authorization': 'Bearer {{setting.api_key}}' }
|
|
52
|
+
* })
|
|
53
|
+
*/
|
|
54
|
+
request (options = {}) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
try {
|
|
57
|
+
// Validate required options
|
|
58
|
+
if (!options.url) {
|
|
59
|
+
throw new Error('Request URL is required')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!options.method) {
|
|
63
|
+
throw new Error('Request method is required')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Validate URL format
|
|
67
|
+
if (!isValidUrl(options.url)) {
|
|
68
|
+
throw new Error('Invalid URL format: ' + options.url)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Validate method
|
|
72
|
+
const validMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']
|
|
73
|
+
const method = (options.method || 'GET').toUpperCase()
|
|
74
|
+
if (!validMethods.includes(method)) {
|
|
75
|
+
throw new Error('Invalid HTTP method: ' + method)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Build request object
|
|
79
|
+
const requestObj = {
|
|
80
|
+
url: options.url,
|
|
81
|
+
method,
|
|
82
|
+
headers: options.headers || {},
|
|
83
|
+
timeout: Math.min(options.timeout || 15000, 30000),
|
|
84
|
+
autoRetry: options.autoRetry !== false,
|
|
85
|
+
maxRetry: options.maxRetry || 3,
|
|
86
|
+
retryDelay: options.retryDelay || 1000
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Add query parameters if provided
|
|
90
|
+
if (options.params && isObject(options.params)) {
|
|
91
|
+
const params = new URLSearchParams(options.params)
|
|
92
|
+
const separator = options.url.includes('?') ? '&' : '?'
|
|
93
|
+
requestObj.url += separator + params.toString()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Add body for POST/PUT/PATCH
|
|
97
|
+
if (['POST', 'PUT', 'PATCH'].includes(method)) {
|
|
98
|
+
if (options.body) {
|
|
99
|
+
requestObj.body = isObject(options.body)
|
|
100
|
+
? JSON.stringify(options.body)
|
|
101
|
+
: options.body
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Send request through BoldDesk proxy
|
|
106
|
+
this._client.postMessage('request.send', requestObj, (response) => {
|
|
107
|
+
if (response.error) {
|
|
108
|
+
reject(new Error(response.error))
|
|
109
|
+
} else {
|
|
110
|
+
resolve(response)
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
} catch (error) {
|
|
114
|
+
reject(error)
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Make a GET request
|
|
121
|
+
* @param {string} url - URL endpoint
|
|
122
|
+
* @param {Object} options - Additional options
|
|
123
|
+
* @returns {Promise}
|
|
124
|
+
*/
|
|
125
|
+
get (url, options = {}) {
|
|
126
|
+
return this.request({
|
|
127
|
+
...options,
|
|
128
|
+
url,
|
|
129
|
+
method: 'GET'
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Make a POST request
|
|
135
|
+
* @param {string} url - URL endpoint
|
|
136
|
+
* @param {*} body - Request body
|
|
137
|
+
* @param {Object} options - Additional options
|
|
138
|
+
* @returns {Promise}
|
|
139
|
+
*/
|
|
140
|
+
post (url, body, options = {}) {
|
|
141
|
+
return this.request({
|
|
142
|
+
...options,
|
|
143
|
+
url,
|
|
144
|
+
method: 'POST',
|
|
145
|
+
body
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Make a PUT request
|
|
151
|
+
* @param {string} url - URL endpoint
|
|
152
|
+
* @param {*} body - Request body
|
|
153
|
+
* @param {Object} options - Additional options
|
|
154
|
+
* @returns {Promise}
|
|
155
|
+
*/
|
|
156
|
+
put (url, body, options = {}) {
|
|
157
|
+
return this.request({
|
|
158
|
+
...options,
|
|
159
|
+
url,
|
|
160
|
+
method: 'PUT',
|
|
161
|
+
body
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Make a PATCH request
|
|
167
|
+
* @param {string} url - URL endpoint
|
|
168
|
+
* @param {*} body - Request body
|
|
169
|
+
* @param {Object} options - Additional options
|
|
170
|
+
* @returns {Promise}
|
|
171
|
+
*/
|
|
172
|
+
patch (url, body, options = {}) {
|
|
173
|
+
return this.request({
|
|
174
|
+
...options,
|
|
175
|
+
url,
|
|
176
|
+
method: 'PATCH',
|
|
177
|
+
body
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Make a DELETE request
|
|
183
|
+
* @param {string} url - URL endpoint
|
|
184
|
+
* @param {Object} options - Additional options
|
|
185
|
+
* @returns {Promise}
|
|
186
|
+
*/
|
|
187
|
+
delete (url, options = {}) {
|
|
188
|
+
return this.request({
|
|
189
|
+
...options,
|
|
190
|
+
url,
|
|
191
|
+
method: 'DELETE'
|
|
192
|
+
})
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export default RequestAPI
|