@pega/custom-dx-components 8.8.10 → 8.8.11
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/package.json +2 -1
- package/src/auth.js +587 -553
- package/src/constants.js +18 -7
- package/src/tasks/authenticate/helper.js +76 -13
- package/src/tasks/authenticate/index.js +20 -2
- package/src/tasks/init/template/package.json.mustache +1 -1
- package/src/tasks/init/template/tasks.config.json +6 -2
- package/src/tasks/publish/helper.js +71 -27
package/src/constants.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export const TASKS_CONFIG_JSON_FILENAME = 'tasks.config.json';
|
|
3
3
|
export const BUILD_CONFIG_JSON_FILENAME = 'build.config.json';
|
|
4
4
|
export const COMPONENTS_DIRECTORY_PATH = 'components-directory-path';
|
|
5
|
-
export const COMPONENTS_PATH = 'component'
|
|
5
|
+
export const COMPONENTS_PATH = 'component';
|
|
6
6
|
export const TOKEN_PATH = 'node_modules/@pega/custom-dx-components/.access_token';
|
|
7
7
|
export const OOTB_COMPONENTS = 'node_modules/@pega/custom-dx-components/.ootb_components';
|
|
8
8
|
|
|
@@ -15,18 +15,29 @@ export const INF_TOKEN_URL_V1 = 'PRRestService/oauth2/v1/token';
|
|
|
15
15
|
export const INF_AUTHORIZE_URL_V1 = 'PRRestService/oauth2/v1/authorize';
|
|
16
16
|
export const LP_TOKEN_URL = 'uas/oauth/token';
|
|
17
17
|
export const LP_AUTHORIZE_URL = 'uas/oauth/authorize';
|
|
18
|
-
export const LP_LIST_COMPONENT_SERVICE_REST_ENDPOINT =
|
|
19
|
-
|
|
18
|
+
export const LP_LIST_COMPONENT_SERVICE_REST_ENDPOINT =
|
|
19
|
+
'pegalaunchpad/c11n/v103/app/appstudiox/componentslist';
|
|
20
|
+
export const LP_PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT =
|
|
21
|
+
'pegalaunchpad/c11n/isolations/{isolationId}/v102/assetsUpdate';
|
|
20
22
|
|
|
21
23
|
export const FIELD_PATH = '/field';
|
|
22
24
|
export const TEMPLATE_PATH = '/template';
|
|
23
25
|
export const WIDGET_PATH = '/widget';
|
|
24
26
|
|
|
25
|
-
export const COMPONENT_PREFIX_FIELD_PATH =
|
|
26
|
-
export const COMPONENT_PREFIX_TEMPLATE_PATH =
|
|
27
|
-
export const COMPONENT_PREFIX_WIDGET_PATH =
|
|
27
|
+
export const COMPONENT_PREFIX_FIELD_PATH = 'field/';
|
|
28
|
+
export const COMPONENT_PREFIX_TEMPLATE_PATH = 'template/';
|
|
29
|
+
export const COMPONENT_PREFIX_WIDGET_PATH = 'widget/';
|
|
30
|
+
|
|
31
|
+
export const CATEGORY_CONSTELLATION = 'constellation';
|
|
28
32
|
|
|
29
|
-
export const
|
|
33
|
+
export const AUTHENTICATE_DEFAULTS = {
|
|
34
|
+
serverType: 'infinity',
|
|
35
|
+
server: 'https://localhost:1080/prweb',
|
|
36
|
+
clientId: '10095186356008396159',
|
|
37
|
+
grantType: 'authCode',
|
|
38
|
+
authService: 'pega',
|
|
39
|
+
redirectUri: 'https://localhost:4010/'
|
|
40
|
+
};
|
|
30
41
|
|
|
31
42
|
export const AUTHENTICATE_SCHEMA = {
|
|
32
43
|
serverType: [
|
|
@@ -1,30 +1,47 @@
|
|
|
1
1
|
/* eslint-disable import/prefer-default-export */
|
|
2
2
|
import { getPegaServerConfig } from '../../util.js';
|
|
3
3
|
|
|
4
|
-
import { AUTHENTICATE_SCHEMA } from '../../constants.js';
|
|
4
|
+
import { AUTHENTICATE_SCHEMA, AUTHENTICATE_DEFAULTS } from '../../constants.js';
|
|
5
5
|
|
|
6
6
|
export const getAuthQuestions = async (dxcbConfig) => {
|
|
7
7
|
const defaultPegaConfig = dxcbConfig;
|
|
8
|
-
const
|
|
8
|
+
const aAlwaysAsk = dxcbConfig['questions_askAlways'] ? dxcbConfig['questions_askAlways'].split(',') : [];
|
|
9
9
|
const aNeverAsk = dxcbConfig['questions_askNever'] ? dxcbConfig['questions_askNever'].split(',') : [];
|
|
10
|
+
const aAskOnce = dxcbConfig['questions_askOnce'] ? dxcbConfig['questions_askOnce'].split(',') : [];
|
|
11
|
+
const aAskedOnce = dxcbConfig['questions_askedOnce'] ? dxcbConfig['questions_askedOnce'].split(',') : [];
|
|
12
|
+
|
|
13
|
+
// Ask if various must, never, once criteria are met
|
|
14
|
+
const askThisTime = (prop) => {
|
|
15
|
+
const bAsk = aAlwaysAsk.includes(prop) ||
|
|
16
|
+
(!aNeverAsk.includes(prop) && (aAskOnce.includes(prop) && !aAskedOnce.includes(prop)));
|
|
17
|
+
return bAsk;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const initAnswer = (prop, answers, defValue) => {
|
|
21
|
+
return askThisTime(prop, answers) ? undefined : (defaultPegaConfig[prop] ? defaultPegaConfig[prop] : defValue);
|
|
22
|
+
};
|
|
10
23
|
|
|
11
24
|
const initAnswers = (answers) => {
|
|
12
25
|
// Setup default answers (if they are present and non-empty)
|
|
13
|
-
answers.serverType =
|
|
14
|
-
answers.server =
|
|
15
|
-
answers.isolationId =
|
|
16
|
-
answers.clientId =
|
|
17
|
-
answers.grantType =
|
|
18
|
-
answers.
|
|
19
|
-
answers.
|
|
20
|
-
answers.
|
|
26
|
+
answers.serverType = initAnswer('serverType', answers, AUTHENTICATE_DEFAULTS.serverType);
|
|
27
|
+
answers.server = initAnswer('server', answers, AUTHENTICATE_DEFAULTS.server);
|
|
28
|
+
answers.isolationId = initAnswer('isolationId', answers);
|
|
29
|
+
answers.clientId = initAnswer('clientId', answers, AUTHENTICATE_DEFAULTS.clientId);
|
|
30
|
+
answers.grantType = initAnswer('grantType', answers, AUTHENTICATE_DEFAULTS.grantType);
|
|
31
|
+
answers.authService = initAnswer('authService', answers, AUTHENTICATE_DEFAULTS.authService);
|
|
32
|
+
answers.redirectUri = initAnswer('redirectUri', AUTHENTICATE_DEFAULTS.redirectUri);
|
|
33
|
+
answers.clientSecret = initAnswer('clientSecret', answers);
|
|
34
|
+
answers.user = initAnswer('user', answers);
|
|
35
|
+
answers.password = initAnswer('password', answers);
|
|
36
|
+
answers.aAsked = [];
|
|
21
37
|
};
|
|
22
38
|
|
|
23
39
|
const fnStandardWhen = (prop, answers) => {
|
|
24
|
-
|
|
25
|
-
|
|
40
|
+
const ask = askThisTime(prop) || !answers[prop];
|
|
41
|
+
if (ask) {
|
|
42
|
+
answers.aAsked.push(prop);
|
|
26
43
|
}
|
|
27
|
-
return
|
|
44
|
+
return ask;
|
|
28
45
|
};
|
|
29
46
|
|
|
30
47
|
return [
|
|
@@ -49,16 +66,30 @@ export const getAuthQuestions = async (dxcbConfig) => {
|
|
|
49
66
|
},
|
|
50
67
|
{
|
|
51
68
|
name: 'server',
|
|
69
|
+
type: 'input',
|
|
52
70
|
message: 'Enter pega server url',
|
|
53
71
|
default: defaultPegaConfig.server,
|
|
72
|
+
validate: value => {
|
|
73
|
+
if (value.trim()) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
return 'Pega server cannot be empty';
|
|
77
|
+
},
|
|
54
78
|
when: answers => {
|
|
55
79
|
return fnStandardWhen('server', answers);
|
|
56
80
|
}
|
|
57
81
|
},
|
|
58
82
|
{
|
|
59
83
|
name: 'isolationId',
|
|
84
|
+
tpye: 'input',
|
|
60
85
|
message: 'Enter isolation id',
|
|
61
86
|
default: defaultPegaConfig.isolationId,
|
|
87
|
+
validate: value => {
|
|
88
|
+
if (value.trim()) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
return 'Launchpad isolationId cannot be empty';
|
|
92
|
+
},
|
|
62
93
|
when: answers => {
|
|
63
94
|
return answers.serverType === "launchpad" && fnStandardWhen('isolationId', answers);
|
|
64
95
|
}
|
|
@@ -81,8 +112,39 @@ export const getAuthQuestions = async (dxcbConfig) => {
|
|
|
81
112
|
return fnStandardWhen('grantType', answers);
|
|
82
113
|
}
|
|
83
114
|
},
|
|
115
|
+
{
|
|
116
|
+
name: 'authService',
|
|
117
|
+
type: 'input',
|
|
118
|
+
message: 'Enter authentication service alias',
|
|
119
|
+
default: defaultPegaConfig.authService,
|
|
120
|
+
validate: value => {
|
|
121
|
+
if (value.trim()) {
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
return 'Authentication service alias cannot be empty';
|
|
125
|
+
},
|
|
126
|
+
when: answers => {
|
|
127
|
+
return answers.serverType === "infinity" && answers.grantType === "authCode" && fnStandardWhen('authService', answers);
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'redirectUri',
|
|
132
|
+
type: 'input',
|
|
133
|
+
message: 'Enter valid redirect Uri within OAuth 2.0 client reg reccord',
|
|
134
|
+
default: defaultPegaConfig.redirectUri,
|
|
135
|
+
validate: value => {
|
|
136
|
+
if (value.trim()) {
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
return 'Redirect URI cannot be empty';
|
|
140
|
+
},
|
|
141
|
+
when: answers => {
|
|
142
|
+
return answers.serverType === "infinity" && answers.grantType === "authCode" && fnStandardWhen('redirectUri', answers);
|
|
143
|
+
}
|
|
144
|
+
},
|
|
84
145
|
{
|
|
85
146
|
name: 'user',
|
|
147
|
+
type: 'input',
|
|
86
148
|
message: 'Enter user id',
|
|
87
149
|
default: defaultPegaConfig.user,
|
|
88
150
|
validate: (value, answers) => {
|
|
@@ -112,6 +174,7 @@ export const getAuthQuestions = async (dxcbConfig) => {
|
|
|
112
174
|
},
|
|
113
175
|
{
|
|
114
176
|
name: 'clientId',
|
|
177
|
+
type: 'input',
|
|
115
178
|
message: 'Enter clientId',
|
|
116
179
|
default: defaultPegaConfig.clientId,
|
|
117
180
|
validate: value => {
|
|
@@ -144,8 +144,9 @@ export default async options => {
|
|
|
144
144
|
const questions = await getAuthQuestions(serverConfig);
|
|
145
145
|
// console.log(`questions: ${JSON.stringify(questions)}`);
|
|
146
146
|
const answers = await inquirer.prompt(questions);
|
|
147
|
-
const
|
|
148
|
-
|
|
147
|
+
const aAsked = answers.aAsked;
|
|
148
|
+
delete answers.aAsked;
|
|
149
|
+
const aProps = ['serverType', 'server', 'isolationId', 'clientId', 'grantType', 'authService', 'redirectUri', 'clientSecret', 'user', 'password'];
|
|
149
150
|
const isLaunchPad = answers.serverType === "launchpad";
|
|
150
151
|
let bWriteUpdate = false;
|
|
151
152
|
for (let i = 0; i < aProps.length; i += 1) {
|
|
@@ -161,6 +162,23 @@ export default async options => {
|
|
|
161
162
|
}
|
|
162
163
|
}
|
|
163
164
|
}
|
|
165
|
+
// Update the askedOnce array based on askOnce criteria
|
|
166
|
+
const aAskOnce = serverConfig['questions_askOnce'] ? serverConfig['questions_askOnce'].split(',') : [];
|
|
167
|
+
const aAskedOnce = serverConfig['questions_askedOnce'] ? serverConfig['questions_askedOnce'].split(',') : [];
|
|
168
|
+
let bAskedOnceUpdated = false;
|
|
169
|
+
for (let j = 0; j < aAsked.length; j += 1) {
|
|
170
|
+
const prop = aAsked[j];
|
|
171
|
+
if (aAskOnce.includes(prop) && !aAskedOnce.includes(prop)) {
|
|
172
|
+
// Add entries we want to only ask once to the asked list if appropriate
|
|
173
|
+
aAskedOnce.push(prop);
|
|
174
|
+
bAskedOnceUpdated = true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// If askedOnce array was updated we need to update value in config
|
|
178
|
+
if (bAskedOnceUpdated) {
|
|
179
|
+
serverConfig['questions_askedOnce'] = aAskedOnce.join(',');
|
|
180
|
+
bWriteUpdate = true;
|
|
181
|
+
}
|
|
164
182
|
|
|
165
183
|
try {
|
|
166
184
|
// console.log(`serverConfig: ${JSON.stringify(serverConfig)}`);
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@pega/configs": "^0.5.3",
|
|
59
|
-
"@pega/custom-dx-components": "^8.8.
|
|
59
|
+
"@pega/custom-dx-components": "^8.8.11",
|
|
60
60
|
"@pega/eslint-config": "^0.3.2",
|
|
61
61
|
"@storybook/addon-actions": "^6.5.12",
|
|
62
62
|
"@storybook/addon-essentials": "^6.5.12",
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
"clientSecret": "",
|
|
13
13
|
"grantType": "authCode",
|
|
14
14
|
"redirectUri": "https://localhost:4010/",
|
|
15
|
+
"authService_comment": "Infinity authentication service alias (when grantType is set to 'authCode')",
|
|
16
|
+
"authService": "pega",
|
|
15
17
|
"cert_and_key_comment": "Path to SSL certificate file and SSL key file to use when starting local HTTPS server",
|
|
16
18
|
"cert_and_key_comment2": "Needed only when using 'authCode' grantType and redirectUri begins with 'https://localhost'",
|
|
17
19
|
"cert": "./keys/dxcb.crt",
|
|
@@ -19,9 +21,11 @@
|
|
|
19
21
|
"user_and_password_comment": "useful primarily when grantType is set to 'passwordCreds'",
|
|
20
22
|
"user": "",
|
|
21
23
|
"password": "",
|
|
22
|
-
"questions_comment": "useful for designating
|
|
24
|
+
"questions_comment": "useful for designating how frequently questions should be asked during npm run authenticate",
|
|
23
25
|
"questions_askAlways": "",
|
|
24
|
-
"questions_askNever": ""
|
|
26
|
+
"questions_askNever": "",
|
|
27
|
+
"questions_askOnce": "server,authService",
|
|
28
|
+
"questions_askedOnce": ""
|
|
25
29
|
},
|
|
26
30
|
"component": {
|
|
27
31
|
"library": "Extensions",
|
|
@@ -13,7 +13,11 @@ import {
|
|
|
13
13
|
getPegaServerConfig,
|
|
14
14
|
validateRulesetVersion
|
|
15
15
|
} from '../../util.js';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT,
|
|
18
|
+
LP_PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT,
|
|
19
|
+
TOKEN_PATH
|
|
20
|
+
} from '../../constants.js';
|
|
17
21
|
|
|
18
22
|
export const getPublishComponentQuestions = async () => {
|
|
19
23
|
const components = await getComponents();
|
|
@@ -35,6 +39,9 @@ export const getPublishComponentQuestions = async () => {
|
|
|
35
39
|
return true;
|
|
36
40
|
}
|
|
37
41
|
return 'Ruleset name cannot be empty';
|
|
42
|
+
},
|
|
43
|
+
when: answers => {
|
|
44
|
+
return answers.serverType === 'infinity';
|
|
38
45
|
}
|
|
39
46
|
},
|
|
40
47
|
{
|
|
@@ -46,12 +53,16 @@ export const getPublishComponentQuestions = async () => {
|
|
|
46
53
|
return true;
|
|
47
54
|
}
|
|
48
55
|
return 'Please provide compatible version e.g 01-01-01';
|
|
56
|
+
},
|
|
57
|
+
when: answers => {
|
|
58
|
+
return answers.serverType === 'infinity';
|
|
49
59
|
}
|
|
50
60
|
},
|
|
51
61
|
{
|
|
52
62
|
name: 'sourceMap',
|
|
53
63
|
message: 'Generate source map ?',
|
|
54
64
|
default: defaultPegaConfig.sourceMap,
|
|
65
|
+
// eslint-disable-next-line sonarjs/no-redundant-boolean
|
|
55
66
|
when: () => false && !process.env.SOURCE_MAP
|
|
56
67
|
},
|
|
57
68
|
{
|
|
@@ -86,37 +97,65 @@ export const zipComponent = async componentKey => {
|
|
|
86
97
|
};
|
|
87
98
|
|
|
88
99
|
export const publishComponentToServer = async data => {
|
|
89
|
-
const { configContent, zipContent,
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
+
const { configContent, zipContent, rulesetName, rulesetVersion } = data;
|
|
101
|
+
|
|
102
|
+
const defaultPegaServerConfig = await getPegaServerConfig();
|
|
103
|
+
const { serverType, isolationId } = defaultPegaServerConfig;
|
|
104
|
+
const isLaunchpad = serverType === 'launchpad';
|
|
105
|
+
const launchpadRestEndpoint = LP_PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT.replace(
|
|
106
|
+
'{isolationId}',
|
|
107
|
+
isolationId
|
|
108
|
+
);
|
|
109
|
+
let apiBody;
|
|
110
|
+
|
|
111
|
+
if (isLaunchpad) {
|
|
112
|
+
apiBody = {
|
|
113
|
+
type: 'CustomComponent',
|
|
114
|
+
zipContent,
|
|
115
|
+
componentName: JSON.parse(configContent).componentKey,
|
|
116
|
+
pxUpdateDateTime: '',
|
|
117
|
+
environmentID: defaultPegaServerConfig.isolationId
|
|
118
|
+
};
|
|
119
|
+
} else {
|
|
120
|
+
apiBody = {
|
|
121
|
+
configContent,
|
|
122
|
+
zipContent,
|
|
123
|
+
componentKey: JSON.parse(configContent).componentKey,
|
|
124
|
+
publishFor: 'constellation',
|
|
125
|
+
rulesetName,
|
|
126
|
+
rulesetVersion,
|
|
127
|
+
category: ''
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
100
131
|
const defaultPegaConfig = await getPegaServerConfig();
|
|
101
132
|
const url = constructCompleteUrl(
|
|
102
133
|
defaultPegaConfig.server,
|
|
103
|
-
PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT
|
|
134
|
+
isLaunchpad ? launchpadRestEndpoint : PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT
|
|
104
135
|
);
|
|
136
|
+
|
|
105
137
|
try {
|
|
106
138
|
const OauthData = fs.readFileSync(TOKEN_PATH, 'utf8');
|
|
107
139
|
if (OauthData) {
|
|
108
140
|
const {
|
|
109
141
|
access_token: accessToken,
|
|
110
|
-
token_type: tokenType
|
|
111
|
-
refresh_token: refreshToken
|
|
142
|
+
token_type: tokenType
|
|
143
|
+
// refresh_token: refreshToken
|
|
112
144
|
} = JSON.parse(OauthData);
|
|
113
145
|
let status = 500;
|
|
146
|
+
const headers = {};
|
|
147
|
+
|
|
148
|
+
if (isLaunchpad) {
|
|
149
|
+
headers.cookie = `Pega-AAT=${accessToken}`;
|
|
150
|
+
headers['Content-Type'] = 'application/json';
|
|
151
|
+
} else {
|
|
152
|
+
headers.Authorization = `${tokenType} ${accessToken}`;
|
|
153
|
+
}
|
|
154
|
+
|
|
114
155
|
fetch(url, {
|
|
115
156
|
method: 'POST',
|
|
116
157
|
agent: new https.Agent({ rejectUnauthorized: false }),
|
|
117
|
-
headers
|
|
118
|
-
Authorization: `${tokenType} ${accessToken}`
|
|
119
|
-
},
|
|
158
|
+
headers,
|
|
120
159
|
body: JSON.stringify(apiBody)
|
|
121
160
|
})
|
|
122
161
|
.then(response => {
|
|
@@ -124,27 +163,32 @@ export const publishComponentToServer = async data => {
|
|
|
124
163
|
return response.text();
|
|
125
164
|
})
|
|
126
165
|
.then(resp => {
|
|
127
|
-
const respData = JSON.parse(resp);
|
|
166
|
+
const respData = isLaunchpad ? resp : JSON.parse(resp);
|
|
128
167
|
if (status === 401) {
|
|
129
168
|
throw new Error(
|
|
130
169
|
'Error occurred in authentication. Please regenerate using authenticate'
|
|
131
170
|
);
|
|
132
171
|
// console.log(accessTokenUri, refreshToken);
|
|
133
172
|
/* TODO - Handle refresh_token */
|
|
134
|
-
} else if (status
|
|
135
|
-
console.log(chalk.bold.green(`Success : ${respData.message}`));
|
|
173
|
+
} else if (status === 200 || status === 201) {
|
|
174
|
+
console.log(chalk.bold.green(`Success : ${isLaunchpad ? respData : respData.message}`));
|
|
136
175
|
} else {
|
|
137
176
|
throw new Error(`${respData.message}`);
|
|
138
177
|
}
|
|
139
178
|
})
|
|
140
|
-
.catch(
|
|
141
|
-
if (e.code
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
179
|
+
.catch(e => {
|
|
180
|
+
if (e.code === 'ECONNREFUSED') {
|
|
181
|
+
// eslint-disable-next-line prefer-promise-reject-errors
|
|
182
|
+
Promise.reject(
|
|
183
|
+
`${chalk.bold.red(
|
|
184
|
+
'Error occurred in authentication. Please regenerate using authenticate'
|
|
185
|
+
)}`
|
|
186
|
+
);
|
|
187
|
+
} else {
|
|
188
|
+
// eslint-disable-next-line prefer-promise-reject-errors
|
|
145
189
|
Promise.reject(`${chalk.bold.red(e)}`);
|
|
146
190
|
}
|
|
147
|
-
})
|
|
191
|
+
});
|
|
148
192
|
} else {
|
|
149
193
|
throw new Error(`Error occurred in authentication. Please regenerate using authenticate`);
|
|
150
194
|
}
|