@celonis/content-cli 1.16.0 → 1.17.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/commands/sdk/module.js +54 -0
- package/commands/sdk/sdk-api.js +48 -0
- package/commands/sdk/sdk.service.js +64 -0
- package/core/http/http-client.js +15 -0
- package/core/profile/profile.service.js +10 -3
- package/lib/commands/sdk/module.d.ts +8 -0
- package/lib/commands/sdk/sdk-api.d.ts +11 -0
- package/lib/commands/sdk/sdk.service.d.ts +10 -0
- package/lib/core/http/http-client.d.ts +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
(function (factory) {
|
|
11
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
12
|
+
var v = factory(require, exports);
|
|
13
|
+
if (v !== undefined) module.exports = v;
|
|
14
|
+
}
|
|
15
|
+
else if (typeof define === "function" && define.amd) {
|
|
16
|
+
define(["require", "exports", "../../core/command/module-handler", "./sdk.service"], factory);
|
|
17
|
+
}
|
|
18
|
+
})(function (require, exports) {
|
|
19
|
+
"use strict";
|
|
20
|
+
const module_handler_1 = require("../../core/command/module-handler");
|
|
21
|
+
const sdk_service_1 = require("./sdk.service");
|
|
22
|
+
class Module extends module_handler_1.IModule {
|
|
23
|
+
register(context, configurator) {
|
|
24
|
+
const sdkCommand = configurator
|
|
25
|
+
.command("sdk")
|
|
26
|
+
.beta()
|
|
27
|
+
.description("Implement custom apps for Codespace assets using the Celonis SDK");
|
|
28
|
+
sdkCommand
|
|
29
|
+
.command("download")
|
|
30
|
+
.beta()
|
|
31
|
+
.description("Download the latest Celonis SDK generated for a Codespace asset")
|
|
32
|
+
.requiredOption("--appId <appId>", "Identifier of the app to download the SDK for")
|
|
33
|
+
.action(this.downloadSdk);
|
|
34
|
+
sdkCommand
|
|
35
|
+
.command("publish")
|
|
36
|
+
.beta()
|
|
37
|
+
.description("Publish a build of a custom app as a new version of its Codespace asset")
|
|
38
|
+
.requiredOption("--appId <appId>", "Identifier of the app to publish the build for")
|
|
39
|
+
.requiredOption("--dist <dist>", "Directory containing the build of the app")
|
|
40
|
+
.action(this.publishApp);
|
|
41
|
+
}
|
|
42
|
+
downloadSdk(context, command, options) {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
yield new sdk_service_1.SdkService(context).downloadSdk(options.appId);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
publishApp(context, command, options) {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
yield new sdk_service_1.SdkService(context).publishApp(options.appId, options.dist);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return Module;
|
|
54
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
(function (factory) {
|
|
11
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
12
|
+
var v = factory(require, exports);
|
|
13
|
+
if (v !== undefined) module.exports = v;
|
|
14
|
+
}
|
|
15
|
+
else if (typeof define === "function" && define.amd) {
|
|
16
|
+
define(["require", "exports", "../../core/utils/logger"], factory);
|
|
17
|
+
}
|
|
18
|
+
})(function (require, exports) {
|
|
19
|
+
"use strict";
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.SdkApi = void 0;
|
|
22
|
+
const logger_1 = require("../../core/utils/logger");
|
|
23
|
+
class SdkApi {
|
|
24
|
+
constructor(context) {
|
|
25
|
+
this.httpClient = () => context.httpClient;
|
|
26
|
+
}
|
|
27
|
+
downloadSdk(appId) {
|
|
28
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
return this.httpClient()
|
|
30
|
+
.getFile(`/pro-code-app-manager/api/npm/@celonis-sdk/${appId}/-/${appId}-latest.tgz`)
|
|
31
|
+
.catch((e) => {
|
|
32
|
+
const problem = `Problem downloading SDK for app ${appId}`;
|
|
33
|
+
throw new logger_1.FatalError(e ? `${problem}: ${e}` : problem);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
publishApp(appId, bundle) {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
return this.httpClient()
|
|
40
|
+
.postBinary(`/pro-code-app-manager/api/codespace/apps/${appId}/publish`, bundle, "application/zip")
|
|
41
|
+
.catch((e) => {
|
|
42
|
+
throw new logger_1.FatalError(`Problem publishing app ${appId}: ${e}`);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.SdkApi = SdkApi;
|
|
48
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
(function (factory) {
|
|
11
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
12
|
+
var v = factory(require, exports);
|
|
13
|
+
if (v !== undefined) module.exports = v;
|
|
14
|
+
}
|
|
15
|
+
else if (typeof define === "function" && define.amd) {
|
|
16
|
+
define(["require", "exports", "node:fs", "node:path", "adm-zip", "./sdk-api", "../../core/utils/logger"], factory);
|
|
17
|
+
}
|
|
18
|
+
})(function (require, exports) {
|
|
19
|
+
"use strict";
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.SdkService = void 0;
|
|
22
|
+
const fs = require("node:fs");
|
|
23
|
+
const path = require("node:path");
|
|
24
|
+
const AdmZip = require("adm-zip");
|
|
25
|
+
const sdk_api_1 = require("./sdk-api");
|
|
26
|
+
const logger_1 = require("../../core/utils/logger");
|
|
27
|
+
class SdkService {
|
|
28
|
+
constructor(context) {
|
|
29
|
+
this.sdkApi = new sdk_api_1.SdkApi(context);
|
|
30
|
+
}
|
|
31
|
+
downloadSdk(appId) {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
const sdk = yield this.sdkApi.downloadSdk(appId);
|
|
34
|
+
const sdkDirectory = path.resolve(process.cwd(), SdkService.SDK_DIRECTORY);
|
|
35
|
+
fs.rmSync(sdkDirectory, { recursive: true, force: true });
|
|
36
|
+
fs.mkdirSync(sdkDirectory, { recursive: true });
|
|
37
|
+
const sdkFile = path.join(SdkService.SDK_DIRECTORY, `${appId}.tgz`);
|
|
38
|
+
fs.writeFileSync(path.resolve(process.cwd(), sdkFile), sdk);
|
|
39
|
+
logger_1.logger.info(`SDK downloaded successfully: ${sdkFile}`);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
publishApp(appId, dist) {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
const distDirectory = path.resolve(process.cwd(), dist);
|
|
45
|
+
this.requireDirectory(distDirectory);
|
|
46
|
+
const bundle = this.compressDirectory(distDirectory);
|
|
47
|
+
const { version } = yield this.sdkApi.publishApp(appId, bundle);
|
|
48
|
+
logger_1.logger.info(`App published successfully as version '${version}'`);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
requireDirectory(directory) {
|
|
52
|
+
if (!fs.existsSync(directory) || !fs.statSync(directory).isDirectory()) {
|
|
53
|
+
throw new logger_1.FatalError(`The dist directory ${directory} does not exist or is no directory`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
compressDirectory(directory) {
|
|
57
|
+
const zip = new AdmZip();
|
|
58
|
+
zip.addLocalFolder(directory);
|
|
59
|
+
return zip.toBuffer();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.SdkService = SdkService;
|
|
63
|
+
SdkService.SDK_DIRECTORY = ".celonis-sdk";
|
|
64
|
+
});
|
package/core/http/http-client.js
CHANGED
|
@@ -133,6 +133,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
133
133
|
});
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
|
+
postBinary(url, body, contentType) {
|
|
137
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
138
|
+
return new Promise((resolve, reject) => {
|
|
139
|
+
this.axios.post(this.resolveUrl(url), body, {
|
|
140
|
+
headers: this.buildHeaders(contentType)
|
|
141
|
+
}).then(response => {
|
|
142
|
+
this.handleResponse(response, resolve, reject);
|
|
143
|
+
}).catch(err => {
|
|
144
|
+
this.handleError(err, resolve, reject);
|
|
145
|
+
});
|
|
146
|
+
}).catch(e => {
|
|
147
|
+
throw new logger_1.FatalError(e);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
136
151
|
put(url, body) {
|
|
137
152
|
return __awaiter(this, void 0, void 0, function* () {
|
|
138
153
|
return new Promise((resolve, reject) => {
|
|
@@ -36,6 +36,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
36
36
|
const OAUTH_SCOPES = ["studio", "package-manager", "integration.data-pools", "action-engine.projects"];
|
|
37
37
|
/** Device code fallback: try without action-engine.projects if all 4 scopes fail. */
|
|
38
38
|
const DEVICE_CODE_SCOPES_WITHOUT_ACTION_ENGINE = ["studio", "package-manager", "integration.data-pools"];
|
|
39
|
+
/** First attempt for both auth flows: all scopes plus the pro-code-app-manager scopes, which are not yet available on every environment. */
|
|
40
|
+
const OAUTH_SCOPES_WITH_PRO_CODE = [...OAUTH_SCOPES, "pro-code-app-manager.sdk:read", "pro-code-app-manager.publish"];
|
|
39
41
|
class ProfileService {
|
|
40
42
|
constructor() {
|
|
41
43
|
this.profileContainerPath = path.resolve(homedir, ".celonis-content-cli-profiles");
|
|
@@ -216,13 +218,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
216
218
|
}
|
|
217
219
|
}
|
|
218
220
|
break;
|
|
219
|
-
case profile_interface_1.ProfileType.DEVICE_CODE:
|
|
221
|
+
case profile_interface_1.ProfileType.DEVICE_CODE: {
|
|
220
222
|
const deviceCodeIssuer = yield openid_client_1.Issuer.discover(profile.team);
|
|
221
223
|
const deviceCodeOAuthClient = new deviceCodeIssuer.Client({
|
|
222
224
|
client_id: "content-cli",
|
|
223
225
|
token_endpoint_auth_method: "none",
|
|
224
226
|
});
|
|
225
|
-
const deviceCodeScopeAttempts = [
|
|
227
|
+
const deviceCodeScopeAttempts = [
|
|
228
|
+
OAUTH_SCOPES_WITH_PRO_CODE,
|
|
229
|
+
OAUTH_SCOPES,
|
|
230
|
+
DEVICE_CODE_SCOPES_WITHOUT_ACTION_ENGINE,
|
|
231
|
+
];
|
|
226
232
|
let deviceCodeSuccess = false;
|
|
227
233
|
for (const scopeList of deviceCodeScopeAttempts) {
|
|
228
234
|
try {
|
|
@@ -245,6 +251,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
245
251
|
throw new logger_1.FatalError("Device code authorization failed. The provided team or requested scopes may be invalid.");
|
|
246
252
|
}
|
|
247
253
|
break;
|
|
254
|
+
}
|
|
248
255
|
case profile_interface_1.ProfileType.CLIENT_CREDENTIALS:
|
|
249
256
|
const clientCredentialsIssuer = yield openid_client_1.Issuer.discover(profile.team);
|
|
250
257
|
const basicResult = yield this.tryClientCredentialsGrant(clientCredentialsIssuer, profile, profile_interface_1.ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
|
|
@@ -411,7 +418,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
411
418
|
client_secret: profile.clientSecret,
|
|
412
419
|
token_endpoint_auth_method: tokenEndpointAuthMethod,
|
|
413
420
|
});
|
|
414
|
-
const scopeAttempts = this.getScopeCombinationsOrderedBySize(OAUTH_SCOPES);
|
|
421
|
+
const scopeAttempts = [OAUTH_SCOPES_WITH_PRO_CODE, ...this.getScopeCombinationsOrderedBySize(OAUTH_SCOPES)];
|
|
415
422
|
for (const scopeList of scopeAttempts) {
|
|
416
423
|
try {
|
|
417
424
|
const tokenSet = yield client.grant({
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Configurator, IModule } from "../../core/command/module-handler";
|
|
2
|
+
import { Context } from "../../core/command/cli-context";
|
|
3
|
+
declare class Module extends IModule {
|
|
4
|
+
register(context: Context, configurator: Configurator): void;
|
|
5
|
+
private downloadSdk;
|
|
6
|
+
private publishApp;
|
|
7
|
+
}
|
|
8
|
+
export = Module;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Context } from "../../core/command/cli-context";
|
|
3
|
+
export interface SdkPublishResponse {
|
|
4
|
+
version: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class SdkApi {
|
|
7
|
+
private readonly httpClient;
|
|
8
|
+
constructor(context: Context);
|
|
9
|
+
downloadSdk(appId: string): Promise<Buffer>;
|
|
10
|
+
publishApp(appId: string, bundle: Buffer): Promise<SdkPublishResponse>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Context } from "../../core/command/cli-context";
|
|
2
|
+
export declare class SdkService {
|
|
3
|
+
static readonly SDK_DIRECTORY = ".celonis-sdk";
|
|
4
|
+
private readonly sdkApi;
|
|
5
|
+
constructor(context: Context);
|
|
6
|
+
downloadSdk(appId: string): Promise<void>;
|
|
7
|
+
publishApp(appId: string, dist: string): Promise<void>;
|
|
8
|
+
private requireDirectory;
|
|
9
|
+
private compressDirectory;
|
|
10
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import * as FormData from "form-data";
|
|
2
3
|
import { Context } from "../command/cli-context";
|
|
3
4
|
/**
|
|
@@ -16,6 +17,7 @@ export declare class HttpClient {
|
|
|
16
17
|
getFile(url: string): Promise<any>;
|
|
17
18
|
postFile(url: string, formData: FormData, parameters?: {}): Promise<any>;
|
|
18
19
|
post(url: string, body: any): Promise<any>;
|
|
20
|
+
postBinary(url: string, body: Buffer, contentType: string): Promise<any>;
|
|
19
21
|
put(url: string, body: object): Promise<any>;
|
|
20
22
|
delete(url: string): Promise<any>;
|
|
21
23
|
downloadFile(url: string): Promise<any>;
|