hereya-cli 0.89.0 → 0.90.1
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 +65 -65
- package/dist/backend/cloud/cloud-backend/apps-deploy.d.ts +69 -0
- package/dist/backend/cloud/cloud-backend/apps-deploy.js +94 -0
- package/dist/backend/cloud/cloud-backend/apps-versions.d.ts +69 -0
- package/dist/backend/cloud/cloud-backend/apps-versions.js +113 -0
- package/dist/backend/cloud/cloud-backend/executor-jobs.d.ts +75 -0
- package/dist/backend/cloud/cloud-backend/executor-jobs.js +110 -0
- package/dist/backend/cloud/cloud-backend/misc.d.ts +5 -0
- package/dist/backend/cloud/cloud-backend/misc.js +78 -0
- package/dist/backend/cloud/cloud-backend/packages-publish.d.ts +3 -0
- package/dist/backend/cloud/cloud-backend/packages-publish.js +99 -0
- package/dist/backend/cloud/cloud-backend/packages-registry.d.ts +6 -0
- package/dist/backend/cloud/cloud-backend/packages-registry.js +146 -0
- package/dist/backend/cloud/cloud-backend/packages-workspace.d.ts +4 -0
- package/dist/backend/cloud/cloud-backend/packages-workspace.js +50 -0
- package/dist/backend/cloud/cloud-backend/projects.d.ts +7 -0
- package/dist/backend/cloud/cloud-backend/projects.js +122 -0
- package/dist/backend/cloud/cloud-backend/state.d.ts +6 -0
- package/dist/backend/cloud/cloud-backend/state.js +86 -0
- package/dist/backend/cloud/cloud-backend/utils.d.ts +55 -0
- package/dist/backend/cloud/cloud-backend/utils.js +56 -0
- package/dist/backend/cloud/cloud-backend/workspace-env.d.ts +5 -0
- package/dist/backend/cloud/cloud-backend/workspace-env.js +63 -0
- package/dist/backend/cloud/cloud-backend/workspaces.d.ts +7 -0
- package/dist/backend/cloud/cloud-backend/workspaces.js +124 -0
- package/dist/backend/cloud/cloud-backend.d.ts +56 -126
- package/dist/backend/cloud/cloud-backend.js +95 -1089
- package/dist/backend/cloud/cloud-backend.test.setup.d.ts +13 -0
- package/dist/backend/cloud/cloud-backend.test.setup.js +14 -0
- package/dist/backend/local.setup.d.ts +10 -0
- package/dist/backend/local.setup.js +20 -0
- package/dist/commands/executor/start/index.d.ts +1 -11
- package/dist/commands/executor/start/index.js +13 -498
- package/dist/commands/import-repo/index.js +2 -2
- package/dist/lib/env/test.setup.d.ts +7 -0
- package/dist/lib/env/test.setup.js +18 -0
- package/dist/lib/executor-start/auth.d.ts +2 -0
- package/dist/lib/executor-start/auth.js +21 -0
- package/dist/lib/executor-start/execute-app-job.d.ts +13 -0
- package/dist/lib/executor-start/execute-app-job.js +146 -0
- package/dist/lib/executor-start/execute-deploy-job.d.ts +14 -0
- package/dist/lib/executor-start/execute-deploy-job.js +64 -0
- package/dist/lib/executor-start/execute-init-job.d.ts +14 -0
- package/dist/lib/executor-start/execute-init-job.js +135 -0
- package/dist/lib/executor-start/format.d.ts +13 -0
- package/dist/lib/executor-start/format.js +22 -0
- package/dist/lib/executor-start/job-dispatch.d.ts +15 -0
- package/dist/lib/executor-start/job-dispatch.js +89 -0
- package/dist/lib/package/index.d.ts +4 -4
- package/oclif.manifest.json +52 -52
- package/package.json +1 -1
|
@@ -1,1137 +1,143 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as appsDeploy from './cloud-backend/apps-deploy.js';
|
|
2
|
+
import * as appsVersions from './cloud-backend/apps-versions.js';
|
|
3
|
+
import * as executorJobs from './cloud-backend/executor-jobs.js';
|
|
4
|
+
import * as misc from './cloud-backend/misc.js';
|
|
5
|
+
import * as packagesPublish from './cloud-backend/packages-publish.js';
|
|
6
|
+
import * as packagesRegistry from './cloud-backend/packages-registry.js';
|
|
7
|
+
import * as packagesWorkspace from './cloud-backend/packages-workspace.js';
|
|
8
|
+
import * as projects from './cloud-backend/projects.js';
|
|
9
|
+
import * as state from './cloud-backend/state.js';
|
|
10
|
+
import * as workspaceEnv from './cloud-backend/workspace-env.js';
|
|
11
|
+
import * as workspaces from './cloud-backend/workspaces.js';
|
|
2
12
|
export class CloudBackend {
|
|
3
13
|
config;
|
|
4
14
|
constructor(config) {
|
|
5
15
|
this.config = config;
|
|
6
16
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
formData.append('package', input.package);
|
|
10
|
-
formData.append('infra', input.infra);
|
|
11
|
-
formData.append('env', JSON.stringify(input.env));
|
|
12
|
-
if (input.parameters) {
|
|
13
|
-
formData.append('parameters', JSON.stringify(input.parameters));
|
|
14
|
-
}
|
|
15
|
-
if (input.version) {
|
|
16
|
-
formData.append('version', input.version);
|
|
17
|
-
}
|
|
18
|
-
const response = await fetch(`${this.config.url}/api/workspaces/${encodeURIComponent(input.workspace)}/packages`, {
|
|
19
|
-
body: formData,
|
|
20
|
-
headers: {
|
|
21
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
22
|
-
},
|
|
23
|
-
method: 'POST',
|
|
24
|
-
});
|
|
25
|
-
if (!response.ok) {
|
|
26
|
-
return {
|
|
27
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
28
|
-
success: false,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
const result = await response.json();
|
|
32
|
-
return {
|
|
33
|
-
success: true,
|
|
34
|
-
workspace: this.convertWorkspace(result.workspace),
|
|
35
|
-
};
|
|
17
|
+
addPackageToWorkspace(input) {
|
|
18
|
+
return packagesWorkspace.addPackageToWorkspace(this.config, input);
|
|
36
19
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
formData.append('name', input.name);
|
|
40
|
-
if (input.mirrorOf) {
|
|
41
|
-
formData.append('mirrorOf', input.mirrorOf);
|
|
42
|
-
}
|
|
43
|
-
if (input.profile) {
|
|
44
|
-
formData.append('profile', input.profile);
|
|
45
|
-
}
|
|
46
|
-
if (input.isDeploy !== undefined) {
|
|
47
|
-
formData.append('isDeploy', String(input.isDeploy));
|
|
48
|
-
}
|
|
49
|
-
const response = await fetch(`${this.config.url}/api/workspaces`, {
|
|
50
|
-
body: formData,
|
|
51
|
-
headers: {
|
|
52
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
53
|
-
},
|
|
54
|
-
method: 'POST',
|
|
55
|
-
});
|
|
56
|
-
if (!response.ok) {
|
|
57
|
-
return {
|
|
58
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
59
|
-
success: false,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
const result = await response.json();
|
|
63
|
-
return {
|
|
64
|
-
isNew: true,
|
|
65
|
-
success: true,
|
|
66
|
-
workspace: this.convertWorkspace(result.workspace),
|
|
67
|
-
};
|
|
20
|
+
createWorkspace(input) {
|
|
21
|
+
return workspaces.createWorkspace(this.config, input);
|
|
68
22
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
headers: {
|
|
72
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
73
|
-
},
|
|
74
|
-
method: 'DELETE',
|
|
75
|
-
});
|
|
76
|
-
if (!response.ok) {
|
|
77
|
-
return {
|
|
78
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
79
|
-
success: false,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
return {
|
|
83
|
-
message: `State for project ${input.project} in workspace ${input.workspace} deleted successfully`,
|
|
84
|
-
success: true,
|
|
85
|
-
};
|
|
23
|
+
deleteState(input) {
|
|
24
|
+
return state.deleteState(this.config, input);
|
|
86
25
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
headers: {
|
|
90
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
91
|
-
},
|
|
92
|
-
method: 'DELETE',
|
|
93
|
-
});
|
|
94
|
-
if (!response.ok) {
|
|
95
|
-
return {
|
|
96
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
97
|
-
success: false,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
return {
|
|
101
|
-
success: true,
|
|
102
|
-
};
|
|
26
|
+
deleteWorkspace(input) {
|
|
27
|
+
return workspaces.deleteWorkspace(this.config, input);
|
|
103
28
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
workspace: input.workspace,
|
|
107
|
-
};
|
|
108
|
-
if (input.version)
|
|
109
|
-
body.version = input.version;
|
|
110
|
-
if (input.parameters)
|
|
111
|
-
body.parameters = input.parameters;
|
|
112
|
-
const response = await fetch(`${this.config.url}/api/apps/${encodeURIComponent(input.name)}/deployments`, {
|
|
113
|
-
body: JSON.stringify(body),
|
|
114
|
-
headers: {
|
|
115
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
116
|
-
'Content-Type': 'application/json',
|
|
117
|
-
},
|
|
118
|
-
method: 'POST',
|
|
119
|
-
});
|
|
120
|
-
if (!response.ok) {
|
|
121
|
-
const error = await this.safeResponseJson(response);
|
|
122
|
-
return { reason: error.error || `Failed to deploy app (status ${response.status})`, success: false };
|
|
123
|
-
}
|
|
124
|
-
const result = await response.json();
|
|
125
|
-
return { deploymentId: result.deploymentId, jobId: result.jobId, success: true };
|
|
29
|
+
deployApp(input) {
|
|
30
|
+
return appsDeploy.deployApp(this.config, input);
|
|
126
31
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const response = await fetch(`${this.config.url}/api/apps/${encodeURIComponent(input.name)}/deployments/${encodeURIComponent(input.workspace)}`, {
|
|
130
|
-
body,
|
|
131
|
-
headers: {
|
|
132
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
133
|
-
...(body ? { 'Content-Type': 'application/json' } : {}),
|
|
134
|
-
},
|
|
135
|
-
method: 'DELETE',
|
|
136
|
-
});
|
|
137
|
-
if (!response.ok) {
|
|
138
|
-
const error = await this.safeResponseJson(response);
|
|
139
|
-
return { reason: error.error || `Failed to destroy app (status ${response.status})`, success: false };
|
|
140
|
-
}
|
|
141
|
-
const result = await response.json();
|
|
142
|
-
return { jobId: result.jobId, success: true };
|
|
32
|
+
destroyApp(input) {
|
|
33
|
+
return appsDeploy.destroyApp(this.config, input);
|
|
143
34
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
headers: {
|
|
147
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
148
|
-
},
|
|
149
|
-
method: 'GET',
|
|
150
|
-
});
|
|
151
|
-
if (!response.ok) {
|
|
152
|
-
return {
|
|
153
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
154
|
-
success: false,
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
const result = await response.json();
|
|
158
|
-
if (!result.success) {
|
|
159
|
-
return {
|
|
160
|
-
reason: JSON.stringify(result),
|
|
161
|
-
success: false,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
return {
|
|
165
|
-
data: JSON.stringify(result.data),
|
|
166
|
-
success: true,
|
|
167
|
-
};
|
|
35
|
+
exportBackend() {
|
|
36
|
+
return misc.exportBackend(this.config);
|
|
168
37
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
172
|
-
method: 'POST',
|
|
173
|
-
});
|
|
174
|
-
if (!response.ok) {
|
|
175
|
-
const error = await this.safeResponseJson(response);
|
|
176
|
-
return { reason: error.error || 'Failed to generate executor token', success: false };
|
|
177
|
-
}
|
|
178
|
-
const result = await response.json();
|
|
179
|
-
return { expiresAt: result.expiresAt, success: true, token: result.token };
|
|
38
|
+
generateExecutorToken(input) {
|
|
39
|
+
return executorJobs.generateExecutorToken(this.config, input);
|
|
180
40
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
184
|
-
method: 'GET',
|
|
185
|
-
});
|
|
186
|
-
if (!response.ok) {
|
|
187
|
-
const error = await this.safeResponseJson(response);
|
|
188
|
-
let errorMessage = error.error || `Failed to get app (status ${response.status})`;
|
|
189
|
-
if (response.status === 404) {
|
|
190
|
-
errorMessage = `App '${name}' not found`;
|
|
191
|
-
}
|
|
192
|
-
return { reason: errorMessage, success: false };
|
|
193
|
-
}
|
|
194
|
-
const result = await response.json();
|
|
195
|
-
return { app: result.app, success: true };
|
|
41
|
+
getApp(name) {
|
|
42
|
+
return appsVersions.getApp(this.config, name);
|
|
196
43
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
200
|
-
method: 'GET',
|
|
201
|
-
});
|
|
202
|
-
if (!response.ok) {
|
|
203
|
-
const error = await this.safeResponseJson(response);
|
|
204
|
-
let errorMessage = error.error || `Failed to get app deployment (status ${response.status})`;
|
|
205
|
-
if (response.status === 404) {
|
|
206
|
-
errorMessage = `Deployment for app '${input.name}' on workspace '${input.workspace}' not found`;
|
|
207
|
-
}
|
|
208
|
-
return { reason: errorMessage, success: false };
|
|
209
|
-
}
|
|
210
|
-
const result = await response.json();
|
|
211
|
-
return { deployment: result.deployment, success: true };
|
|
44
|
+
getAppDeployment(input) {
|
|
45
|
+
return appsDeploy.getAppDeployment(this.config, input);
|
|
212
46
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
? `${this.config.url}/api/apps/${encodeURIComponent(input.name)}/versions/${encodeURIComponent(input.version)}`
|
|
216
|
-
: `${this.config.url}/api/apps/${encodeURIComponent(input.name)}/versions/latest`;
|
|
217
|
-
const response = await fetch(url, {
|
|
218
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
219
|
-
method: 'GET',
|
|
220
|
-
});
|
|
221
|
-
if (!response.ok) {
|
|
222
|
-
const error = await this.safeResponseJson(response);
|
|
223
|
-
let errorMessage = error.error || `Failed to get app version (status ${response.status})`;
|
|
224
|
-
if (response.status === 404) {
|
|
225
|
-
errorMessage = input.version
|
|
226
|
-
? `App version '${input.name}@${input.version}' not found`
|
|
227
|
-
: `App '${input.name}' not found`;
|
|
228
|
-
}
|
|
229
|
-
return { reason: errorMessage, success: false };
|
|
230
|
-
}
|
|
231
|
-
const result = await response.json();
|
|
232
|
-
return { appVersion: result.appVersion ?? result.version, success: true };
|
|
47
|
+
getAppVersion(input) {
|
|
48
|
+
return appsVersions.getAppVersion(this.config, input);
|
|
233
49
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if (input.poll) {
|
|
237
|
-
url.searchParams.set('poll', 'true');
|
|
238
|
-
}
|
|
239
|
-
if (input.lastStatus) {
|
|
240
|
-
url.searchParams.set('lastStatus', input.lastStatus);
|
|
241
|
-
}
|
|
242
|
-
const response = await fetch(url.toString(), {
|
|
243
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
244
|
-
method: 'GET',
|
|
245
|
-
});
|
|
246
|
-
if (!response.ok) {
|
|
247
|
-
if (response.status === 401) {
|
|
248
|
-
return { reason: 'Unauthorized', success: false };
|
|
249
|
-
}
|
|
250
|
-
const error = await this.safeResponseJson(response);
|
|
251
|
-
return { reason: error.error || 'Failed to get job status', success: false };
|
|
252
|
-
}
|
|
253
|
-
const result = await response.json();
|
|
254
|
-
return { job: result.job, success: true };
|
|
50
|
+
getExecutorJobStatus(input) {
|
|
51
|
+
return executorJobs.getExecutorJobStatus(this.config, input);
|
|
255
52
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
headers: {
|
|
259
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
260
|
-
},
|
|
261
|
-
method: 'GET',
|
|
262
|
-
});
|
|
263
|
-
const result = await this.safeResponseJson(response);
|
|
264
|
-
if (!response.ok) {
|
|
265
|
-
// Handle error responses
|
|
266
|
-
let errorMessage = result.error || 'Failed to get package';
|
|
267
|
-
switch (response.status) {
|
|
268
|
-
case 401: {
|
|
269
|
-
errorMessage = 'Authentication failed. Please run `hereya login` to refresh your credentials.';
|
|
270
|
-
break;
|
|
271
|
-
}
|
|
272
|
-
case 403: {
|
|
273
|
-
errorMessage = `Access denied: ${errorMessage}`;
|
|
274
|
-
break;
|
|
275
|
-
}
|
|
276
|
-
case 404: {
|
|
277
|
-
errorMessage = `Package '${name}@${version}' not found`;
|
|
278
|
-
break;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return {
|
|
282
|
-
reason: errorMessage,
|
|
283
|
-
success: false,
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
return {
|
|
287
|
-
package: result.package,
|
|
288
|
-
success: true,
|
|
289
|
-
};
|
|
53
|
+
getPackageByVersion(name, version) {
|
|
54
|
+
return packagesRegistry.getPackageByVersion(this.config, name, version);
|
|
290
55
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
headers: {
|
|
294
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
295
|
-
},
|
|
296
|
-
method: 'GET',
|
|
297
|
-
});
|
|
298
|
-
const result = await this.safeResponseJson(response);
|
|
299
|
-
if (!response.ok) {
|
|
300
|
-
// Handle error responses
|
|
301
|
-
let errorMessage = result.error || 'Failed to get package';
|
|
302
|
-
switch (response.status) {
|
|
303
|
-
case 401: {
|
|
304
|
-
errorMessage = 'Authentication failed. Please run `hereya login` to refresh your credentials.';
|
|
305
|
-
break;
|
|
306
|
-
}
|
|
307
|
-
case 403: {
|
|
308
|
-
errorMessage = `Access denied: ${errorMessage}`;
|
|
309
|
-
break;
|
|
310
|
-
}
|
|
311
|
-
case 404: {
|
|
312
|
-
errorMessage = `Package '${name}' not found`;
|
|
313
|
-
break;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
return {
|
|
317
|
-
reason: errorMessage,
|
|
318
|
-
success: false,
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
return {
|
|
322
|
-
package: result.package,
|
|
323
|
-
success: true,
|
|
324
|
-
};
|
|
56
|
+
getPackageLatest(name) {
|
|
57
|
+
return packagesRegistry.getPackageLatest(this.config, name);
|
|
325
58
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
headers: {
|
|
329
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
330
|
-
},
|
|
331
|
-
method: 'GET',
|
|
332
|
-
});
|
|
333
|
-
if (!response.ok) {
|
|
334
|
-
return {
|
|
335
|
-
found: false,
|
|
336
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
const result = await this.safeResponseJson(response);
|
|
340
|
-
if (!result.metadata) {
|
|
341
|
-
return {
|
|
342
|
-
found: false,
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
return {
|
|
346
|
-
defaultWorkspace: result.defaultWorkspace,
|
|
347
|
-
found: true,
|
|
348
|
-
metadata: result.metadata,
|
|
349
|
-
};
|
|
59
|
+
getProjectMetadata(input) {
|
|
60
|
+
return projects.getProjectMetadata(this.config, input);
|
|
350
61
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
formData.append('packageCanonicalName', input.packageCanonicalName);
|
|
354
|
-
formData.append('logicalId', input.logicalId);
|
|
355
|
-
if (input.app) {
|
|
356
|
-
formData.append('app', input.app);
|
|
357
|
-
}
|
|
358
|
-
if (input.project) {
|
|
359
|
-
formData.append('project', input.project);
|
|
360
|
-
}
|
|
361
|
-
if (input.workspace) {
|
|
362
|
-
formData.append('workspace', input.workspace);
|
|
363
|
-
}
|
|
364
|
-
const response = await fetch(`${this.config.url}/api/provisioning-id`, {
|
|
365
|
-
body: formData,
|
|
366
|
-
headers: {
|
|
367
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
368
|
-
},
|
|
369
|
-
method: 'POST',
|
|
370
|
-
});
|
|
371
|
-
if (!response.ok) {
|
|
372
|
-
return {
|
|
373
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
374
|
-
success: false,
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
const result = await response.json();
|
|
378
|
-
return {
|
|
379
|
-
id: result.provisioningId.id,
|
|
380
|
-
success: true,
|
|
381
|
-
};
|
|
62
|
+
getProvisioningId(input) {
|
|
63
|
+
return misc.getProvisioningId(this.config, input);
|
|
382
64
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
url.searchParams.append('workspace', input.workspace);
|
|
386
|
-
const response = await fetch(url, {
|
|
387
|
-
headers: {
|
|
388
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
389
|
-
},
|
|
390
|
-
method: 'GET',
|
|
391
|
-
});
|
|
392
|
-
if (!response.ok) {
|
|
393
|
-
return {
|
|
394
|
-
found: false,
|
|
395
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
const result = await response.json();
|
|
399
|
-
if (!result.success) {
|
|
400
|
-
return {
|
|
401
|
-
found: false,
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
const deploy = {};
|
|
405
|
-
for (const item of result.config.deploy) {
|
|
406
|
-
deploy[item.name] = { version: item.version };
|
|
407
|
-
}
|
|
408
|
-
const packages = {};
|
|
409
|
-
for (const item of result.config.packages) {
|
|
410
|
-
packages[item.name] = { version: item.version };
|
|
411
|
-
}
|
|
412
|
-
return {
|
|
413
|
-
config: {
|
|
414
|
-
deploy,
|
|
415
|
-
packages,
|
|
416
|
-
project: input.project,
|
|
417
|
-
workspace: input.workspace,
|
|
418
|
-
},
|
|
419
|
-
found: true,
|
|
420
|
-
};
|
|
65
|
+
getState(input) {
|
|
66
|
+
return state.getState(this.config, input);
|
|
421
67
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
headers: {
|
|
425
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
426
|
-
},
|
|
427
|
-
method: 'GET',
|
|
428
|
-
});
|
|
429
|
-
// Handle 404 as "not found" rather than error
|
|
430
|
-
if (response.status === 404) {
|
|
431
|
-
return {
|
|
432
|
-
found: false,
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
if (!response.ok) {
|
|
436
|
-
const error = await this.safeResponseJson(response);
|
|
437
|
-
return {
|
|
438
|
-
error: JSON.stringify(error),
|
|
439
|
-
found: true,
|
|
440
|
-
hasError: true,
|
|
441
|
-
};
|
|
442
|
-
}
|
|
443
|
-
const result = await response.json();
|
|
444
|
-
return {
|
|
445
|
-
found: true,
|
|
446
|
-
hasError: false,
|
|
447
|
-
workspace: this.convertWorkspace(result.workspace),
|
|
448
|
-
};
|
|
68
|
+
getWorkspace(name) {
|
|
69
|
+
return workspaces.getWorkspace(this.config, name);
|
|
449
70
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
const workspaceName = resolveWorkspaceName(input.workspace, input.project);
|
|
453
|
-
const workspace$ = await this.getWorkspace(workspaceName);
|
|
454
|
-
if (!workspace$.found) {
|
|
455
|
-
return {
|
|
456
|
-
reason: `Workspace ${input.workspace} not found`,
|
|
457
|
-
success: false,
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
if (workspace$.hasError) {
|
|
461
|
-
return {
|
|
462
|
-
reason: workspace$.error,
|
|
463
|
-
success: false,
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
return {
|
|
467
|
-
env: workspace$.workspace.env ?? {},
|
|
468
|
-
success: true,
|
|
469
|
-
};
|
|
71
|
+
getWorkspaceEnv(input) {
|
|
72
|
+
return workspaceEnv.getWorkspaceEnv(this.config, input);
|
|
470
73
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
formData.append('data', input.data);
|
|
474
|
-
const response = await fetch(`${this.config.url}/api/import`, {
|
|
475
|
-
body: formData,
|
|
476
|
-
headers: {
|
|
477
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
478
|
-
},
|
|
479
|
-
method: 'POST',
|
|
480
|
-
});
|
|
481
|
-
if (!response.ok) {
|
|
482
|
-
return {
|
|
483
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
484
|
-
success: false,
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
return {
|
|
488
|
-
success: true,
|
|
489
|
-
};
|
|
74
|
+
importBackend(input) {
|
|
75
|
+
return misc.importBackend(this.config, input);
|
|
490
76
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
body: JSON.stringify({ repoUrl: input.repoUrl, workspace: input.workspace }),
|
|
494
|
-
headers: {
|
|
495
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
496
|
-
'Content-Type': 'application/json',
|
|
497
|
-
},
|
|
498
|
-
method: 'POST',
|
|
499
|
-
});
|
|
500
|
-
const result = await this.safeResponseJson(response);
|
|
501
|
-
if (!response.ok) {
|
|
502
|
-
const reason = typeof result?.error === 'string'
|
|
503
|
-
? result.error
|
|
504
|
-
: (result?.errors && typeof result.errors === 'object'
|
|
505
|
-
? JSON.stringify(result.errors)
|
|
506
|
-
: JSON.stringify(result));
|
|
507
|
-
return {
|
|
508
|
-
...(typeof result?.code === 'string' ? { code: result.code } : {}),
|
|
509
|
-
reason,
|
|
510
|
-
success: false,
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
if (!result?.success || !result?.project) {
|
|
514
|
-
return {
|
|
515
|
-
reason: typeof result?.error === 'string' ? result.error : 'Unexpected response from server',
|
|
516
|
-
success: false,
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
return {
|
|
520
|
-
project: {
|
|
521
|
-
defaultWorkspace: result.project.defaultWorkspace,
|
|
522
|
-
name: result.project.name,
|
|
523
|
-
},
|
|
524
|
-
success: true,
|
|
525
|
-
};
|
|
77
|
+
importProject(input) {
|
|
78
|
+
return projects.importProject(this.config, input);
|
|
526
79
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
formData.append('name', input.project);
|
|
530
|
-
formData.append('workspace', input.workspace);
|
|
531
|
-
const response = await fetch(`${this.config.url}/api/projects`, {
|
|
532
|
-
body: formData,
|
|
533
|
-
headers: {
|
|
534
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
535
|
-
},
|
|
536
|
-
method: 'POST',
|
|
537
|
-
});
|
|
538
|
-
if (!response.ok) {
|
|
539
|
-
throw new Error(JSON.stringify(await this.safeResponseJson(response)));
|
|
540
|
-
}
|
|
541
|
-
const result = await response.json();
|
|
542
|
-
return {
|
|
543
|
-
project: {
|
|
544
|
-
id: result.project.id,
|
|
545
|
-
name: result.project.name,
|
|
546
|
-
},
|
|
547
|
-
workspace: {
|
|
548
|
-
id: result.project.defaultWorkspace.id,
|
|
549
|
-
name: result.project.defaultWorkspace.name,
|
|
550
|
-
},
|
|
551
|
-
};
|
|
80
|
+
init(input) {
|
|
81
|
+
return projects.init(this.config, input);
|
|
552
82
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
556
|
-
method: 'GET',
|
|
557
|
-
});
|
|
558
|
-
if (!response.ok) {
|
|
559
|
-
const error = await this.safeResponseJson(response);
|
|
560
|
-
return { reason: error.error || `Failed to list app deployments (status ${response.status})`, success: false };
|
|
561
|
-
}
|
|
562
|
-
const result = await response.json();
|
|
563
|
-
return { deployments: result.deployments || [], success: true };
|
|
83
|
+
listAppDeployments(name) {
|
|
84
|
+
return appsDeploy.listAppDeployments(this.config, name);
|
|
564
85
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
568
|
-
method: 'GET',
|
|
569
|
-
});
|
|
570
|
-
if (!response.ok) {
|
|
571
|
-
const error = await this.safeResponseJson(response);
|
|
572
|
-
return { reason: error.error || `Failed to list apps (status ${response.status})`, success: false };
|
|
573
|
-
}
|
|
574
|
-
const result = await response.json();
|
|
575
|
-
return { apps: result.apps || [], success: true };
|
|
86
|
+
listApps() {
|
|
87
|
+
return appsVersions.listApps(this.config);
|
|
576
88
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
580
|
-
method: 'GET',
|
|
581
|
-
});
|
|
582
|
-
if (!response.ok) {
|
|
583
|
-
const error = await this.safeResponseJson(response);
|
|
584
|
-
return { reason: error.error || `Failed to list app versions (status ${response.status})`, success: false };
|
|
585
|
-
}
|
|
586
|
-
const result = await response.json();
|
|
587
|
-
return { success: true, versions: result.versions || [] };
|
|
89
|
+
listAppVersions(name) {
|
|
90
|
+
return appsVersions.listAppVersions(this.config, name);
|
|
588
91
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
headers: {
|
|
592
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
593
|
-
},
|
|
594
|
-
method: 'GET',
|
|
595
|
-
});
|
|
596
|
-
const result = await this.safeResponseJson(response);
|
|
597
|
-
if (!response.ok) {
|
|
598
|
-
// Handle error responses
|
|
599
|
-
let errorMessage = result.error || 'Failed to list package versions';
|
|
600
|
-
switch (response.status) {
|
|
601
|
-
case 401: {
|
|
602
|
-
errorMessage = 'Authentication failed. Please run `hereya login` to refresh your credentials.';
|
|
603
|
-
break;
|
|
604
|
-
}
|
|
605
|
-
case 403: {
|
|
606
|
-
errorMessage = `Access denied: ${errorMessage}`;
|
|
607
|
-
break;
|
|
608
|
-
}
|
|
609
|
-
case 404: {
|
|
610
|
-
errorMessage = `Package '${name}' not found`;
|
|
611
|
-
break;
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
return {
|
|
615
|
-
reason: errorMessage,
|
|
616
|
-
success: false,
|
|
617
|
-
};
|
|
618
|
-
}
|
|
619
|
-
return {
|
|
620
|
-
packages: result.packages || [],
|
|
621
|
-
success: true,
|
|
622
|
-
};
|
|
92
|
+
listPackageVersions(name) {
|
|
93
|
+
return packagesRegistry.listPackageVersions(this.config, name);
|
|
623
94
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
627
|
-
method: 'GET',
|
|
628
|
-
});
|
|
629
|
-
if (!response.ok) {
|
|
630
|
-
throw new Error(JSON.stringify(await this.safeResponseJson(response)));
|
|
631
|
-
}
|
|
632
|
-
const result = await response.json();
|
|
633
|
-
return (result.projects ?? []).map((p) => ({
|
|
634
|
-
defaultWorkspace: p.defaultWorkspace?.name ?? '-',
|
|
635
|
-
name: p.name,
|
|
636
|
-
}));
|
|
95
|
+
listProjects() {
|
|
96
|
+
return projects.listProjects(this.config);
|
|
637
97
|
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
if (input?.org) {
|
|
641
|
-
url.searchParams.set('org', input.org);
|
|
642
|
-
}
|
|
643
|
-
const response = await fetch(url.toString(), {
|
|
644
|
-
headers: {
|
|
645
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
646
|
-
},
|
|
647
|
-
method: 'GET',
|
|
648
|
-
});
|
|
649
|
-
if (!response.ok) {
|
|
650
|
-
throw new Error(JSON.stringify(await this.safeResponseJson(response)));
|
|
651
|
-
}
|
|
652
|
-
const result = await response.json();
|
|
653
|
-
return result.workspaces.map((workspace) => workspace.name);
|
|
98
|
+
listWorkspaces(input) {
|
|
99
|
+
return workspaces.listWorkspaces(this.config, input);
|
|
654
100
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
url.searchParams.set('workspace', input.workspace);
|
|
658
|
-
if (input.executorId) {
|
|
659
|
-
url.searchParams.set('executorId', input.executorId);
|
|
660
|
-
}
|
|
661
|
-
const response = await fetch(url.toString(), {
|
|
662
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
663
|
-
method: 'GET',
|
|
664
|
-
});
|
|
665
|
-
if (!response.ok) {
|
|
666
|
-
if (response.status === 401) {
|
|
667
|
-
return { reason: 'Unauthorized', success: false, unauthorized: true };
|
|
668
|
-
}
|
|
669
|
-
const error = await this.safeResponseJson(response);
|
|
670
|
-
return { reason: error.error || 'Failed to poll for jobs', success: false };
|
|
671
|
-
}
|
|
672
|
-
const result = await response.json();
|
|
673
|
-
return { job: result.job, success: true };
|
|
101
|
+
pollExecutorJobs(input) {
|
|
102
|
+
return executorJobs.pollExecutorJobs(this.config, input);
|
|
674
103
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
commit: input.commit,
|
|
678
|
-
hereyaYaml: input.hereyaYaml,
|
|
679
|
-
repository: input.repository,
|
|
680
|
-
sha256: input.sha256,
|
|
681
|
-
version: input.version,
|
|
682
|
-
};
|
|
683
|
-
if (input.description !== undefined)
|
|
684
|
-
requestBody.description = input.description;
|
|
685
|
-
if (input.visibility !== undefined)
|
|
686
|
-
requestBody.visibility = input.visibility;
|
|
687
|
-
if (input.parameters !== undefined)
|
|
688
|
-
requestBody.parameters = input.parameters;
|
|
689
|
-
const response = await fetch(`${this.config.url}/api/apps/${encodeURIComponent(input.name)}/versions`, {
|
|
690
|
-
body: JSON.stringify(requestBody),
|
|
691
|
-
headers: {
|
|
692
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
693
|
-
'Content-Type': 'application/json',
|
|
694
|
-
},
|
|
695
|
-
method: 'POST',
|
|
696
|
-
});
|
|
697
|
-
const result = await this.safeResponseJson(response);
|
|
698
|
-
if (!response.ok) {
|
|
699
|
-
let errorMessage = result.error || 'Failed to publish app version';
|
|
700
|
-
switch (response.status) {
|
|
701
|
-
case 401: {
|
|
702
|
-
errorMessage = 'Authentication failed. Please run `hereya login` to refresh your credentials.';
|
|
703
|
-
break;
|
|
704
|
-
}
|
|
705
|
-
case 403: {
|
|
706
|
-
errorMessage = `Permission denied: ${errorMessage}`;
|
|
707
|
-
break;
|
|
708
|
-
}
|
|
709
|
-
case 409: {
|
|
710
|
-
errorMessage = `Conflict: ${errorMessage}`;
|
|
711
|
-
break;
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
return { reason: errorMessage, success: false };
|
|
715
|
-
}
|
|
716
|
-
const app = result.appVersion ?? result.app ?? { name: input.name, version: input.version };
|
|
717
|
-
return {
|
|
718
|
-
app: {
|
|
719
|
-
id: app.id,
|
|
720
|
-
name: app.name ?? input.name,
|
|
721
|
-
version: app.version ?? input.version,
|
|
722
|
-
},
|
|
723
|
-
success: true,
|
|
724
|
-
};
|
|
104
|
+
publishAppVersion(input) {
|
|
105
|
+
return appsVersions.publishAppVersion(this.config, input);
|
|
725
106
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
formData.append('name', input.name);
|
|
729
|
-
formData.append('version', input.version);
|
|
730
|
-
formData.append('description', input.description);
|
|
731
|
-
formData.append('repository', input.repository);
|
|
732
|
-
formData.append('commit', input.commit);
|
|
733
|
-
formData.append('sha256', input.sha256);
|
|
734
|
-
formData.append('iac', input.iac);
|
|
735
|
-
formData.append('infra', input.infra);
|
|
736
|
-
if (input.doc) {
|
|
737
|
-
formData.append('doc', input.doc);
|
|
738
|
-
}
|
|
739
|
-
if (input.visibility) {
|
|
740
|
-
formData.append('visibility', input.visibility);
|
|
741
|
-
}
|
|
742
|
-
if (input.onDeployPkg) {
|
|
743
|
-
formData.append('onDeployPkg', input.onDeployPkg);
|
|
744
|
-
}
|
|
745
|
-
if (input.onDeployVersion) {
|
|
746
|
-
formData.append('onDeployVersion', input.onDeployVersion);
|
|
747
|
-
}
|
|
748
|
-
const response = await fetch(`${this.config.url}/api/registry/packages`, {
|
|
749
|
-
body: formData,
|
|
750
|
-
headers: {
|
|
751
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
752
|
-
},
|
|
753
|
-
method: 'POST',
|
|
754
|
-
});
|
|
755
|
-
const result = await this.safeResponseJson(response);
|
|
756
|
-
if (!response.ok) {
|
|
757
|
-
// Handle validation errors (field-specific errors)
|
|
758
|
-
if (result.errors && typeof result.errors === 'object') {
|
|
759
|
-
const errorMessages = [];
|
|
760
|
-
// Add main error message if present
|
|
761
|
-
if (result.error) {
|
|
762
|
-
errorMessages.push(result.error, ''); // Empty line for separation
|
|
763
|
-
}
|
|
764
|
-
// Add field-specific errors
|
|
765
|
-
for (const [field, messages] of Object.entries(result.errors)) {
|
|
766
|
-
if (Array.isArray(messages)) {
|
|
767
|
-
errorMessages.push(`${field}: ${messages.join(', ')}`);
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
// Add help message if present
|
|
771
|
-
if (result.help) {
|
|
772
|
-
errorMessages.push('', `ℹ️ ${result.help}`);
|
|
773
|
-
}
|
|
774
|
-
return {
|
|
775
|
-
reason: errorMessages.join('\n'),
|
|
776
|
-
success: false,
|
|
777
|
-
};
|
|
778
|
-
}
|
|
779
|
-
// Handle other errors with more context
|
|
780
|
-
const errorMessages = [];
|
|
781
|
-
const errorMessage = result.error || 'Unknown error occurred';
|
|
782
|
-
// Add main error with context based on errorType or status code
|
|
783
|
-
if (result.errorType) {
|
|
784
|
-
errorMessages.push(`[${result.errorType}] ${errorMessage}`);
|
|
785
|
-
}
|
|
786
|
-
else {
|
|
787
|
-
// Fallback to status-based context
|
|
788
|
-
switch (response.status) {
|
|
789
|
-
case 401: {
|
|
790
|
-
errorMessages.push('Authentication failed. Please run `hereya login` to refresh your credentials.');
|
|
791
|
-
break;
|
|
792
|
-
}
|
|
793
|
-
case 403: {
|
|
794
|
-
errorMessages.push(`Permission denied: ${errorMessage}`);
|
|
795
|
-
break;
|
|
796
|
-
}
|
|
797
|
-
case 409: {
|
|
798
|
-
errorMessages.push(`Conflict: ${errorMessage}`);
|
|
799
|
-
break;
|
|
800
|
-
}
|
|
801
|
-
default: {
|
|
802
|
-
if (response.status >= 500) {
|
|
803
|
-
errorMessages.push(`Server error: ${errorMessage} (status ${response.status})`);
|
|
804
|
-
}
|
|
805
|
-
else {
|
|
806
|
-
errorMessages.push(errorMessage);
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
// Add help message if present
|
|
812
|
-
if (result.help) {
|
|
813
|
-
errorMessages.push('', `ℹ️ ${result.help}`);
|
|
814
|
-
}
|
|
815
|
-
// Add package info if present (helpful for debugging)
|
|
816
|
-
if (result.package) {
|
|
817
|
-
errorMessages.push('', `Package: ${result.package.name}@${result.package.version}`);
|
|
818
|
-
}
|
|
819
|
-
return {
|
|
820
|
-
reason: errorMessages.join('\n'),
|
|
821
|
-
success: false,
|
|
822
|
-
};
|
|
823
|
-
}
|
|
824
|
-
return {
|
|
825
|
-
package: result.package,
|
|
826
|
-
success: true,
|
|
827
|
-
};
|
|
107
|
+
publishPackage(input) {
|
|
108
|
+
return packagesPublish.publishPackage(this.config, input);
|
|
828
109
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
headers: {
|
|
832
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
833
|
-
},
|
|
834
|
-
method: 'DELETE',
|
|
835
|
-
});
|
|
836
|
-
if (!response.ok) {
|
|
837
|
-
return {
|
|
838
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
839
|
-
success: false,
|
|
840
|
-
};
|
|
841
|
-
}
|
|
842
|
-
const result = await response.json();
|
|
843
|
-
return {
|
|
844
|
-
success: true,
|
|
845
|
-
workspace: this.convertWorkspace(result.workspace),
|
|
846
|
-
};
|
|
110
|
+
removePackageFromWorkspace(input) {
|
|
111
|
+
return packagesWorkspace.removePackageFromWorkspace(this.config, input);
|
|
847
112
|
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
851
|
-
method: 'DELETE',
|
|
852
|
-
});
|
|
853
|
-
if (!response.ok) {
|
|
854
|
-
const error = await this.safeResponseJson(response);
|
|
855
|
-
return { reason: error.error || 'Failed to revoke executor token', success: false };
|
|
856
|
-
}
|
|
857
|
-
return { success: true };
|
|
113
|
+
revokeExecutorToken(input) {
|
|
114
|
+
return executorJobs.revokeExecutorToken(this.config, input);
|
|
858
115
|
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
formData.append('metadata', JSON.stringify(input.metadata));
|
|
862
|
-
const response = await fetch(`${this.config.url}/api/projects/${encodeURIComponent(input.project)}/metadata`, {
|
|
863
|
-
body: formData,
|
|
864
|
-
headers: {
|
|
865
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
866
|
-
},
|
|
867
|
-
method: 'POST',
|
|
868
|
-
});
|
|
869
|
-
if (!response.ok) {
|
|
870
|
-
return {
|
|
871
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
872
|
-
success: false,
|
|
873
|
-
};
|
|
874
|
-
}
|
|
875
|
-
return {
|
|
876
|
-
success: true,
|
|
877
|
-
};
|
|
116
|
+
saveProjectMetadata(input) {
|
|
117
|
+
return projects.saveProjectMetadata(this.config, input);
|
|
878
118
|
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
if (workspace) {
|
|
882
|
-
formData.append('workspace', workspace);
|
|
883
|
-
}
|
|
884
|
-
if (config.deploy) {
|
|
885
|
-
const deployArray = Object.entries(config.deploy).map(([name, { version }]) => ({ name, version })).sort((a, b) => a.name.localeCompare(b.name));
|
|
886
|
-
formData.append('deploy', JSON.stringify(deployArray));
|
|
887
|
-
}
|
|
888
|
-
if (config.packages) {
|
|
889
|
-
const packagesArray = Object.entries(config.packages).map(([name, { version }]) => ({ name, version })).sort((a, b) => a.name.localeCompare(b.name));
|
|
890
|
-
formData.append('packages', JSON.stringify(packagesArray));
|
|
891
|
-
}
|
|
892
|
-
const response = await fetch(`${this.config.url}/api/projects/${encodeURIComponent(config.project)}/state`, {
|
|
893
|
-
body: formData,
|
|
894
|
-
headers: {
|
|
895
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
896
|
-
},
|
|
897
|
-
method: 'POST',
|
|
898
|
-
});
|
|
899
|
-
if (!response.ok) {
|
|
900
|
-
throw new Error(JSON.stringify(await this.safeResponseJson(response)));
|
|
901
|
-
}
|
|
119
|
+
saveState(config, workspace) {
|
|
120
|
+
return state.saveState(this.config, config, workspace);
|
|
902
121
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
url.searchParams.append('q', input.query);
|
|
906
|
-
if (input.limit !== undefined) {
|
|
907
|
-
url.searchParams.append('limit', String(input.limit));
|
|
908
|
-
}
|
|
909
|
-
if (input.offset !== undefined) {
|
|
910
|
-
url.searchParams.append('offset', String(input.offset));
|
|
911
|
-
}
|
|
912
|
-
const response = await fetch(url, {
|
|
913
|
-
headers: {
|
|
914
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
915
|
-
},
|
|
916
|
-
method: 'GET',
|
|
917
|
-
});
|
|
918
|
-
const result = await this.safeResponseJson(response);
|
|
919
|
-
if (!response.ok) {
|
|
920
|
-
let errorMessage = result.error || 'Failed to search packages';
|
|
921
|
-
switch (response.status) {
|
|
922
|
-
case 400: {
|
|
923
|
-
errorMessage = `Invalid search query: ${errorMessage}`;
|
|
924
|
-
break;
|
|
925
|
-
}
|
|
926
|
-
case 401: {
|
|
927
|
-
errorMessage = 'Authentication failed. Please run `hereya login` to refresh your credentials.';
|
|
928
|
-
break;
|
|
929
|
-
}
|
|
930
|
-
case 500: {
|
|
931
|
-
errorMessage = `Server error: ${errorMessage}`;
|
|
932
|
-
break;
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
return {
|
|
936
|
-
reason: errorMessage,
|
|
937
|
-
success: false,
|
|
938
|
-
};
|
|
939
|
-
}
|
|
940
|
-
return {
|
|
941
|
-
hasMore: result.hasMore ?? false,
|
|
942
|
-
packages: result.packages || [],
|
|
943
|
-
success: true,
|
|
944
|
-
};
|
|
122
|
+
searchPackages(input) {
|
|
123
|
+
return packagesRegistry.searchPackages(this.config, input);
|
|
945
124
|
}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
formData.append('key', input.name);
|
|
949
|
-
formData.append('value', input.value);
|
|
950
|
-
formData.append('infrastructure', input.infrastructure);
|
|
951
|
-
const response = await fetch(`${this.config.url}/api/workspaces/${encodeURIComponent(input.workspace)}/env`, {
|
|
952
|
-
body: formData,
|
|
953
|
-
headers: {
|
|
954
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
955
|
-
},
|
|
956
|
-
method: 'POST',
|
|
957
|
-
});
|
|
958
|
-
if (!response.ok) {
|
|
959
|
-
return {
|
|
960
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
961
|
-
success: false,
|
|
962
|
-
};
|
|
963
|
-
}
|
|
964
|
-
return {
|
|
965
|
-
success: true,
|
|
966
|
-
};
|
|
125
|
+
setEnvVar(input) {
|
|
126
|
+
return workspaceEnv.setEnvVar(this.config, input);
|
|
967
127
|
}
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
formData.append('type', input.type);
|
|
971
|
-
formData.append('payload', JSON.stringify(input.payload));
|
|
972
|
-
const response = await fetch(`${this.config.url}/api/workspaces/${encodeURIComponent(input.workspace)}/jobs`, {
|
|
973
|
-
body: formData,
|
|
974
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
975
|
-
method: 'POST',
|
|
976
|
-
});
|
|
977
|
-
if (!response.ok) {
|
|
978
|
-
if (response.status === 401) {
|
|
979
|
-
return { reason: 'Unauthorized', success: false };
|
|
980
|
-
}
|
|
981
|
-
const error = await this.safeResponseJson(response);
|
|
982
|
-
return { reason: error.error || 'Failed to submit executor job', success: false };
|
|
983
|
-
}
|
|
984
|
-
const result = await response.json();
|
|
985
|
-
return { jobId: result.jobId, success: true };
|
|
128
|
+
submitExecutorJob(input) {
|
|
129
|
+
return executorJobs.submitExecutorJob(this.config, input);
|
|
986
130
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
headers: {
|
|
990
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
991
|
-
},
|
|
992
|
-
method: 'DELETE',
|
|
993
|
-
});
|
|
994
|
-
if (!response.ok) {
|
|
995
|
-
return {
|
|
996
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
997
|
-
success: false,
|
|
998
|
-
};
|
|
999
|
-
}
|
|
1000
|
-
return {
|
|
1001
|
-
success: true,
|
|
1002
|
-
};
|
|
131
|
+
unsetEnvVar(input) {
|
|
132
|
+
return workspaceEnv.unsetEnvVar(this.config, input);
|
|
1003
133
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
if (input.state !== undefined)
|
|
1007
|
-
body.state = input.state;
|
|
1008
|
-
if (input.env !== undefined)
|
|
1009
|
-
body.env = input.env;
|
|
1010
|
-
if (input.lastJobId !== undefined)
|
|
1011
|
-
body.lastJobId = input.lastJobId;
|
|
1012
|
-
const response = await fetch(`${this.config.url}/api/apps/${encodeURIComponent(input.name)}/deployments/${encodeURIComponent(input.workspace)}`, {
|
|
1013
|
-
body: JSON.stringify(body),
|
|
1014
|
-
headers: {
|
|
1015
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
1016
|
-
'Content-Type': 'application/json',
|
|
1017
|
-
},
|
|
1018
|
-
method: 'PATCH',
|
|
1019
|
-
});
|
|
1020
|
-
if (!response.ok) {
|
|
1021
|
-
const error = await this.safeResponseJson(response);
|
|
1022
|
-
return { reason: error.error || `Failed to update app deployment (status ${response.status})`, success: false };
|
|
1023
|
-
}
|
|
1024
|
-
return { success: true };
|
|
134
|
+
updateAppDeployment(input) {
|
|
135
|
+
return appsDeploy.updateAppDeployment(this.config, input);
|
|
1025
136
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
if (input.logs) {
|
|
1029
|
-
formData.append('logs', input.logs);
|
|
1030
|
-
}
|
|
1031
|
-
if (input.status) {
|
|
1032
|
-
formData.append('status', input.status);
|
|
1033
|
-
}
|
|
1034
|
-
if (input.result) {
|
|
1035
|
-
formData.append('result', JSON.stringify(input.result));
|
|
1036
|
-
}
|
|
1037
|
-
const response = await fetch(`${this.config.url}/api/executor/jobs/${encodeURIComponent(input.jobId)}`, {
|
|
1038
|
-
body: formData,
|
|
1039
|
-
headers: { 'Authorization': `Bearer ${this.config.accessToken}` },
|
|
1040
|
-
method: 'PATCH',
|
|
1041
|
-
});
|
|
1042
|
-
if (!response.ok) {
|
|
1043
|
-
if (response.status === 401) {
|
|
1044
|
-
return { reason: 'Unauthorized', success: false, unauthorized: true };
|
|
1045
|
-
}
|
|
1046
|
-
const error = await this.safeResponseJson(response);
|
|
1047
|
-
return { reason: error.error || 'Failed to update job', success: false };
|
|
1048
|
-
}
|
|
1049
|
-
return { success: true };
|
|
137
|
+
updateExecutorJob(input) {
|
|
138
|
+
return executorJobs.updateExecutorJob(this.config, input);
|
|
1050
139
|
}
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
if (input.profile !== undefined) {
|
|
1054
|
-
formData.append('profile', input.profile === null ? '' : input.profile);
|
|
1055
|
-
}
|
|
1056
|
-
if (input.hasExecutor !== undefined) {
|
|
1057
|
-
formData.append('hasExecutor', input.hasExecutor === null ? '' : String(input.hasExecutor));
|
|
1058
|
-
}
|
|
1059
|
-
if (input.isDeploy !== undefined) {
|
|
1060
|
-
formData.append('isDeploy', input.isDeploy === null ? '' : String(input.isDeploy));
|
|
1061
|
-
}
|
|
1062
|
-
const response = await fetch(`${this.config.url}/api/workspaces/${encodeURIComponent(input.name)}`, {
|
|
1063
|
-
body: formData,
|
|
1064
|
-
headers: {
|
|
1065
|
-
'Authorization': `Bearer ${this.config.accessToken}`,
|
|
1066
|
-
},
|
|
1067
|
-
method: 'PATCH',
|
|
1068
|
-
});
|
|
1069
|
-
if (!response.ok) {
|
|
1070
|
-
return {
|
|
1071
|
-
reason: JSON.stringify(await this.safeResponseJson(response)),
|
|
1072
|
-
success: false,
|
|
1073
|
-
};
|
|
1074
|
-
}
|
|
1075
|
-
const result = await response.json();
|
|
1076
|
-
return {
|
|
1077
|
-
success: true,
|
|
1078
|
-
workspace: this.convertWorkspace(result.workspace),
|
|
1079
|
-
};
|
|
1080
|
-
}
|
|
1081
|
-
convertWorkspace(workspace) {
|
|
1082
|
-
const env = {};
|
|
1083
|
-
if (workspace.packages) {
|
|
1084
|
-
for (const pkg of workspace.packages) {
|
|
1085
|
-
if (pkg.env) {
|
|
1086
|
-
for (const e of pkg.env) {
|
|
1087
|
-
env[e.key] = `${e.infrastructure}:${e.value}`;
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
if (workspace.env) {
|
|
1093
|
-
for (const e of workspace.env) {
|
|
1094
|
-
env[e.key] = `${e.infrastructure}:${e.value}`;
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
const packages = {};
|
|
1098
|
-
if (workspace.packages) {
|
|
1099
|
-
for (const pkg of workspace.packages) {
|
|
1100
|
-
packages[pkg.name] = {
|
|
1101
|
-
parameters: pkg.parameters,
|
|
1102
|
-
version: pkg.version,
|
|
1103
|
-
};
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
let ownPackages;
|
|
1107
|
-
if (workspace.ownPackages) {
|
|
1108
|
-
ownPackages = {};
|
|
1109
|
-
for (const pkg of workspace.ownPackages) {
|
|
1110
|
-
ownPackages[pkg.name] = {
|
|
1111
|
-
parameters: pkg.parameters,
|
|
1112
|
-
version: pkg.version,
|
|
1113
|
-
};
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
return {
|
|
1117
|
-
env,
|
|
1118
|
-
hasExecutor: workspace.hasExecutor ?? undefined,
|
|
1119
|
-
id: workspace.id,
|
|
1120
|
-
isDeploy: workspace.isDeploy,
|
|
1121
|
-
mirrorOf: workspace.mirrorOf?.name,
|
|
1122
|
-
name: workspace.name,
|
|
1123
|
-
...(ownPackages === undefined ? {} : { ownPackages }),
|
|
1124
|
-
packages,
|
|
1125
|
-
profile: workspace.profile === null ? undefined : workspace.profile,
|
|
1126
|
-
};
|
|
1127
|
-
}
|
|
1128
|
-
async safeResponseJson(response) {
|
|
1129
|
-
const text = await response.text();
|
|
1130
|
-
try {
|
|
1131
|
-
return JSON.parse(text);
|
|
1132
|
-
}
|
|
1133
|
-
catch {
|
|
1134
|
-
return { error: text || 'Unknown error' };
|
|
1135
|
-
}
|
|
140
|
+
updateWorkspace(input) {
|
|
141
|
+
return workspaces.updateWorkspace(this.config, input);
|
|
1136
142
|
}
|
|
1137
143
|
}
|