@pega/custom-dx-components 2.0.24 → 8.4.2

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.
Files changed (44) hide show
  1. package/package.json +1 -1
  2. package/src/auth.js +5 -5
  3. package/src/cli.js +18 -0
  4. package/src/constants.js +35 -1
  5. package/src/tasks/authenticate/index.js +72 -31
  6. package/src/tasks/build/helper.js +3 -3
  7. package/src/tasks/build-all/helper.js +69 -0
  8. package/src/tasks/build-all/index.js +79 -0
  9. package/src/tasks/create/templates/Constellation/Field/Boolean/styles.js.mustache +1 -1
  10. package/src/tasks/create/templates/Constellation/Field/Date/styles.js.mustache +1 -1
  11. package/src/tasks/create/templates/Constellation/Field/DateTime/styles.js.mustache +1 -1
  12. package/src/tasks/create/templates/Constellation/Field/Decimal/styles.js.mustache +1 -1
  13. package/src/tasks/create/templates/Constellation/Field/Decimal-Currency/styles.js.mustache +1 -1
  14. package/src/tasks/create/templates/Constellation/Field/Decimal-Percentage/styles.js.mustache +1 -1
  15. package/src/tasks/create/templates/Constellation/Field/Integer/styles.js.mustache +1 -1
  16. package/src/tasks/create/templates/Constellation/Field/Picklist/styles.js.mustache +1 -1
  17. package/src/tasks/create/templates/Constellation/Field/Text/config.json.mustache +14 -0
  18. package/src/tasks/create/templates/Constellation/Field/Text/styles.js.mustache +1 -1
  19. package/src/tasks/create/templates/Constellation/Field/Text-Email/styles.js.mustache +1 -1
  20. package/src/tasks/create/templates/Constellation/Field/Text-Input/styles.js.mustache +1 -1
  21. package/src/tasks/create/templates/Constellation/Field/Text-Paragraph/styles.js.mustache +1 -1
  22. package/src/tasks/create/templates/Constellation/Field/Text-Phone/styles.js.mustache +1 -1
  23. package/src/tasks/create/templates/Constellation/Field/Text-URL/styles.js.mustache +1 -1
  24. package/src/tasks/create/templates/Constellation/Field/TimeofDay/styles.js.mustache +1 -1
  25. package/src/tasks/create/templates/Constellation/Template/DETAILS/styles.js.mustache +1 -1
  26. package/src/tasks/create/templates/Constellation/Template/DETAILS-region/styles.js.mustache +1 -1
  27. package/src/tasks/create/templates/Constellation/Template/FORM/styles.js.mustache +1 -1
  28. package/src/tasks/create/templates/Constellation/Template/FORM-region/index.jsx.mustache +4 -1
  29. package/src/tasks/create/templates/Constellation/Template/FORM-region/styles.js.mustache +1 -1
  30. package/src/tasks/create/templates/Constellation/Template/PAGE/styles.js.mustache +1 -1
  31. package/src/tasks/create-all/index.js +400 -0
  32. package/src/tasks/index.js +3 -0
  33. package/src/tasks/init/template/package.json.mustache +5 -2
  34. package/src/tasks/list/helper.js +19 -6
  35. package/src/tasks/publish/helper.js +3 -3
  36. package/src/tasks/publish-all/helper.js +20 -6
  37. package/src/tasks/publish-all/index.js +29 -18
  38. package/src/tasks/rename/index.js +315 -0
  39. package/src/tasks/validator/index.js +182 -7
  40. package/src/util.js +66 -3
  41. package/src/tasks/create/template/config.json.mustache +0 -62
  42. package/src/tasks/create/template/demo.stories.jsx.mustache +0 -44
  43. package/src/tasks/create/template/index.jsx.mustache +0 -55
  44. package/src/tasks/create/template/styles.js.mustache +0 -7
@@ -8,28 +8,17 @@ import bundleComponent from '../bundle/index.js';
8
8
  import { lintComponent } from '../linter/index.js';
9
9
 
10
10
 
