@pega/dx-component-builder-sdk 0.1.0 → 0.1.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.
@@ -6,13 +6,16 @@ import {
6
6
  deleteLocalComponents,
7
7
  SOURCE_OF_COMPONENT_TYPES,
8
8
  deleteServerComponents,
9
- getDeleteComponentsQuestions
9
+ getDeleteComponentsQuestions,
10
+ getOptionsCategory
10
11
  } from './helper.js';
11
12
 
13
+
14
+
12
15
  const deleteComponentsFn = async (sourceOfComponents, answers) => {
13
16
  switch (sourceOfComponents) {
14
17
  case SOURCE_OF_COMPONENT_TYPES.LOCAL: {
15
- await deleteLocalComponents(sourceOfComponents);
18
+ await deleteLocalComponents(sourceOfComponents, answers.category);
16
19
  break;
17
20
  }
18
21
  case SOURCE_OF_COMPONENT_TYPES.SERVER: {
@@ -28,18 +31,25 @@ const deleteComponentsFn = async (sourceOfComponents, answers) => {
28
31
 
29
32
  export default async options => {
30
33
  let sourceOfComponentsOption = SOURCE_OF_COMPONENT_TYPES.LOCAL;
31
- if (options.params[3] === SOURCE_OF_COMPONENT_TYPES.LOCAL) {
34
+ if (options.params[4] === SOURCE_OF_COMPONENT_TYPES.LOCAL) {
32
35
  sourceOfComponentsOption = options.params[3];
33
36
  await deleteComponentsFn(sourceOfComponentsOption);
34
- } else if (options.params[3] === SOURCE_OF_COMPONENT_TYPES.SERVER) {
37
+ } else if (options.params[4] === SOURCE_OF_COMPONENT_TYPES.SERVER) {
35
38
  sourceOfComponentsOption = options.params[3];
36
39
  const questions = await getDeleteComponentsQuestions(options, sourceOfComponentsOption);
37
40
  const answers = await inquirer.prompt(questions);
38
41
  await deleteComponentsFn(sourceOfComponentsOption, answers);
39
42
  } else {
40
43
  const questions = await getDeleteComponentsQuestions(options);
41
- const answers = await inquirer.prompt(questions);
42
- const { sourceOfComponents } = answers;
44
+ let answers = await inquirer.prompt(questions);
45
+ const categoryType = getOptionsCategory(options);
46
+ let { sourceOfComponents, category } = answers;
47
+ if (!sourceOfComponents) {
48
+ sourceOfComponents = SOURCE_OF_COMPONENT_TYPES.LOCAL
49
+ }
50
+ if (categoryType != null) {
51
+ answers.category = categoryType;
52
+ }
43
53
  await deleteComponentsFn(sourceOfComponents, answers);
44
54
  }
45
55
  };
@@ -2,7 +2,7 @@ import chalk from 'chalk';
2
2
  import inquirer from 'inquirer';
3
3
  import ora from 'ora';
4
4
 
5
- import { LIST_COMPONENT_SERVICE_REST_ENDPOINT } from '../..//constants.js';
5
+ import { LIST_COMPONENT_SERVICE_REST_ENDPOINT, COMPONENT_SCHEMA } from '../..//constants.js';
6
6
  import {
7
7
  constructCompleteUrl,
8
8
  deleteLocalComponent,
@@ -22,19 +22,48 @@ export const SOURCE_OF_COMPONENT_TYPES = {
22
22
  LOCAL: 'Local'
23
23
  };
24
24
 
25
+ export const getOptionsCategory = (options) => {
26
+ let categoryType = null;
27
+ if (options.params[3]) {
28
+ let catType = options.params[3];
29
+
30
+ switch (catType.toLowerCase()) {
31
+ case "override" :
32
+ case "o" :
33
+ categoryType = "override";
34
+ break;
35
+ case "custom" :
36
+ case "c" :
37
+ categoryType = "custom";
38
+ break;
39
+ }
40
+ }
41
+ return categoryType;
42
+ }
43
+
25
44
  export const getDeleteComponentsQuestions = async (options, sourceOfComponentsOption) => {
26
45
  const defaultPegaServerConfig = await getPegaServerConfig();
27
-
46
+ const categoryType = getOptionsCategory(options);
28
47
 
29
48
  return [
49
+ {
50
+ name: 'category',
51
+ type: 'rawlist',
52
+ message: 'Category of components ?',
53
+ choices: COMPONENT_SCHEMA.category,
54
+ when() {
55
+ return !options.params[4] && categoryType == null;
56
+ }
57
+ },
30
58
  {
31
59
  name: 'sourceOfComponents',
32
60
  type: 'rawlist',
33
61
  message: 'Delete components from Server or Local ?',
34
62
  choices: Object.values(SOURCE_OF_COMPONENT_TYPES),
35
63
  default: defaultPegaServerConfig.sourceOfComponents,
36
- when() {
37
- return !options.params[3];
64
+ when(answers) {
65
+ return !options.params[4] && answers.category != 'override' && categoryType != 'override';
66
+
38
67
  }
39
68
  }
40
69
  ];
@@ -42,8 +71,8 @@ export const getDeleteComponentsQuestions = async (options, sourceOfComponentsOp
42
71
 
43
72
 
44
73
 
45
- export const deleteLocalComponents = async sourceOfComponents => {
46
- const localComponents = await getComponentsObj(true);
74
+ export const deleteLocalComponents = async (sourceOfComponents, category = "custom") => {
75
+ const localComponents = await getComponentsObj(true, category);
47
76
 
48
77
  for (var index in localComponents) {
49
78
  if (localComponents[index].type != undefined && localComponents[index].type === "separator") {
@@ -69,7 +98,18 @@ export const deleteLocalComponents = async sourceOfComponents => {
69
98
  for (var index in localComponents) {
70
99
  if (localComponents[index].type == undefined) {
71
100
  var componentToDelete = localComponents[index].value;
72
- await deleteLocalComponent(componentToDelete);
101
+ await deleteLocalComponent(componentToDelete, category);
102
+
103
+ if (category === "override") {
104
+ // need to remove the map as well
105
+ if (componentToDelete != undefined) {
106
+ await deleteFromComponentMap(componentToDelete, category);
107
+ }
108
+ else {
109
+ console.log(chalk.bold.redBright(`No component in map: ` + componentToDelete));
110
+ }
111
+
112
+ }
73
113
  }
74
114
 
75
115
  }
@@ -6,13 +6,14 @@ import {
6
6
  deleteLocalComponents,
7
7
  SOURCE_OF_COMPONENT_TYPES,
8
8
  deleteServerComponents,
9
- getDeleteComponentsQuestions
9
+ getDeleteComponentsQuestions,
10
+ getOptionsCategory
10
11
  } from './helper.js';
11
12
 
12
13
  const deleteComponentsFn = async (sourceOfComponents, answers) => {
13
14
  switch (sourceOfComponents) {
14
15
  case SOURCE_OF_COMPONENT_TYPES.LOCAL: {
15
- await deleteLocalComponents(sourceOfComponents);
16
+ await deleteLocalComponents(sourceOfComponents, answers.category);
16
17
  break;
17
18
  }
18
19
  case SOURCE_OF_COMPONENT_TYPES.SERVER: {
@@ -38,8 +39,15 @@ export default async options => {
38
39
  await deleteComponentsFn(sourceOfComponentsOption, answers);
39
40
  } else {
40
41
  const questions = await getDeleteComponentsQuestions(options);
41
- const answers = await inquirer.prompt(questions);
42
- const { sourceOfComponents } = answers;
42
+ let answers = await inquirer.prompt(questions);
43
+ const categoryType = getOptionsCategory(options);
44
+ let { sourceOfComponents, category } = answers;
45
+ if (!sourceOfComponents) {
46
+ sourceOfComponents = SOURCE_OF_COMPONENT_TYPES.LOCAL
47
+ }
48
+ if (categoryType != null) {
49
+ answers.category = categoryType;
50
+ }
43
51
  await deleteComponentsFn(sourceOfComponents, answers);
44
52
  }
45
53
  };
@@ -1,4 +1,5 @@
1
1
  export { default as createComponent } from './create/index.js';
2
+ export { default as overrideComponent } from './override/index.js';
2
3
  export { default as deleteComponent } from './delete/index.js';
3
4
  export { default as deleteAllComponents } from './delete-all/index.js';
4
5
  export { default as publishComponent } from './publish/index.js';
@@ -4,33 +4,64 @@ import https from 'https';
4
4
  import chalk from 'chalk';
5
5
  import fetch from 'node-fetch';
6
6
 
7
- import { LIST_COMPONENT_SERVICE_REST_ENDPOINT, TOKEN_PATH } from '../../constants.js';
7
+ import { LIST_COMPONENT_SERVICE_REST_ENDPOINT, TOKEN_PATH, COMPONENT_SCHEMA } from '../../constants.js';
8
8
  import { constructCompleteUrl, getComponents, getPegaServerConfig } from '../../util.js';
9
9
 
10
+
10
11
  export const SOURCE_OF_COMPONENT_TYPES = {
11
12
  SERVER: 'Server',
12
13
  LOCAL: 'Local'
13
14
  };
14
15
 
16
+ export const getOptionsCategory = (options) => {
17
+ let categoryType = null;
18
+ if (options.params[3]) {
19
+ let catType = options.params[3];
20
+
21
+ switch (catType.toLowerCase()) {
22
+ case "override" :
23
+ case "o" :
24
+ categoryType = "override";
25
+ break;
26
+ case "custom" :
27
+ case "c" :
28
+ categoryType = "custom";
29
+ break;
30
+ }
31
+ }
32
+ return categoryType;
33
+ }
34
+
15
35
  export const getListComponentsQuestions = async (options, sourceOfComponentsOption) => {
16
36
  const defaultPegaServerConfig = await getPegaServerConfig();
17
37
 
38
+ const categoryType = getOptionsCategory(options);
39
+
18
40
  return [
41
+ {
42
+ name: 'category',
43
+ type: 'rawlist',
44
+ message: 'Category of components ?',
45
+ choices: COMPONENT_SCHEMA.category,
46
+ when() {
47
+ return !options.params[4] && categoryType == null;
48
+ }
49
+ },
19
50
  {
20
51
  name: 'sourceOfComponents',
21
52
  type: 'rawlist',
22
53
  message: 'List components from Server or Local ?',
23
54
  choices: Object.values(SOURCE_OF_COMPONENT_TYPES),
24
55
  default: defaultPegaServerConfig.sourceOfComponents,
25
- when() {
26
- return !options.params[3];
56
+ when(answers) {
57
+ return !options.params[4] && answers.category != 'override' && categoryType != 'override';
27
58
  }
28
59
  }
29
60
  ];
30
61
  };
31
62
 
32
- export const listLocalComponents = async sourceOfComponents => {
33
- let localComponents = await getComponents();
63
+ export const listLocalComponents = async (sourceOfComponents, category = "custom") => {
64
+ let localComponents = await getComponents(false, category);
34
65
  localComponents = localComponents.map(name => ({ 'Rule name': name }));
35
66
  if (localComponents.length > 0) {
36
67
  console.log(chalk.bold.blueBright(`List of custom components in ${sourceOfComponents}`));
@@ -7,13 +7,15 @@ import {
7
7
  SOURCE_OF_COMPONENT_TYPES,
8
8
  getComponentsFromServer,
9
9
  displayServerComponents,
10
- getListComponentsQuestions
10
+ getListComponentsQuestions,
11
+ getOptionsCategory
11
12
  } from './helper.js';
12
13
 
14
+
13
15
  const getList = async (sourceOfComponents, answers) => {
14
16
  switch (sourceOfComponents) {
15
17
  case SOURCE_OF_COMPONENT_TYPES.LOCAL: {
16
- await listLocalComponents(sourceOfComponents);
18
+ await listLocalComponents(sourceOfComponents, answers.category);
17
19
  break;
18
20
  }
19
21
  case SOURCE_OF_COMPONENT_TYPES.SERVER: {
@@ -32,20 +34,28 @@ const getList = async (sourceOfComponents, answers) => {
32
34
  };
33
35
 
34
36
  export default async options => {
37
+
35
38
  let sourceOfComponentsOption = SOURCE_OF_COMPONENT_TYPES.LOCAL;
36
39
 
37
- if (options.params[3] === SOURCE_OF_COMPONENT_TYPES.LOCAL) {
40
+ if (options.params[4] === SOURCE_OF_COMPONENT_TYPES.LOCAL) {
38
41
  sourceOfComponentsOption = options.params[3];
39
42
  await getList(sourceOfComponentsOption);
40
- } else if (options.params[3] === SOURCE_OF_COMPONENT_TYPES.SERVER) {
43
+ } else if (options.params[4] === SOURCE_OF_COMPONENT_TYPES.SERVER) {
41
44
  sourceOfComponentsOption = options.params[3];
42
45
  const questions = await getListComponentsQuestions(options, sourceOfComponentsOption);
43
46
  const answers = await inquirer.prompt(questions);
44
47
  await getList(sourceOfComponentsOption, answers);
45
48
  } else {
46
49
  const questions = await getListComponentsQuestions(options);
47
- const answers = await inquirer.prompt(questions);
48
- const { sourceOfComponents } = answers;
50
+ let answers = await inquirer.prompt(questions);
51
+ const categoryType = getOptionsCategory(options);
52
+ let { sourceOfComponents, category } = answers;
53
+ if (!sourceOfComponents) {
54
+ sourceOfComponents = SOURCE_OF_COMPONENT_TYPES.LOCAL
55
+ }
56
+ if (categoryType != null) {
57
+ answers.category = categoryType;
58
+ }
49
59
  await getList(sourceOfComponents, answers);
50
60
  }
51
61
  };
@@ -80,6 +80,7 @@ export const updateComponentMap = async (componentKey, category = "custom") => {
80
80
  export const deleteFromComponentMap = async (componentKey, category = "custom") => {
81
81
  const pegaLocalComponentMapPath = path.join(path.resolve(), SDK_LOCAL_COMPONENT_MAP_FILENAME);
82
82
  const categoryDirectory = join("/", category.toLowerCase());
83
+ const pegaConfigJsonPath = path.join(path.resolve(), DXCB_CONFIG_JSON_FILENAME);
83
84
 
84
85
  const componentNameNoPrefix = removeComponentPrefix(componentKey);
85
86
  const componentName = convertIntoPascalCase(componentNameNoPrefix);
@@ -96,7 +97,8 @@ export const deleteFromComponentMap = async (componentKey, category = "custom")
96
97
  process.exit(1);
97
98
  }
98
99
 
99
- let importComponent = join("./", data[COMPONENTS_DIRECTORY_PATH], categoryDirectory, componentKey);
100
+ let importComponent = join(data[COMPONENTS_DIRECTORY_PATH], categoryDirectory, componentKey);
101
+ importComponent = "./".concat(importComponent);
100
102
 
101
103
  let importFull = "import ".concat(componentName).concat(" from '").concat(importComponent).concat("/';");
102
104
  let mapFull = "\"".concat(componentNameNoPrefix).concat("\" : " ).concat(componentName).concat(",");
@@ -0,0 +1,212 @@
1
+ import path from 'path';
2
+ import { URL, fileURLToPath } from 'url';
3
+ import fs from 'fs';
4
+ import { promisify } from 'util';
5
+ import { createRequire } from "module";
6
+ import { join } from 'path';
7
+
8
+ import inquirer from 'inquirer';
9
+ import ncp from 'ncp';
10
+ import chalk from 'chalk';
11
+ import { updateComponentMap } from '../map/map.js';
12
+
13
+ import { checkPathAccess, getTokenUrl } from '../../util.js';
14
+
15
+
16
+ export const DXCB_CONFIG_JSON_FILENAME = 'dxcb.config.json';
17
+ export const DXCB_CONFIG_INTERNAL_JSON_FILENAME = 'src/dxcb.config.json';
18
+
19
+ const pegaConfigJsonPath = path.join(path.resolve(), DXCB_CONFIG_JSON_FILENAME);
20
+ const pegaConfigInternalJsonPath = path.join(path.resolve(), DXCB_CONFIG_INTERNAL_JSON_FILENAME);
21
+
22
+ import {
23
+ convertIntoPascalCase,
24
+ compileMustacheTemplate,
25
+ getComponentDirectoryPath,
26
+ getComponents,
27
+ getComponentDefaults,
28
+ sanitize,
29
+ validateSemver
30
+ } from '@pega/dx-component-builder-sdk/src/util.js';
31
+ import { COMPONENT_SCHEMA } from '../../constants.js';
32
+
33
+ const copy = promisify(ncp);
34
+
35
+ const copyComponentTemplate = async options => {
36
+ return copy(options.overrideDirectory, options.targetDirectory, {
37
+ clobber: false
38
+ });
39
+ };
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+ const validateCompile = async (
48
+ {
49
+ componentName,
50
+ type
51
+ },
52
+ options
53
+ ) => {
54
+
55
+ // componentName has sub directory if components are in a sub directory of main "type"
56
+ const overrideDirectory = `node_modules/@pega/react-sdk-overrides/lib/${type}/${componentName}`;
57
+
58
+ await checkPathAccess(overrideDirectory);
59
+
60
+ let componentKey = componentName;
61
+ if (componentKey.indexOf("/") >= 0) {
62
+ componentKey = componentKey.split("/")[1];
63
+ }
64
+ const typeLC = type.toLowerCase();
65
+ const targetDirectory = await getComponentDirectoryPath(join(typeLC, "/",componentKey), "override");
66
+
67
+ const components = await getComponents(false, "override");
68
+ if (components.includes(componentKey)) {
69
+ console.log(chalk.red(`${componentKey} component already exists in ${targetDirectory}`));
70
+ return;
71
+ }
72
+
73
+ await copyComponentTemplate({
74
+ ...options,
75
+ targetDirectory,
76
+ overrideDirectory
77
+ });
78
+
79
+
80
+ console.log(chalk.green(`> Created ${componentKey} component in ${targetDirectory}`));
81
+
82
+ const componentKeyWithType = join(type, componentKey);
83
+ await updateComponentMap(componentKeyWithType, "override");
84
+
85
+ console.log(chalk.green(`> Added ${componentKeyWithType} to map`));
86
+
87
+ };
88
+
89
+ export default async options => {
90
+
91
+ let promptType = null;
92
+ if (options.params[3]) {
93
+ let inputType = options.params[3];
94
+
95
+ switch (inputType.toLowerCase()) {
96
+ case "forms" :
97
+ case "f" :
98
+ promptType = "forms";
99
+ break;
100
+ case "templates" :
101
+ case "t" :
102
+ promptType = "templates";
103
+ break;
104
+ case "widgets" :
105
+ case "w" :
106
+ promptType = "widgets";
107
+ break;
108
+ case "designsystemextensions" :
109
+ case "des" :
110
+ case "d" :
111
+ promptType = "designSystemExtensions";
112
+ break;
113
+ case "infra" :
114
+ case "i" :
115
+ promptType = "infra";
116
+ break;
117
+ }
118
+ }
119
+
120
+ await checkPathAccess(pegaConfigJsonPath);
121
+
122
+ let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
123
+ data = data && JSON.parse(data);
124
+
125
+ const componentData = data['component'];
126
+
127
+ const { organization, library} = componentData;
128
+
129
+ let componentDefaults = await getComponentDefaults();
130
+ componentDefaults.library = library;
131
+
132
+
133
+ const questions = [
134
+ {
135
+ name: 'type',
136
+ type: 'rawlist',
137
+ message: 'Enter type of component',
138
+ choices: COMPONENT_SCHEMA.overrideType,
139
+ when (propmtType) {
140
+ return promptType === null;
141
+ }
142
+ },
143
+ {
144
+ name: 'componentName',
145
+ type: 'rawlist',
146
+ message: 'Enter component to be overridden',
147
+ choices: COMPONENT_SCHEMA.overrideComponent.forms,
148
+ when(answers) {
149
+ return answers.type === 'forms' || promptType === 'forms';
150
+ }
151
+ },
152
+ {
153
+ name: 'componentName',
154
+ type: 'rawlist',
155
+ message: 'Enter component to be overridden',
156
+ choices: COMPONENT_SCHEMA.overrideComponent.designSystemExtensions,
157
+ when(answers) {
158
+ return answers.type === 'designSystemExtensions' || promptType === 'designSystemExtensions';
159
+ }
160
+ },
161
+ {
162
+ name: 'componentName',
163
+ type: 'rawlist',
164
+ message: 'Enter component to be overridden',
165
+ choices: COMPONENT_SCHEMA.overrideComponent.infra,
166
+ when(answers) {
167
+ return answers.type === 'infra' || promptType === 'infra';
168
+ }
169
+ },
170
+ {
171
+ name: 'componentName',
172
+ type: 'rawlist',
173
+ message: 'Enter component to be overridden',
174
+ choices: COMPONENT_SCHEMA.overrideComponent.templates,
175
+ when(answers) {
176
+ return answers.type === 'templates' || promptType === 'templates';
177
+ }
178
+ },
179
+ {
180
+ name: 'componentName',
181
+ type: 'rawlist',
182
+ message: 'Enter component to be overridden',
183
+ choices: COMPONENT_SCHEMA.overrideComponent.widgets,
184
+ when(answers) {
185
+ return answers.type === 'widgets' || promptType === 'widgets';
186
+ }
187
+ },
188
+
189
+ ];
190
+
191
+ // get package version, so can display at create
192
+ const require = createRequire(import.meta.url);
193
+ const pData = require("@pega/dx-component-builder-sdk/package.json");
194
+
195
+ console.log(chalk.green("DX Component Builder - SDK vt" + pData.version));
196
+ await inquirer.prompt(questions).then(async answers => {
197
+ let {
198
+ componentName,
199
+ type
200
+ } = answers;
201
+ if (promptType) type = promptType;
202
+
203
+ await validateCompile(
204
+ {
205
+ componentName,
206
+ type
207
+ },
208
+ options
209
+ );
210
+ });
211
+
212
+ };
@@ -169,7 +169,7 @@ const validateSchema = ajv.compile(schema);
169
169
 
170
170
 
171
171
 
172
- export default async option => {
172
+ export default async (option, category = "custom") => {
173
173
  let componentToValidate = null;
174
174
  if (option.params && option.params[3]) {
175
175
  componentToValidate = option.params[3];
@@ -189,9 +189,26 @@ export default async option => {
189
189
  componentToValidate = option;
190
190
  }
191
191
 
192
- const componentDirectory = await getComponentDirectoryPath(componentToValidate);
192
+ const componentDirectory = await getComponentDirectoryPath(componentToValidate, category);
193
193
  const configFile = path.join(componentDirectory, 'config.json');
194
- const data = JSON.parse(fs.readFileSync(path.resolve(configFile), 'utf8'));
194
+ let configData;
195
+ try {
196
+ configData = fs.readFileSync(path.resolve(configFile), 'utf8');
197
+ }
198
+ catch (err) {
199
+ if (category == "custom") {
200
+ throw new Error(`Missing config file for: ${componentToValidate}`);
201
+ }
202
+ else if (category == "override") {
203
+ // for now, if now file just end
204
+ console.log(`${chalk.bold.yellow('config file not availabe for: ' + componentToValidate)}`);
205
+ return;
206
+ }
207
+ }
208
+
209
+ //const data = JSON.parse(fs.readFileSync(path.resolve(configFile), 'utf8'));
210
+ const data = JSON.parse(configData);
211
+
195
212
  const valid = validateSchema(data);
196
213
 
197
214
  if (valid) {