@magentrix-corp/magentrix-cli 1.3.15 → 1.3.17
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 +25 -25
- package/README.md +1166 -1166
- package/actions/autopublish.old.js +293 -293
- package/actions/config.js +182 -182
- package/actions/create.js +466 -466
- package/actions/help.js +164 -164
- package/actions/iris/buildStage.js +874 -874
- package/actions/iris/delete.js +256 -256
- package/actions/iris/dev.js +391 -391
- package/actions/iris/index.js +6 -6
- package/actions/iris/link.js +375 -375
- package/actions/iris/recover.js +268 -268
- package/actions/main.js +80 -80
- package/actions/publish.js +1420 -1420
- package/actions/pull.js +684 -684
- package/actions/setup.js +148 -148
- package/actions/status.js +17 -17
- package/actions/update.js +248 -248
- package/bin/magentrix.js +393 -393
- package/package.json +55 -55
- package/utils/assetPaths.js +158 -158
- package/utils/autopublishLock.js +77 -77
- package/utils/cacher.js +206 -206
- package/utils/cli/checkInstanceUrl.js +76 -45
- package/utils/cli/helpers/compare.js +282 -282
- package/utils/cli/helpers/ensureApiKey.js +63 -63
- package/utils/cli/helpers/ensureCredentials.js +68 -68
- package/utils/cli/helpers/ensureInstanceUrl.js +75 -75
- package/utils/cli/writeRecords.js +262 -262
- package/utils/compare.js +135 -135
- package/utils/compress.js +17 -17
- package/utils/config.js +527 -527
- package/utils/debug.js +144 -144
- package/utils/diagnostics/testPublishLogic.js +96 -96
- package/utils/diff.js +49 -49
- package/utils/downloadAssets.js +291 -291
- package/utils/filetag.js +115 -115
- package/utils/hash.js +14 -14
- package/utils/iris/backup.js +411 -411
- package/utils/iris/builder.js +541 -541
- package/utils/iris/config-reader.js +664 -664
- package/utils/iris/deleteHelper.js +150 -150
- package/utils/iris/errors.js +537 -537
- package/utils/iris/linker.js +601 -601
- package/utils/iris/lock.js +360 -360
- package/utils/iris/validation.js +360 -360
- package/utils/iris/validator.js +281 -281
- package/utils/iris/zipper.js +248 -248
- package/utils/logger.js +291 -291
- package/utils/magentrix/api/assets.js +220 -220
- package/utils/magentrix/api/auth.js +107 -107
- package/utils/magentrix/api/createEntity.js +61 -61
- package/utils/magentrix/api/deleteEntity.js +55 -55
- package/utils/magentrix/api/iris.js +251 -251
- package/utils/magentrix/api/meqlQuery.js +36 -36
- package/utils/magentrix/api/retrieveEntity.js +86 -86
- package/utils/magentrix/api/updateEntity.js +66 -66
- package/utils/magentrix/fetch.js +168 -168
- package/utils/merge.js +22 -22
- package/utils/permissionError.js +70 -70
- package/utils/preferences.js +40 -40
- package/utils/progress.js +469 -469
- package/utils/spinner.js +43 -43
- package/utils/template.js +52 -52
- package/utils/updateFileBase.js +121 -121
- package/utils/workspaces.js +108 -108
- package/vars/config.js +11 -11
- package/vars/global.js +50 -50
|
@@ -1,251 +1,251 @@
|
|
|
1
|
-
import { fetchMagentrix } from "../fetch.js";
|
|
2
|
-
import { File } from "node:buffer";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* List all deployed Iris applications.
|
|
6
|
-
* @param {string} instanceUrl - Magentrix instance base URL
|
|
7
|
-
* @param {string} token - OAuth2 bearer token
|
|
8
|
-
* @returns {Promise<{success: boolean, apps: Array<{folderName: string, uploadedOn: string, modifiedOn: string, size: number}>}>}
|
|
9
|
-
*/
|
|
10
|
-
export const listApps = async (instanceUrl, token) => {
|
|
11
|
-
if (!instanceUrl || !token) {
|
|
12
|
-
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const response = await fetchMagentrix({
|
|
16
|
-
instanceUrl,
|
|
17
|
-
token,
|
|
18
|
-
path: '/iris/listapps',
|
|
19
|
-
method: 'GET',
|
|
20
|
-
returnErrorObject: true
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
return response;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Publish (upload) an Iris Vue.js application.
|
|
28
|
-
* @param {string} instanceUrl - Magentrix instance base URL
|
|
29
|
-
* @param {string} token - OAuth2 bearer token
|
|
30
|
-
* @param {Buffer} zipBuffer - The zip file as a Buffer
|
|
31
|
-
* @param {string} filename - The filename for the zip (e.g., "my-app.zip")
|
|
32
|
-
* @param {string} appName - The user-friendly display name (required for navigation)
|
|
33
|
-
* @param {Object} options - Optional parameters
|
|
34
|
-
* @param {string} [options.appDescription] - App description
|
|
35
|
-
* @param {string} [options.appIconId] - App icon ID
|
|
36
|
-
* @returns {Promise<{success: boolean, message: string, folderName: string}>}
|
|
37
|
-
*/
|
|
38
|
-
export const publishApp = async (instanceUrl, token, zipBuffer, filename, appName, options = {}) => {
|
|
39
|
-
if (!instanceUrl || !token) {
|
|
40
|
-
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (!zipBuffer || !Buffer.isBuffer(zipBuffer)) {
|
|
44
|
-
throw new Error('zipBuffer must be a valid Buffer');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (!filename) {
|
|
48
|
-
throw new Error('filename is required');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Create a File object from the buffer for FormData
|
|
52
|
-
const file = new File([zipBuffer], filename, { type: 'application/zip' });
|
|
53
|
-
|
|
54
|
-
const formData = new FormData();
|
|
55
|
-
formData.append('file', file);
|
|
56
|
-
|
|
57
|
-
// Build query parameters
|
|
58
|
-
// Note: app-name is only sent when provided (required for creates, optional for updates)
|
|
59
|
-
// Sending app-name on updates can trigger a rename attempt that fails if the user
|
|
60
|
-
// lacks metadata-edit permissions on the server
|
|
61
|
-
const params = new URLSearchParams();
|
|
62
|
-
|
|
63
|
-
if (appName) {
|
|
64
|
-
params.append('app-name', appName);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (options.appDescription) {
|
|
68
|
-
params.append('app-description', options.appDescription);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (options.appIconId) {
|
|
72
|
-
params.append('app-icon-id', options.appIconId);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const response = await fetchMagentrix({
|
|
76
|
-
instanceUrl,
|
|
77
|
-
token,
|
|
78
|
-
path: `/iris/publishapp?${params.toString()}`,
|
|
79
|
-
method: 'POST',
|
|
80
|
-
body: formData,
|
|
81
|
-
ignoreContentType: true,
|
|
82
|
-
returnErrorObject: true
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
return response;
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Delete an Iris application.
|
|
90
|
-
* @param {string} instanceUrl - Magentrix instance base URL
|
|
91
|
-
* @param {string} token - OAuth2 bearer token
|
|
92
|
-
* @param {string} folderName - The folder name of the app to delete
|
|
93
|
-
* @returns {Promise<{success: boolean, message: string}>}
|
|
94
|
-
*/
|
|
95
|
-
export const deleteApp = async (instanceUrl, token, folderName) => {
|
|
96
|
-
if (!instanceUrl || !token) {
|
|
97
|
-
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (!folderName) {
|
|
101
|
-
throw new Error('folderName is required');
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const response = await fetchMagentrix({
|
|
105
|
-
instanceUrl,
|
|
106
|
-
token,
|
|
107
|
-
path: `/iris/deleteapp?folderName=${encodeURIComponent(folderName)}`,
|
|
108
|
-
method: 'POST',
|
|
109
|
-
returnErrorObject: true
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
return response;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Download a single Iris application as a buffer.
|
|
117
|
-
* @param {string} instanceUrl - Magentrix instance base URL
|
|
118
|
-
* @param {string} token - OAuth2 bearer token
|
|
119
|
-
* @param {string} folderName - The folder name of the app to download
|
|
120
|
-
* @returns {Promise<{buffer: Buffer, filename: string}>}
|
|
121
|
-
*/
|
|
122
|
-
export const downloadApp = async (instanceUrl, token, folderName) => {
|
|
123
|
-
if (!instanceUrl || !token) {
|
|
124
|
-
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (!folderName) {
|
|
128
|
-
throw new Error('folderName is required');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const url = `${instanceUrl.replace(/\/$/, '')}/iris/downloadapp?folderName=${encodeURIComponent(folderName)}`;
|
|
132
|
-
|
|
133
|
-
const response = await fetch(url, {
|
|
134
|
-
method: 'GET',
|
|
135
|
-
headers: {
|
|
136
|
-
'Authorization': `Bearer ${token}`
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
if (!response.ok) {
|
|
141
|
-
let errorMessage = `Download failed (${response.status})`;
|
|
142
|
-
try {
|
|
143
|
-
const errorData = await response.json();
|
|
144
|
-
if (errorData.message) {
|
|
145
|
-
errorMessage = errorData.message;
|
|
146
|
-
}
|
|
147
|
-
} catch {
|
|
148
|
-
errorMessage = `Download failed: ${response.statusText}`;
|
|
149
|
-
}
|
|
150
|
-
throw new Error(errorMessage);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Get filename from Content-Disposition header
|
|
154
|
-
const contentDisposition = response.headers.get('content-disposition') || '';
|
|
155
|
-
const filenameMatch = /filename\*?=(?:UTF-8'')?["']?([^"';]+)["']?/i.exec(contentDisposition);
|
|
156
|
-
const filename = filenameMatch ? decodeURIComponent(filenameMatch[1]) : `${folderName}.zip`;
|
|
157
|
-
|
|
158
|
-
const arrayBuffer = await response.arrayBuffer();
|
|
159
|
-
const buffer = Buffer.from(arrayBuffer);
|
|
160
|
-
|
|
161
|
-
return { buffer, filename };
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Download all Iris applications as a single zip buffer.
|
|
166
|
-
* @param {string} instanceUrl - Magentrix instance base URL
|
|
167
|
-
* @param {string} token - OAuth2 bearer token
|
|
168
|
-
* @returns {Promise<{buffer: Buffer, filename: string}>}
|
|
169
|
-
*/
|
|
170
|
-
export const downloadAllApps = async (instanceUrl, token) => {
|
|
171
|
-
if (!instanceUrl || !token) {
|
|
172
|
-
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const url = `${instanceUrl.replace(/\/$/, '')}/iris/downloadallapps`;
|
|
176
|
-
|
|
177
|
-
const response = await fetch(url, {
|
|
178
|
-
method: 'GET',
|
|
179
|
-
headers: {
|
|
180
|
-
'Authorization': `Bearer ${token}`
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
if (!response.ok) {
|
|
185
|
-
let errorMessage = `Download failed (${response.status})`;
|
|
186
|
-
try {
|
|
187
|
-
const errorData = await response.json();
|
|
188
|
-
if (errorData.message) {
|
|
189
|
-
errorMessage = errorData.message;
|
|
190
|
-
}
|
|
191
|
-
} catch {
|
|
192
|
-
errorMessage = `Download failed: ${response.statusText}`;
|
|
193
|
-
}
|
|
194
|
-
throw new Error(errorMessage);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Get filename from Content-Disposition header
|
|
198
|
-
const contentDisposition = response.headers.get('content-disposition') || '';
|
|
199
|
-
const filenameMatch = /filename\*?=(?:UTF-8'')?["']?([^"';]+)["']?/i.exec(contentDisposition);
|
|
200
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
201
|
-
const filename = filenameMatch ? decodeURIComponent(filenameMatch[1]) : `iris-apps_${timestamp}.zip`;
|
|
202
|
-
|
|
203
|
-
const arrayBuffer = await response.arrayBuffer();
|
|
204
|
-
const buffer = Buffer.from(arrayBuffer);
|
|
205
|
-
|
|
206
|
-
return { buffer, filename };
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Get platform assets for local development (CSS, fonts, etc.).
|
|
211
|
-
* @param {string} siteUrl - Magentrix instance base URL (from Vue config.ts)
|
|
212
|
-
* @param {string} token - OAuth2 bearer token
|
|
213
|
-
* @returns {Promise<{success: boolean, assets: string[]}>}
|
|
214
|
-
*/
|
|
215
|
-
export const getIrisAssets = async (siteUrl, token) => {
|
|
216
|
-
if (!siteUrl) {
|
|
217
|
-
throw new Error('Missing required siteUrl');
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const url = `${siteUrl.replace(/\/$/, '')}/iris/getirisassets`;
|
|
221
|
-
|
|
222
|
-
const headers = {
|
|
223
|
-
'Accept': 'application/json'
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
// Token is optional for this endpoint (might be public)
|
|
227
|
-
if (token) {
|
|
228
|
-
headers['Authorization'] = `Bearer ${token}`;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const response = await fetch(url, {
|
|
232
|
-
method: 'GET',
|
|
233
|
-
headers
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
if (!response.ok) {
|
|
237
|
-
let errorMessage = `Failed to fetch Iris assets (${response.status})`;
|
|
238
|
-
try {
|
|
239
|
-
const errorData = await response.json();
|
|
240
|
-
if (errorData.message) {
|
|
241
|
-
errorMessage = errorData.message;
|
|
242
|
-
}
|
|
243
|
-
} catch {
|
|
244
|
-
errorMessage = `Failed to fetch Iris assets: ${response.statusText}`;
|
|
245
|
-
}
|
|
246
|
-
throw new Error(errorMessage);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const data = await response.json();
|
|
250
|
-
return data;
|
|
251
|
-
};
|
|
1
|
+
import { fetchMagentrix } from "../fetch.js";
|
|
2
|
+
import { File } from "node:buffer";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* List all deployed Iris applications.
|
|
6
|
+
* @param {string} instanceUrl - Magentrix instance base URL
|
|
7
|
+
* @param {string} token - OAuth2 bearer token
|
|
8
|
+
* @returns {Promise<{success: boolean, apps: Array<{folderName: string, uploadedOn: string, modifiedOn: string, size: number}>}>}
|
|
9
|
+
*/
|
|
10
|
+
export const listApps = async (instanceUrl, token) => {
|
|
11
|
+
if (!instanceUrl || !token) {
|
|
12
|
+
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const response = await fetchMagentrix({
|
|
16
|
+
instanceUrl,
|
|
17
|
+
token,
|
|
18
|
+
path: '/iris/listapps',
|
|
19
|
+
method: 'GET',
|
|
20
|
+
returnErrorObject: true
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return response;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Publish (upload) an Iris Vue.js application.
|
|
28
|
+
* @param {string} instanceUrl - Magentrix instance base URL
|
|
29
|
+
* @param {string} token - OAuth2 bearer token
|
|
30
|
+
* @param {Buffer} zipBuffer - The zip file as a Buffer
|
|
31
|
+
* @param {string} filename - The filename for the zip (e.g., "my-app.zip")
|
|
32
|
+
* @param {string} appName - The user-friendly display name (required for navigation)
|
|
33
|
+
* @param {Object} options - Optional parameters
|
|
34
|
+
* @param {string} [options.appDescription] - App description
|
|
35
|
+
* @param {string} [options.appIconId] - App icon ID
|
|
36
|
+
* @returns {Promise<{success: boolean, message: string, folderName: string}>}
|
|
37
|
+
*/
|
|
38
|
+
export const publishApp = async (instanceUrl, token, zipBuffer, filename, appName, options = {}) => {
|
|
39
|
+
if (!instanceUrl || !token) {
|
|
40
|
+
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!zipBuffer || !Buffer.isBuffer(zipBuffer)) {
|
|
44
|
+
throw new Error('zipBuffer must be a valid Buffer');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!filename) {
|
|
48
|
+
throw new Error('filename is required');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Create a File object from the buffer for FormData
|
|
52
|
+
const file = new File([zipBuffer], filename, { type: 'application/zip' });
|
|
53
|
+
|
|
54
|
+
const formData = new FormData();
|
|
55
|
+
formData.append('file', file);
|
|
56
|
+
|
|
57
|
+
// Build query parameters
|
|
58
|
+
// Note: app-name is only sent when provided (required for creates, optional for updates)
|
|
59
|
+
// Sending app-name on updates can trigger a rename attempt that fails if the user
|
|
60
|
+
// lacks metadata-edit permissions on the server
|
|
61
|
+
const params = new URLSearchParams();
|
|
62
|
+
|
|
63
|
+
if (appName) {
|
|
64
|
+
params.append('app-name', appName);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (options.appDescription) {
|
|
68
|
+
params.append('app-description', options.appDescription);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (options.appIconId) {
|
|
72
|
+
params.append('app-icon-id', options.appIconId);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const response = await fetchMagentrix({
|
|
76
|
+
instanceUrl,
|
|
77
|
+
token,
|
|
78
|
+
path: `/iris/publishapp?${params.toString()}`,
|
|
79
|
+
method: 'POST',
|
|
80
|
+
body: formData,
|
|
81
|
+
ignoreContentType: true,
|
|
82
|
+
returnErrorObject: true
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return response;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Delete an Iris application.
|
|
90
|
+
* @param {string} instanceUrl - Magentrix instance base URL
|
|
91
|
+
* @param {string} token - OAuth2 bearer token
|
|
92
|
+
* @param {string} folderName - The folder name of the app to delete
|
|
93
|
+
* @returns {Promise<{success: boolean, message: string}>}
|
|
94
|
+
*/
|
|
95
|
+
export const deleteApp = async (instanceUrl, token, folderName) => {
|
|
96
|
+
if (!instanceUrl || !token) {
|
|
97
|
+
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!folderName) {
|
|
101
|
+
throw new Error('folderName is required');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const response = await fetchMagentrix({
|
|
105
|
+
instanceUrl,
|
|
106
|
+
token,
|
|
107
|
+
path: `/iris/deleteapp?folderName=${encodeURIComponent(folderName)}`,
|
|
108
|
+
method: 'POST',
|
|
109
|
+
returnErrorObject: true
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return response;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Download a single Iris application as a buffer.
|
|
117
|
+
* @param {string} instanceUrl - Magentrix instance base URL
|
|
118
|
+
* @param {string} token - OAuth2 bearer token
|
|
119
|
+
* @param {string} folderName - The folder name of the app to download
|
|
120
|
+
* @returns {Promise<{buffer: Buffer, filename: string}>}
|
|
121
|
+
*/
|
|
122
|
+
export const downloadApp = async (instanceUrl, token, folderName) => {
|
|
123
|
+
if (!instanceUrl || !token) {
|
|
124
|
+
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!folderName) {
|
|
128
|
+
throw new Error('folderName is required');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const url = `${instanceUrl.replace(/\/$/, '')}/iris/downloadapp?folderName=${encodeURIComponent(folderName)}`;
|
|
132
|
+
|
|
133
|
+
const response = await fetch(url, {
|
|
134
|
+
method: 'GET',
|
|
135
|
+
headers: {
|
|
136
|
+
'Authorization': `Bearer ${token}`
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
if (!response.ok) {
|
|
141
|
+
let errorMessage = `Download failed (${response.status})`;
|
|
142
|
+
try {
|
|
143
|
+
const errorData = await response.json();
|
|
144
|
+
if (errorData.message) {
|
|
145
|
+
errorMessage = errorData.message;
|
|
146
|
+
}
|
|
147
|
+
} catch {
|
|
148
|
+
errorMessage = `Download failed: ${response.statusText}`;
|
|
149
|
+
}
|
|
150
|
+
throw new Error(errorMessage);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Get filename from Content-Disposition header
|
|
154
|
+
const contentDisposition = response.headers.get('content-disposition') || '';
|
|
155
|
+
const filenameMatch = /filename\*?=(?:UTF-8'')?["']?([^"';]+)["']?/i.exec(contentDisposition);
|
|
156
|
+
const filename = filenameMatch ? decodeURIComponent(filenameMatch[1]) : `${folderName}.zip`;
|
|
157
|
+
|
|
158
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
159
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
160
|
+
|
|
161
|
+
return { buffer, filename };
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Download all Iris applications as a single zip buffer.
|
|
166
|
+
* @param {string} instanceUrl - Magentrix instance base URL
|
|
167
|
+
* @param {string} token - OAuth2 bearer token
|
|
168
|
+
* @returns {Promise<{buffer: Buffer, filename: string}>}
|
|
169
|
+
*/
|
|
170
|
+
export const downloadAllApps = async (instanceUrl, token) => {
|
|
171
|
+
if (!instanceUrl || !token) {
|
|
172
|
+
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const url = `${instanceUrl.replace(/\/$/, '')}/iris/downloadallapps`;
|
|
176
|
+
|
|
177
|
+
const response = await fetch(url, {
|
|
178
|
+
method: 'GET',
|
|
179
|
+
headers: {
|
|
180
|
+
'Authorization': `Bearer ${token}`
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
if (!response.ok) {
|
|
185
|
+
let errorMessage = `Download failed (${response.status})`;
|
|
186
|
+
try {
|
|
187
|
+
const errorData = await response.json();
|
|
188
|
+
if (errorData.message) {
|
|
189
|
+
errorMessage = errorData.message;
|
|
190
|
+
}
|
|
191
|
+
} catch {
|
|
192
|
+
errorMessage = `Download failed: ${response.statusText}`;
|
|
193
|
+
}
|
|
194
|
+
throw new Error(errorMessage);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Get filename from Content-Disposition header
|
|
198
|
+
const contentDisposition = response.headers.get('content-disposition') || '';
|
|
199
|
+
const filenameMatch = /filename\*?=(?:UTF-8'')?["']?([^"';]+)["']?/i.exec(contentDisposition);
|
|
200
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
201
|
+
const filename = filenameMatch ? decodeURIComponent(filenameMatch[1]) : `iris-apps_${timestamp}.zip`;
|
|
202
|
+
|
|
203
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
204
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
205
|
+
|
|
206
|
+
return { buffer, filename };
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get platform assets for local development (CSS, fonts, etc.).
|
|
211
|
+
* @param {string} siteUrl - Magentrix instance base URL (from Vue config.ts)
|
|
212
|
+
* @param {string} token - OAuth2 bearer token
|
|
213
|
+
* @returns {Promise<{success: boolean, assets: string[]}>}
|
|
214
|
+
*/
|
|
215
|
+
export const getIrisAssets = async (siteUrl, token) => {
|
|
216
|
+
if (!siteUrl) {
|
|
217
|
+
throw new Error('Missing required siteUrl');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const url = `${siteUrl.replace(/\/$/, '')}/iris/getirisassets`;
|
|
221
|
+
|
|
222
|
+
const headers = {
|
|
223
|
+
'Accept': 'application/json'
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// Token is optional for this endpoint (might be public)
|
|
227
|
+
if (token) {
|
|
228
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const response = await fetch(url, {
|
|
232
|
+
method: 'GET',
|
|
233
|
+
headers
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
if (!response.ok) {
|
|
237
|
+
let errorMessage = `Failed to fetch Iris assets (${response.status})`;
|
|
238
|
+
try {
|
|
239
|
+
const errorData = await response.json();
|
|
240
|
+
if (errorData.message) {
|
|
241
|
+
errorMessage = errorData.message;
|
|
242
|
+
}
|
|
243
|
+
} catch {
|
|
244
|
+
errorMessage = `Failed to fetch Iris assets: ${response.statusText}`;
|
|
245
|
+
}
|
|
246
|
+
throw new Error(errorMessage);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const data = await response.json();
|
|
250
|
+
return data;
|
|
251
|
+
};
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import { fetchMagentrix } from "../fetch.js";
|
|
2
|
-
import debug from '../../debug.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Executes a Magentrix Entity Query Language (MEQL) query via the REST API v3.
|
|
6
|
-
*
|
|
7
|
-
* @async
|
|
8
|
-
* @param {string} instanceUrl - Base URL of the Magentrix instance.
|
|
9
|
-
* @param {string} token - Bearer token string.
|
|
10
|
-
* @param {string} query - MEQL query string.
|
|
11
|
-
* @returns {Promise<object>} The API response data.
|
|
12
|
-
* @throws {Error} On HTTP or API-level error.
|
|
13
|
-
*/
|
|
14
|
-
export const meqlQuery = async (instanceUrl, token, query = '') => {
|
|
15
|
-
if (!instanceUrl || !token) {
|
|
16
|
-
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
17
|
-
}
|
|
18
|
-
if (!query.trim()) {
|
|
19
|
-
throw new Error('MEQL query string is required');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
debug.log('MEQL', `Query: ${query}`);
|
|
23
|
-
|
|
24
|
-
const data = await fetchMagentrix({
|
|
25
|
-
instanceUrl,
|
|
26
|
-
token,
|
|
27
|
-
method: "POST",
|
|
28
|
-
path: '/api/3.0/query',
|
|
29
|
-
body: query
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
debug.log('MEQL', `Result: ${data?.Records?.length ?? 0} records returned`);
|
|
33
|
-
|
|
34
|
-
// --- Success ---
|
|
35
|
-
return data;
|
|
36
|
-
};
|
|
1
|
+
import { fetchMagentrix } from "../fetch.js";
|
|
2
|
+
import debug from '../../debug.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Executes a Magentrix Entity Query Language (MEQL) query via the REST API v3.
|
|
6
|
+
*
|
|
7
|
+
* @async
|
|
8
|
+
* @param {string} instanceUrl - Base URL of the Magentrix instance.
|
|
9
|
+
* @param {string} token - Bearer token string.
|
|
10
|
+
* @param {string} query - MEQL query string.
|
|
11
|
+
* @returns {Promise<object>} The API response data.
|
|
12
|
+
* @throws {Error} On HTTP or API-level error.
|
|
13
|
+
*/
|
|
14
|
+
export const meqlQuery = async (instanceUrl, token, query = '') => {
|
|
15
|
+
if (!instanceUrl || !token) {
|
|
16
|
+
throw new Error('Missing required Magentrix instanceUrl or token');
|
|
17
|
+
}
|
|
18
|
+
if (!query.trim()) {
|
|
19
|
+
throw new Error('MEQL query string is required');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
debug.log('MEQL', `Query: ${query}`);
|
|
23
|
+
|
|
24
|
+
const data = await fetchMagentrix({
|
|
25
|
+
instanceUrl,
|
|
26
|
+
token,
|
|
27
|
+
method: "POST",
|
|
28
|
+
path: '/api/3.0/query',
|
|
29
|
+
body: query
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
debug.log('MEQL', `Result: ${data?.Records?.length ?? 0} records returned`);
|
|
33
|
+
|
|
34
|
+
// --- Success ---
|
|
35
|
+
return data;
|
|
36
|
+
};
|