11
- import { getPublishComponentQuestions, publishComponentToServer, zipComponent } from './helper.js';
11
+ import { getPublishComponentQuestions, publishComponentToServer, zipComponent, cleanUp } from './helper.js';
12
12
  import {
13
13
  getComponents,
14
14
  getComponentDirectoryPath,
15
15
  showVersion
16
16
  } from '../../util.js';
17
17
 
18
- export default async options => {
19
- showVersion();
20
-
21
- const components = await getComponents();
22
- const questions = await getPublishComponentQuestions();
23
- const answers = await inquirer.prompt(questions);
24
- const {sourceMap, devBuild } = answers;
25
-
26
- let content = {
27
- ...answers
28
- };
29
18
 
30
- var componentKey;
31
19
 
32
- const tasks = new Listr(
20
+ export function getCustomTasks(componentKey, sourceMap, devBuild, content, options) {
21
+ const customTasks = new Listr(
33
22
  [
34
23
  {
35
24
  title: 'Validate config schema',
@@ -69,16 +58,38 @@ export default async options => {
69
58
  }
70
59
  );
71
60
 
61
+ return customTasks;
62
+ }
63
+
64
+ export default async options => {
65
+ showVersion();
66
+
67
+ const components = await getComponents();
68
+ const questions = await getPublishComponentQuestions();
69
+ const answers = await inquirer.prompt(questions);
70
+ const {sourceMap, devBuild } = answers;
71
+
72
+ let content = {
73
+ ...answers
74
+ };
75
+
76
+ var componentKey;
77
+
78
+
72
79
  for (var index in components) {
73
80
  componentKey = components[index];
74
81
  console.log(chalk.bold.green("Publishing: " + componentKey));
75
- await tasks.run().catch(err => {
82
+
83
+ let myCustomTasks = getCustomTasks(componentKey, sourceMap, devBuild, content, options);
84
+
85
+ await myCustomTasks.run().catch(err => {
76
86
  console.log(chalk.bold.red(err.toString()));
77
87
  });
78
88
  }
79
89
 
80
- // await tasks.run().catch(err => {
81
- // console.log(chalk.bold.red(err.toString()));
82
- // });
90
+ // once done, remove leftover directories
91
+ cleanUp();
92
+
93
+
83
94
  return true;
84
95
  };
@@ -0,0 +1,315 @@
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 { TASKS_CONFIG_JSON_FILENAME, COMPONENTS_DIRECTORY_PATH, COMPONENTS_PATH } from '../../constants.js';
13
+
14
+
15
+
16
+ export const DXCB_CONFIG_INTERNAL_JSON_FILENAME = 'src/dxcb.config.json';
17
+ const currentDirectory = process.cwd();
18
+ const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
19
+
20
+
21
+ import {
22
+ convertIntoPascalCase,
23
+ getComponentDirectoryPath,
24
+ getPegaConfig,
25
+ getComponentDefaults,
26
+ sanitize,
27
+ validateSemver
28
+ } from '../../util.js';
29
+ import { COMPONENT_SCHEMA } from '../../constants.js';
30
+
31
+ const copy = promisify(ncp);
32
+
33
+
34
+ export const updateConfig = async (
35
+ {
36
+ oldComponentKey,
37
+ newComponentKey,
38
+ library,
39
+ organization,
40
+ componentName,
41
+ componentLabel,
42
+ version,
43
+ description,
44
+ allowedApplications,
45
+ targetDirectory,
46
+ },
47
+ options,
48
+ onlyCompanion = false
49
+ ) => {
50
+
51
+ let configData = fs.readFileSync(join(targetDirectory, "/config.json"), { encoding: 'utf8' });
52
+ configData = configData && JSON.parse(configData);
53
+
54
+ configData.name = newComponentKey;
55
+ configData.label = componentLabel;
56
+ configData.organization = organization;
57
+ if (configData.componentKey) configData.componentKey = newComponentKey;
58
+ configData.library = library;
59
+ configData.version = version;
60
+ configData.description = (description != '') ? description : componentLabel;
61
+
62
+ if (allowedApplications.trim() === '') {
63
+ allowedApplications = [];
64
+ } else {
65
+ if (allowedApplications.indexOf(',') !== -1) {
66
+ allowedApplications = allowedApplications.split(',');
67
+ }
68
+ allowedApplications = [].concat(allowedApplications);
69
+ }
70
+
71
+ allowedApplications = allowedApplications.filter(el => !!el.trim()).map(el => el.trim());
72
+
73
+ configData.allowedApplications = allowedApplications;
74
+
75
+ // stringify "4", makes the json string look like JSON in the file, formated instead of a single line
76
+ fs.writeFileSync(join(targetDirectory, "/config.json"), JSON.stringify(configData, null, 4), { encoding: 'utf8' });
77
+
78
+ };
79
+
80
+ export const updateFile = async (
81
+ fileName,
82
+ oldComponentKeyPC,
83
+ newComponentKeyPC,
84
+ targetDirectory,
85
+ ) => {
86
+
87
+ let fileData = fs.readFileSync(join(targetDirectory, "/", fileName), { encoding: 'utf8' });
88
+
89
+ if (fileData.indexOf(oldComponentKeyPC) >= 0) {
90
+ fileData = fileData.replaceAll(oldComponentKeyPC, newComponentKeyPC);
91
+
92
+ fs.writeFileSync(join(targetDirectory, "/", fileName), fileData, { encoding: 'utf8' });
93
+ }
94
+
95
+ };
96
+
97
+
98
+ export const renameComponent = async (
99
+ {
100
+ library,
101
+ organization,
102
+ componentKey,
103
+ componentName,
104
+ componentLabel,
105
+ version,
106
+ description,
107
+ allowedApplications
108
+ },
109
+ options,
110
+ onlyCompanion = false
111
+ ) => {
112
+
113
+
114
+ let pegaConfig = await getPegaConfig();
115
+
116
+ const newComponentKey = `${organization}_${library}_${componentName}`;
117
+
118
+ const oldComponentKey = componentKey;
119
+ const newComponentKeyPC = convertIntoPascalCase(newComponentKey);
120
+ const oldComponentKeyPC = convertIntoPascalCase(oldComponentKey);
121
+
122
+ const currentDirectory = await getComponentDirectoryPath(componentKey);
123
+ const targetDirectory = await getComponentDirectoryPath(newComponentKey);
124
+
125
+
126
+
127
+
128
+ // custom component
129
+ try {
130
+ fs.renameSync(currentDirectory, targetDirectory);
131
+ } catch(err) {
132
+ console.log(err)
133
+ }
134
+
135
+ const targetFileList = await getDirectoryFiles(targetDirectory);
136
+
137
+ for (var fileIndex in targetFileList) {
138
+ const fileName = targetFileList[fileIndex];
139
+
140
+ if (fileName === "config.json") {
141
+ await updateConfig(
142
+ {
143
+ oldComponentKey,
144
+ newComponentKey,
145
+ componentName,
146
+ componentLabel,
147
+ library,
148
+ version,
149
+ description,
150
+ allowedApplications,
151
+ organization,
152
+ targetDirectory,
153
+ },
154
+ options
155
+ );
156
+ }
157
+ else {
158
+ await updateFile(
159
+ fileName,
160
+ oldComponentKeyPC,
161
+ newComponentKeyPC,
162
+ targetDirectory );
163
+
164
+ }
165
+
166
+ } // for
167
+
168
+
169
+ console.log(chalk.green(`Component ${oldComponentKey} renamed to ${newComponentKey}`));
170
+
171
+ };
172
+
173
+
174
+
175
+
176
+
177
+ export default async options => {
178
+ showVersion();
179
+
180
+ await checkPathAccess(pegaConfigJsonPath);
181
+
182
+ let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
183
+ data = data && JSON.parse(data);
184
+
185
+ if (!data[COMPONENTS_DIRECTORY_PATH]) {
186
+ console.error(
187
+ `${chalk.red.bold('ERROR')} Could not able find components directory path in config.json`
188
+ );
189
+ process.exit(1);
190
+ }
191
+
192
+ const componentData = data[COMPONENTS_PATH];
193
+
194
+ const { library } = componentData;
195
+ const { organization } = JSON.parse(fs.readFileSync(path.resolve('package.json'), 'utf8'));
196
+
197
+ let componentDefaults = await getComponentDefaults();
198
+ componentDefaults.library = library;
199
+
200
+ const localComponents = await getComponentsObj();
201
+
202
+ const questions = [
203
+ {
204
+ name: 'componentKey',
205
+ type: 'rawlist',
206
+ pageSize: 15,
207
+ message: 'Select component to rename',
208
+ choices: localComponents
209
+ },
210
+ {
211
+ name: 'componentName',
212
+ message: 'Enter new component name (required, no spaces)',
213
+ validate: value => {
214
+ /* value should not be empty
215
+ It should not have spaces
216
+ It should not start with a number
217
+ Only case-insensitive alphanumeric values are allowed
218
+ */
219
+ if (value && !/^\d/.test(value) && value === sanitize(value)) {
220
+ return true;
221
+ }
222
+ return 'Only alphanumeric values are allowed, starting with alphabets';
223
+ }
224
+ },
225
+ {
226
+ name: 'componentLabel',
227
+ message: 'Enter new component label for display (required)',
228
+ validate: value => {
229
+ if (value) {
230
+ return true;
231
+ }
232
+ return 'Please provide value for label';
233
+ }
234
+ },
235
+ {
236
+ name: 'organization',
237
+ message: 'Enter new component organization',
238
+ default: organization,
239
+ validate: value => {
240
+ if (value) {
241
+ return true;
242
+ }
243
+ return 'Please provide value for organization';
244
+ }
245
+ },
246
+ {
247
+ name: 'version',
248
+ message: 'Enter new component version',
249
+ default: componentDefaults.version,
250
+ validate: value => {
251
+ if (validateSemver(value)) {
252
+ return true;
253
+ }
254
+ return 'Please provide semver compatible version e.g 0.0.1';
255
+ }
256
+ },
257
+ {
258
+ name: 'library',
259
+ message: 'Enter new library name (required)',
260
+ default: componentDefaults.library,
261
+ validate: value => {
262
+ /* value should not be empty
263
+ It should not have spaces
264
+ It should not start with a number
265
+ Only case-insensitive alphanumeric values are allowed
266
+ */
267
+ if (value && !/^\d/.test(value) && value === sanitize(value)) {
268
+ return true;
269
+ }
270
+ return 'Only alphanumeric values are allowed, starting with alphabets';
271
+ }
272
+ },
273
+ {
274
+ name: 'allowedApplications',
275
+ message: 'Please enter the application names to be supported (comma-separated). ',
276
+ suffix: 'Keep empty for all applications'
277
+ },
278
+ {
279
+ name: 'description',
280
+ message: 'Enter new description for the component (defaults to new label)',
281
+ default: componentDefaults.description,
282
+ /* if left blank and no defaults, mustache will use componentLabel, because description is used in app studio and
283
+ shouldn't be blank */
284
+ }
285
+ ];
286
+
287
+ await inquirer.prompt(questions).then(async answers => {
288
+ const {
289
+ componentKey,
290
+ componentName,
291
+ componentLabel,
292
+ organization,
293
+ library,
294
+ version,
295
+ description,
296
+ allowedApplications
297
+ } = answers;
298
+
299
+ await renameComponent(
300
+ {
301
+ componentKey,
302
+ componentName,
303
+ componentLabel,
304
+ library,
305
+ version,
306
+ description,
307
+ allowedApplications,
308
+ organization
309
+ },
310
+ options
311
+ );
312
+
313
+ });
314
+
315
+ };
@@ -5,8 +5,13 @@ import chalk from 'chalk';
5
5
  import inquirer from 'inquirer';
6
6
  import Ajv from 'ajv';
7
7
 
8
- import { COMPONENT_SCHEMA } from '../../constants.js';
9
- import { getComponentDirectoryPath, getComponents, getOOTBComponents } from '../../util.js';
8
+ import {
9
+ COMPONENT_SCHEMA } from '../../constants.js';
10
+
11
+ import {
12
+ getComponentDirectoryPath,
13
+ getComponents,
14
+ getOOTBComponents } from '../../util.js';
10
15
 
11
16
  const ajv = new Ajv({ allErrors: true });
12
17
 
@@ -15,11 +20,20 @@ const combinationTypes = ['PAGE', 'CASE'];
15
20
  const allowedSubtypes = [
16
21
  ...new Set([
17
22
  ...COMPONENT_SCHEMA.subtype.field.map(({ value }) => value),
18
- ...COMPONENT_SCHEMA.subtype.template,
23
+ ...COMPONENT_SCHEMA.subtype.template.map(({ value }) => value),
19
24
  ...COMPONENT_SCHEMA.subtype.widget.map(({ value }) => value)
20
25
  ])
21
26
  ];
22
27
 
28
+ // additional subtypes are manually added below
29
+ const allowedOverrideSubtypes = [
30
+ ...new Set([
31
+ ...COMPONENT_SCHEMA.subtype.field.map(({ value }) => value),
32
+ ...COMPONENT_SCHEMA.subtype.template.map(({ value }) => value),
33
+ ...COMPONENT_SCHEMA.subtype.widget.map(({ value }) => value)
34
+ ]), "ACTION", "DATA_CAPTURE", "SUMMARY", "CASEVIEW", "DATAVIEW", "LIST"
35
+ ];
36
+
23
37
  const schema = {
24
38
  type: 'object',
25
39
  properties: {
@@ -157,9 +171,149 @@ const schema = {
157
171
  additionalProperties: true
158
172
  };
159
173
 
174
+ const overrideSchema = {
175
+ type: 'object',
176
+ properties: {
177
+ baseComponentName: { type: 'string' },
178
+ componentKey: { type: 'string', pattern: '^[A-Za-z0-9]+$' },
179
+ name: { type: 'string', pattern: '^[A-Za-z0-9]+$' },
180
+ label: { type: 'string' },
181
+ description: { type: 'string' },
182
+ organization: { type: 'string' },
183
+ version: { type: 'string' },
184
+ library: { type: 'string' },
185
+ allowedApplications: { type: 'array' },
186
+ type: { type: 'string', enum: COMPONENT_SCHEMA.type.map(({ value }) => value) },
187
+ subtype: {
188
+ anyOf: [{ type: 'string' }, { type: 'array' }],
189
+
190
+ enum: allowedOverrideSubtypes
191
+ },
192
+ icon: { type: 'string' },
193
+ properties: {
194
+ type: 'array',
195
+ uniqueItems: true,
196
+ items: {
197
+ anyOf: [
198
+ {
199
+ type: 'object',
200
+ properties: {
201
+ name: { type: 'string' },
202
+ label: { type: 'string' },
203
+ format: { type: 'string' }
204
+ },
205
+ required: ['name', 'label', 'format']
206
+ },
207
+ {
208
+ type: 'object',
209
+ properties: {
210
+ format: { type: 'string' },
211
+ source: {
212
+ type: 'object',
213
+ properties: {
214
+ name: { type: 'string' },
215
+ label: { type: 'string' },
216
+ format: { type: 'string' }
217
+ },
218
+ required: ['name', 'label', 'format']
219
+ },
220
+ cascadeElements: {
221
+ type: 'array',
222
+ uniqueItems: true,
223
+ items: {
224
+ anyOf: [
225
+ {
226
+ type: 'object',
227
+ properties: {
228
+ key: { type: 'string'},
229
+ name: { type: 'string' },
230
+ label: { type: 'string' },
231
+ format: { type: 'string' }
232
+ },
233
+ required: ['key','name', 'label', 'format']
234
+ }
235
+ ]
236
+ }
237
+ },
238
+ },
239
+ required: ['format']
240
+ },
241
+ {
242
+ type: 'object',
243
+ properties: {
244
+ label: { type: 'string' },
245
+ format: { type: 'string' },
246
+ properties: {
247
+ type: 'array',
248
+ uniqueItems: true,
249
+ items: {
250
+ anyOf: [
251
+ {
252
+ type: 'object',
253
+ properties: {
254
+ name: { type: 'string' },
255
+ label: { type: 'string' },
256
+ format: { type: 'string' }
257
+ },
258
+ required: ['name', 'label', 'format']
259
+ },
260
+ {
261
+ type: 'object',
262
+ properties: {
263
+ variant: { type: 'string' },
264
+ label: { type: 'string' },
265
+ format: { type: 'string' }
266
+ },
267
+ required: ['variant', 'label', 'format']
268
+ },
269
+ {
270
+ type: 'object',
271
+ properties: {
272
+ format: { type: 'string' },
273
+ elements: {
274
+ type: 'array',
275
+ uniqueItems: true,
276
+ items: {
277
+ anyOf: [
278
+ {
279
+ type: 'object',
280
+ properties: {
281
+ key: { type: 'string' },
282
+ name: { type: 'string' },
283
+ label: { type: 'string' },
284
+ format: { type: 'string' },
285
+ variant: { type: 'string' }
286
+ },
287
+ required: ['key', 'format', 'label']
288
+ }
289
+ ]
290
+ }
291
+ }
292
+ },
293
+ required: ['format', 'elements']
294
+ },
295
+ ]
296
+ }
297
+ }
298
+
299
+ },
300
+ required: ['label', 'format'],
301
+ }
302
+ ]
303
+ }
304
+ },
305
+ defaultConfig: { type: 'object' }
306
+ },
307
+ required: ['name', 'type', 'subtype', 'properties', 'componentKey'],
308
+ additionalProperties: true
309
+ };
310
+
160
311
  const validateSchema = ajv.compile(schema);
312
+ const validateOverideSchema = ajv.compile(overrideSchema);
313
+
161
314
 
162
- export default async option => {
315
+
316
+ export default async (option) => {
163
317
  let componentToValidate = null;
164
318
  if (option.params && option.params[3]) {
165
319
  componentToValidate = option.params[3];
@@ -173,26 +327,47 @@ export default async option => {
173
327
  });
174
328
 
175
329
  componentToValidate = answer.component;
330
+ } else if (option.name) {
331
+ componentToValidate = option.value;
176
332
  } else {
177
333
  componentToValidate = option;
178
334
  }
179
335
 
180
336
  const componentDirectory = await getComponentDirectoryPath(componentToValidate);
181
- const configFile = path.join(componentDirectory, 'config.json');
182
- const data = JSON.parse(fs.readFileSync(path.resolve(configFile), 'utf8'));
337
+ let configFileName = "config.json";
338
+
339
+ const configFile = path.join(componentDirectory, configFileName);
340
+ let configData;
341
+ try {
342
+ configData = fs.readFileSync(path.resolve(configFile), 'utf8');
343
+ }
344
+ catch (err) {
345
+
346
+ // for now, if now file just end
347
+ console.log(`${chalk.bold.yellow('Config file not availabe for: ' + componentToValidate)}`);
348
+ return;
349
+
350
+ }
351
+
352
+ //const data = JSON.parse(fs.readFileSync(path.resolve(configFile), 'utf8'));
353
+ const data = JSON.parse(configData);
354
+
183
355
  const valid = validateSchema(data);
184
356
 
185
357
  if (valid) {
358
+
186
359
  if (
187
360
  componentToValidate &&
188
361
  !/^[A-Za-z0-9]+_[A-Za-z0-9]+_[A-Za-z0-9]+$/.test(componentToValidate)
189
362
  ) {
190
363
  const ootbComponents = await getOOTBComponents();
191
364
  if (ootbComponents.includes(componentToValidate)) {
192
- throw new Error(`Invalid: Error occured in validating ${componentToValidate}`);
365
+ throw new Error(`Invalid: Error occurred in validating ${componentToValidate}`);
193
366
  }
194
367
  }
195
368
 
369
+
370
+
196
371
  console.log(`${chalk.bold.green(componentToValidate)} schema is valid`);
197
372
  } else {
198
373
  throw new Error(`Invalid: ${ajv.errorsText(validateSchema.errors)}`);