@pega/dx-component-builder-sdk 0.1.33 → 0.1.35

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pega/dx-component-builder-sdk",
3
- "version": "0.1.33",
3
+ "version": "0.1.35",
4
4
  "description": "Utility for building custom UI components",
5
5
  "bin": "./bin/index.js",
6
6
  "scripts": {
package/src/cli.js CHANGED
@@ -16,6 +16,7 @@ import {
16
16
  overrideAllComponents,
17
17
  publishComponent,
18
18
  publishAllComponents,
19
+ renameComponent,
19
20
  updateComponent,
20
21
  validate,
21
22
  upgrade
@@ -31,6 +32,7 @@ const TASKS = {
31
32
  MAP_ALL: "mapAll",
32
33
  PUBLISH: 'publish',
33
34
  PUBLISH_ALL: 'publishAll',
35
+ RENAME: 'rename',
34
36
  LIST: 'list',
35
37
  VALIDATE_SCHEMA: 'validateSchema',
36
38
  UPDATE: 'update',
@@ -92,6 +94,10 @@ export default async (args = []) => {
92
94
  publishAllComponents(options);
93
95
  break;
94
96
  }
97
+ case TASKS.RENAME: {
98
+ renameComponent(options);
99
+ break;
100
+ }
95
101
  case TASKS.BUILD: {
96
102
  buildComponent(options);
97
103
  break;
@@ -19,7 +19,7 @@ import { PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT, TOKEN_PATH, COMPONENT_SCHEMA,
19
19
 
20
20
 
21
21
  export const cleanUp = async () => {
22
- fs.rm('dist', { recursive: true }, err => {
22
+ fs.rm('dist/components', { recursive: true }, err => {
23
23
  if (err) {
24
24
  throw err;
25
25
  }
@@ -92,10 +92,10 @@ export const zipComponent = async (componentKey, category = CATEGORY_CUSTOM) =>
92
92
  const zipContent = zip.toBuffer().toString('base64');
93
93
 
94
94
  const configContent = Buffer.from(fs.readFileSync(`${srcDirectory}/config.json`)).toString();
95
- fs.rmd('dist', { recursive: true }, err => {
96
- if (err) {
97
- throw err;
98
- }
99
- });
95
+ // fs.rmd('dist/components', { recursive: true }, err => {
96
+ // if (err) {
97
+ // throw err;
98
+ // }
99
+ // });
100
100
  return { zipContent, configContent };
101
101
  };
@@ -13,7 +13,7 @@ import {
13
13
  import { COMPONENT_SCHEMA, CATEGORY_CUSTOM } from '../../constants.js';
14
14
 
15
15
  export const cleanUp = async () => {
16
- fs.rm('dist', { recursive: true }, err => {
16
+ fs.rm('dist/components', { recursive: true }, err => {
17
17
  if (err) {
18
18
  throw err;
19
19
  }
@@ -75,10 +75,10 @@ export const zipComponent = async (componentKey, category = CATEGORY_CUSTOM) =>
75
75
  const zipContent = zip.toBuffer().toString('base64');
76
76
 
77
77
  const configContent = Buffer.from(fs.readFileSync(`${srcDirectory}/config.json`)).toString();
78
- fs.rmd('dist', { recursive: true }, err => {
79
- if (err) {
80
- throw err;
81
- }
82
- });
78
+ // fs.rmd('dist/components', { recursive: true }, err => {
79
+ // if (err) {
80
+ // throw err;
81
+ // }
82
+ // });
83
83
  return { zipContent, configContent };
84
84
  };
@@ -11,27 +11,7 @@ import { getComponentDirectoryPath, showVersion, getOptionsCategory, getComponen
11
11
 
12
12
  import { CATEGORY_CUSTOM } from '../../constants.js';
13
13
 
14
- export default async options => {
15
- showVersion();
16
-
17
- const catQuestion = await getBuildCategory(options);
18
- const catAnwers = await inquirer.prompt(catQuestion);
19
-
20
- let category = catAnwers.category;
21
- if (category == null) {
22
- category = getOptionsCategory(options);
23
- }
24
-
25
- const components = await getComponentsObj(false, category);
26
- const questions = await getBuildComponentQuestions(category);
27
- const answers = await inquirer.prompt(questions);
28
- const { sourceMap, devBuild } = answers;
29
-
30
- let content = {
31
- ...answers
32
- };
33
-
34
- var componentKey;
14
+ export function getCustomTasks(componentKey, category, sourceMap, devBuild, content, options) {
35
15
 
36
16
  const customTasks = new Listr(
37
17
  [
@@ -71,6 +51,12 @@ export default async options => {
71
51
  }
72
52
  );
73
53
 
54
+ return customTasks;
55
+ }
56
+
57
+
58
+ export function getOverrideTasks(componentKey, category, sourceMap, devBuild, content, options) {
59
+
74
60
  const overrideTasks = new Listr(
75
61
  [
76
62
  {
@@ -97,12 +83,40 @@ export default async options => {
97
83
  }
98
84
  );
99
85
 
86
+ return overrideTasks;
87
+ }
88
+
89
+ export default async options => {
90
+ showVersion();
91
+
92
+ const catQuestion = await getBuildCategory(options);
93
+ const catAnwers = await inquirer.prompt(catQuestion);
94
+
95
+ let category = catAnwers.category;
96
+ if (category == null) {
97
+ category = getOptionsCategory(options);
98
+ }
99
+
100
+ const components = await getComponentsObj(false, category);
101
+ const questions = await getBuildComponentQuestions(category);
102
+ const answers = await inquirer.prompt(questions);
103
+ const { sourceMap, devBuild } = answers;
104
+
105
+ let content = {
106
+ ...answers
107
+ };
108
+
109
+ var componentKey;
110
+
100
111
 
101
112
  if (category === CATEGORY_CUSTOM) {
102
113
  for (var index in components) {
103
114
  componentKey = components[index].value;
104
115
  console.log(chalk.bold.green("Building: " + components[index].name));
105
- await customTasks.run().catch(err => {
116
+
117
+ let myCustomTasks = getCustomTasks(componentKey, category, sourceMap, devBuild, content, options);
118
+
119
+ await myCustomTasks.run().catch(err => {
106
120
  console.log(chalk.bold.red(err.toString()));
107
121
  });
108
122
  }
@@ -111,7 +125,10 @@ export default async options => {
111
125
  for (var index in components) {
112
126
  componentKey = components[index].value;
113
127
  console.log(chalk.bold.green("Building: " + components[index].name));
114
- await overrideTasks.run().catch(err => {
128
+
129
+ let myOverrideTasks = getOverrideTasks(componentKey, category, sourceMap, devBuild, content, options);
130
+
131
+ await mOverrideTasks.run().catch(err => {
115
132
  console.log(chalk.bold.red(err.toString()));
116
133
  });
117
134
  }
@@ -7,6 +7,7 @@ export { default as deleteAllComponents } from './delete-all/index.js';
7
7
  export { default as mapAllComponents } from './map-all/index.js';
8
8
  export { default as publishComponent } from './publish/index.js';
9
9
  export { default as publishAllComponents } from './publish-all/index.js';
10
+ export { default as renameComponent } from './rename/index.js';
10
11
  export { default as listComponents } from './list/index.js';
11
12
  export { default as updateComponent } from './update/index.js';
12
13
  export { default as validate } from './validator/index.js';
@@ -33,9 +33,6 @@ export const updateComponentMap = async (componentKey, category = CATEGORY_CUSTO
33
33
 
34
34
  let mapData = fs.readFileSync(pegaLocalComponentMapPath, { encoding: 'utf8' });
35
35
 
36
- let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
37
- data = JSON.parse(data);
38
-
39
36
  let importComponent = join(COMPONENTS_DIRECTORY_PATH, categoryDirectory, componentKey);
40
37
  importComponent = "./".concat(importComponent);
41
38
 
@@ -77,9 +74,6 @@ export const deleteFromComponentMap = async (componentKey, category = CATEGORY_C
77
74
 
78
75
  let mapData = fs.readFileSync(pegaLocalComponentMapPath, { encoding: 'utf8' });
79
76
 
80
- let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
81
- data = JSON.parse(data);
82
-
83
77
  let importComponent = join(COMPONENTS_DIRECTORY_PATH, categoryDirectory, componentKey);
84
78
  importComponent = "./".concat(importComponent);
85
79
 
@@ -101,3 +95,23 @@ export const deleteFromComponentMap = async (componentKey, category = CATEGORY_C
101
95
 
102
96
 
103
97
  };
98
+
99
+ export const renameComponentInMap = async (oldComponentKey, newComponentKey) => {
100
+ const pegaLocalComponentMapPath = path.join(path.resolve(), SDK_LOCAL_COMPONENT_MAP_FILENAME);
101
+
102
+ const oldComponentNameNoPrefix = removeComponentPrefix(oldComponentKey);
103
+ const oldComponentName = convertIntoPascalCase(oldComponentNameNoPrefix);
104
+
105
+ const newComponentNameNoPrefix = removeComponentPrefix(newComponentKey);
106
+ const newComponentName = convertIntoPascalCase(newComponentNameNoPrefix);
107
+
108
+ let mapData = fs.readFileSync(pegaLocalComponentMapPath, { encoding: 'utf8' });
109
+
110
+ if (mapData.indexOf(oldComponentName) >= 0) {
111
+ mapData = mapData.replaceAll(oldComponentName, newComponentName);
112
+ mapData = mapData.replaceAll(oldComponentNameNoPrefix, newComponentNameNoPrefix);
113
+ fs.writeFileSync(pegaLocalComponentMapPath, mapData, { encoding: 'utf8' });
114
+
115
+ }
116
+ }
117
+
@@ -138,7 +138,7 @@ export const zipComponent = async (componentKey, category = CATEGORY_CUSTOM) =>
138
138
  let configContent = "{ }";
139
139
  if (category === CATEGORY_CUSTOM || category === CATEGORY_CONSTELLATION) {
140
140
  configContent = Buffer.from(fs.readFileSync(`${srcDirectory}/config.json`)).toString();
141
- fs.rmdir('dist', { recursive: true }, err => {
141
+ fs.rmdir('dist/components', { recursive: true }, err => {
142
142
  if (err) {
143
143
  throw err;
144
144
  }
@@ -152,7 +152,7 @@ export const zipComponent = async (componentKey, category = CATEGORY_CUSTOM) =>
152
152
  else {
153
153
  if (fs.existsSync(configExtJson)) {
154
154
  configContent = Buffer.from(fs.readFileSync(`${srcDirectory}/config-ext.json`)).toString();
155
- fs.rmdir('dist', { recursive: true }, err => {
155
+ fs.rmdir('dist/components', { recursive: true }, err => {
156
156
  if (err) {
157
157
  throw err;
158
158
  }
@@ -162,7 +162,7 @@ export const zipComponent = async (componentKey, category = CATEGORY_CUSTOM) =>
162
162
  };
163
163
 
164
164
  export const cleanUp = async () => {
165
- fs.rm('dist', { recursive: true }, err => {
165
+ fs.rm('dist/components', { recursive: true }, err => {
166
166
  if (err) {
167
167
  throw err;
168
168
  }
@@ -0,0 +1,333 @@
1
+ import path from 'path';
2
+ import { URL, fileURLToPath } from 'url';
3
+ import fs from 'fs';
4
+ import { promisify } from 'util';
5
+ import { join } from 'path';
6
+
7
+ import inquirer from 'inquirer';
8
+ import ncp from 'ncp';
9
+ import chalk from 'chalk';
10
+
11
+ import { checkPathAccess, showVersion, getComponentsObj, getDirectoryFiles } from '../../util.js';
12
+ import { CATEGORY_CONSTELLATION,
13
+ CATEGORY_CUSTOM,
14
+ SDK_CONFIG_JSON_FILENAME,
15
+ DXCB_CONFIG,
16
+ DXCB_COMPONENT_DEFAULTS } from '../../constants.js';
17
+
18
+ import { renameComponentInMap } from '../map/map.js';
19
+
20
+
21
+ export const DXCB_CONFIG_INTERNAL_JSON_FILENAME = 'src/dxcb.config.json';
22
+
23
+ const pegaConfigJsonPath = path.join(path.resolve(), SDK_CONFIG_JSON_FILENAME);
24
+
25
+
26
+ import {
27
+ convertIntoPascalCase,
28
+ getComponentDirectoryPath,
29
+ getPegaConfig,
30
+ getComponentDefaults,
31
+ sanitize,
32
+ validateSemver
33
+ } from '../../util.js';
34
+ import { COMPONENT_SCHEMA } from '../../constants.js';
35
+
36
+ const copy = promisify(ncp);
37
+
38
+
39
+ export const updateConfig = async (
40
+ {
41
+ oldComponentKey,
42
+ newComponentKey,
43
+ library,
44
+ organization,
45
+ componentName,
46
+ componentLabel,
47
+ version,
48
+ description,
49
+ allowedApplications,
50
+ targetDirectory,
51
+ },
52
+ options,
53
+ onlyCompanion = false
54
+ ) => {
55
+
56
+ let configData = fs.readFileSync(join(targetDirectory, "/config.json"), { encoding: 'utf8' });
57
+ configData = configData && JSON.parse(configData);
58
+
59
+ configData.name = newComponentKey;
60
+ configData.label = componentLabel;
61
+ configData.organization = organization;
62
+ if (configData.componentKey) configData.componentKey = newComponentKey;
63
+ configData.library = library;
64
+ configData.version = version;
65
+ configData.description = (description != '') ? description : componentLabel;
66
+ configData.allowedApplications = allowedApplications;
67
+
68
+ // stringify "4", makes the json string look like JSON in the file, formated instead of a single line
69
+ fs.writeFileSync(join(targetDirectory, "/config.json"), JSON.stringify(configData, null, 4), { encoding: 'utf8' });
70
+
71
+ };
72
+
73
+ export const updateFile = async (
74
+ fileName,
75
+ oldComponentKeyPC,
76
+ newComponentKeyPC,
77
+ targetDirectory,
78
+ ) => {
79
+
80
+ let fileData = fs.readFileSync(join(targetDirectory, "/", fileName), { encoding: 'utf8' });
81
+
82
+ if (fileData.indexOf(oldComponentKeyPC) >= 0) {
83
+ fileData = fileData.replaceAll(oldComponentKeyPC, newComponentKeyPC);
84
+
85
+ fs.writeFileSync(join(targetDirectory, "/", fileName), fileData, { encoding: 'utf8' });
86
+ }
87
+
88
+ };
89
+
90
+
91
+ export const renameComponent = async (
92
+ {
93
+ library,
94
+ organization,
95
+ componentKey,
96
+ componentName,
97
+ componentLabel,
98
+ version,
99
+ description,
100
+ allowedApplications
101
+ },
102
+ options,
103
+ onlyCompanion = false
104
+ ) => {
105
+
106
+
107
+ let pegaConfig = await getPegaConfig();
108
+
109
+ const newComponentKey = `${organization}_${library}_${componentName}`;
110
+ const typeLC = componentKey.split("/")[0];
111
+ const oldComponentKey = componentKey.split("/")[1];
112
+ const newComponentKeyPC = convertIntoPascalCase(newComponentKey);
113
+ const oldComponentKeyPC = convertIntoPascalCase(oldComponentKey);
114
+
115
+ const currentDirectory = await getComponentDirectoryPath(componentKey);
116
+ const currentDirectoryConstellation = await getComponentDirectoryPath(componentKey, CATEGORY_CONSTELLATION);
117
+
118
+ const targetDirectory = await getComponentDirectoryPath(join(typeLC, "/",newComponentKey));
119
+ const targetDirectoryConstellation = await getComponentDirectoryPath(join(typeLC, "/",newComponentKey), CATEGORY_CONSTELLATION);
120
+
121
+
122
+
123
+ // custom component
124
+ try {
125
+ fs.renameSync(currentDirectory, targetDirectory);
126
+ } catch(err) {
127
+ console.log(err)
128
+ }
129
+
130
+ const targetFileList = await getDirectoryFiles(targetDirectory);
131
+
132
+ for (var fileIndex in targetFileList) {
133
+ const fileName = targetFileList[fileIndex];
134
+
135
+ if (fileName === "config.json") {
136
+ await updateConfig(
137
+ {
138
+ oldComponentKey,
139
+ newComponentKey,
140
+ componentName,
141
+ componentLabel,
142
+ library,
143
+ version,
144
+ description,
145
+ allowedApplications,
146
+ organization,
147
+ targetDirectory,
148
+ },
149
+ options
150
+ );
151
+ }
152
+ else {
153
+ await updateFile(
154
+ fileName,
155
+ oldComponentKeyPC,
156
+ newComponentKeyPC,
157
+ targetDirectory );
158
+
159
+ }
160
+
161
+ } // for
162
+
163
+ // associated component
164
+ try {
165
+ fs.renameSync(currentDirectoryConstellation, targetDirectoryConstellation);
166
+ } catch(err) {
167
+ console.log(err)
168
+ }
169
+
170
+ const targetConstellationFileList = await getDirectoryFiles(targetDirectoryConstellation);
171
+
172
+ for (var fileIndex in targetConstellationFileList) {
173
+ const fileName = targetConstellationFileList[fileIndex];
174
+
175
+ await updateFile(
176
+ fileName,
177
+ oldComponentKeyPC,
178
+ newComponentKeyPC,
179
+ targetDirectoryConstellation
180
+ );
181
+
182
+ } // for
183
+
184
+ // update map
185
+ renameComponentInMap(oldComponentKey, newComponentKey);
186
+
187
+ console.log(chalk.green(`Component ${oldComponentKey} renamed to ${newComponentKey}`));
188
+
189
+ };
190
+
191
+
192
+
193
+
194
+
195
+ export default async options => {
196
+ showVersion();
197
+
198
+ await checkPathAccess(pegaConfigJsonPath);
199
+
200
+ let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
201
+ data = data && JSON.parse(data);
202
+
203
+ if (!data[DXCB_CONFIG] || !data[DXCB_CONFIG][DXCB_COMPONENT_DEFAULTS]) {
204
+ console.error(
205
+ `${chalk.red.bold('ERROR')} Could not able find component defaults in config.json`
206
+ );
207
+ process.exit(1);
208
+ }
209
+
210
+ const componentData = data[DXCB_CONFIG][DXCB_COMPONENT_DEFAULTS];
211
+
212
+ const { organization, library} = componentData;
213
+
214
+ let componentDefaults = await getComponentDefaults();
215
+ componentDefaults.library = library;
216
+
217
+ const localComponents = await getComponentsObj(true, CATEGORY_CUSTOM);
218
+
219
+
220
+ const questions = [
221
+ {
222
+ name: 'componentKey',
223
+ type: 'rawlist',
224
+ pageSize: 15,
225
+ message: 'Select component to rename',
226
+ choices: localComponents
227
+ },
228
+ {
229
+ name: 'componentName',
230
+ message: 'Enter new component name (required, no spaces)',
231
+ validate: value => {
232
+ /* value should not be empty
233
+ It should not have spaces
234
+ It should not start with a number
235
+ Only case-insensitive alphanumeric values are allowed
236
+ */
237
+ if (value && !/^\d/.test(value) && value === sanitize(value)) {
238
+ return true;
239
+ }
240
+ return 'Only alphanumeric values are allowed, starting with alphabets';
241
+ }
242
+ },
243
+ {
244
+ name: 'componentLabel',
245
+ message: 'Enter new component label for display (required)',
246
+ validate: value => {
247
+ if (value) {
248
+ return true;
249
+ }
250
+ return 'Please provide value for label';
251
+ }
252
+ },
253
+ {
254
+ name: 'organization',
255
+ message: 'Enter new component organization',
256
+ default: componentDefaults.organization,
257
+ validate: value => {
258
+ if (value) {
259
+ return true;
260
+ }
261
+ return 'Please provide value for organization';
262
+ }
263
+ },
264
+ {
265
+ name: 'version',
266
+ message: 'Enter new component version',
267
+ default: componentDefaults.version,
268
+ validate: value => {
269
+ if (validateSemver(value)) {
270
+ return true;
271
+ }
272
+ return 'Please provide semver compatible version e.g 0.0.1';
273
+ }
274
+ },
275
+ {
276
+ name: 'library',
277
+ message: 'Enter new library name (required)',
278
+ default: componentDefaults.library,
279
+ validate: value => {
280
+ /* value should not be empty
281
+ It should not have spaces
282
+ It should not start with a number
283
+ Only case-insensitive alphanumeric values are allowed
284
+ */
285
+ if (value && !/^\d/.test(value) && value === sanitize(value)) {
286
+ return true;
287
+ }
288
+ return 'Only alphanumeric values are allowed, starting with alphabets';
289
+ }
290
+ },
291
+ {
292
+ name: 'allowedApplications',
293
+ message: 'Please enter the application names to be supported (comma-separated). ',
294
+ suffix: 'Keep empty for all applications'
295
+ },
296
+ {
297
+ name: 'description',
298
+ message: 'Enter new description for the component (defaults to new label)',
299
+ default: componentDefaults.description,
300
+ /* if left blank and no defaults, mustache will use componentLabel, because description is used in app studio and
301
+ shouldn't be blank */
302
+ }
303
+ ];
304
+
305
+ await inquirer.prompt(questions).then(async answers => {
306
+ const {
307
+ componentKey,
308
+ componentName,
309
+ componentLabel,
310
+ organization,
311
+ library,
312
+ version,
313
+ description,
314
+ allowedApplications
315
+ } = answers;
316
+
317
+ await renameComponent(
318
+ {
319
+ componentKey,
320
+ componentName,
321
+ componentLabel,
322
+ library,
323
+ version,
324
+ description,
325
+ allowedApplications,
326
+ organization
327
+ },
328
+ options
329
+ );
330
+
331
+ });
332
+
333
+ };