@pega/custom-dx-components 0.0.1 → 0.23.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.
- package/.vscode/extensions.json +1 -1
- package/README.md +6 -189
- package/package.json +34 -32
- package/src/auth.js +608 -0
- package/src/cli.js +42 -0
- package/src/constants.js +122 -8
- package/src/tasks/authenticate/helper.js +91 -8
- package/src/tasks/authenticate/index.js +169 -49
- package/src/tasks/build/helper.js +122 -0
- package/src/tasks/build/index.js +54 -0
- package/src/tasks/build-all/helper.js +70 -0
- package/src/tasks/build-all/index.js +79 -0
- package/src/tasks/{publish/bundle → bundle}/builder/index.js +49 -5
- package/src/tasks/{publish/bundle → bundle}/builder/webpack.config.js +5 -3
- package/src/tasks/{publish/bundle → bundle}/index.js +2 -2
- package/src/tasks/create/index.js +87 -64
- package/src/tasks/create/templates/Constellation/Field/Boolean/Boolean.js.mustache +38 -0
- package/src/tasks/create/templates/Constellation/Field/Boolean/boolean-format.js.mustache +26 -0
- package/src/tasks/create/templates/Constellation/Field/Boolean/config.json.mustache +145 -0
- package/src/tasks/create/templates/Constellation/Field/Boolean/demo.stories.jsx.mustache +61 -0
- package/src/tasks/create/templates/Constellation/Field/Boolean/event-utils.js.mustache +18 -0
- package/src/tasks/create/templates/Constellation/Field/Boolean/index.jsx.mustache +170 -0
- package/src/tasks/create/templates/Constellation/Field/Boolean/mock.stories.js.mustache +21 -0
- package/src/tasks/create/templates/Constellation/Field/Boolean/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Date/DateFormatter.js.mustache +61 -0
- package/src/tasks/create/templates/Constellation/Field/Date/FormattedText.jsx.mustache +41 -0
- package/src/tasks/create/templates/Constellation/Field/Date/config.json.mustache +195 -0
- package/src/tasks/create/templates/Constellation/Field/Date/date.js.mustache +439 -0
- package/src/tasks/create/templates/Constellation/Field/Date/demo.stories.jsx.mustache +73 -0
- package/src/tasks/create/templates/Constellation/Field/Date/index.jsx.mustache +256 -0
- package/src/tasks/create/templates/Constellation/Field/Date/mock.stories.js.mustache +23 -0
- package/src/tasks/create/templates/Constellation/Field/Date/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Date/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/DateTime/config.json.mustache +256 -0
- package/src/tasks/create/templates/Constellation/Field/DateTime/date-time.js.mustache +92 -0
- package/src/tasks/create/templates/Constellation/Field/DateTime/date-utils.js.mustache +287 -0
- package/src/tasks/create/templates/Constellation/Field/DateTime/date.js.mustache +328 -0
- package/src/tasks/create/templates/Constellation/Field/DateTime/demo.stories.jsx.mustache +73 -0
- package/src/tasks/create/templates/Constellation/Field/DateTime/index.jsx.mustache +254 -0
- package/src/tasks/create/templates/Constellation/Field/DateTime/mock.stories.js.mustache +23 -0
- package/src/tasks/create/templates/Constellation/Field/DateTime/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/DateTime/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal/config.json.mustache +278 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal/demo.stories.jsx.mustache +49 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal/event-utils.js.mustache +18 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal/index.jsx.mustache +273 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal/mock.stories.js.mustache +21 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Currency/config.json.mustache +291 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Currency/demo.stories.jsx.mustache +53 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Currency/event-utils.js.mustache +18 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Currency/index.jsx.mustache +299 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Currency/mock.stories.js.mustache +23 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Currency/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Currency/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Percentage/config.json.mustache +93 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Percentage/demo.stories.jsx.mustache +49 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Percentage/event-utils.js.mustache +18 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Percentage/index.jsx.mustache +281 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Percentage/mock.stories.js.mustache +21 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Percentage/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Percentage/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/Integer/config.json.mustache +347 -0
- package/src/tasks/create/templates/Constellation/Field/Integer/demo.stories.jsx.mustache +49 -0
- package/src/tasks/create/templates/Constellation/Field/Integer/event-utils.js.mustache +18 -0
- package/src/tasks/create/templates/Constellation/Field/Integer/index.jsx.mustache +336 -0
- package/src/tasks/create/templates/Constellation/Field/Integer/mock.stories.js.mustache +21 -0
- package/src/tasks/create/templates/Constellation/Field/Integer/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Integer/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/Picklist/config.json.mustache +114 -0
- package/src/tasks/create/templates/Constellation/Field/Picklist/demo.stories.jsx.mustache +78 -0
- package/src/tasks/create/templates/Constellation/Field/Picklist/event-utils.js.mustache +18 -0
- package/src/tasks/create/templates/Constellation/Field/Picklist/index.jsx.mustache +351 -0
- package/src/tasks/create/templates/Constellation/Field/Picklist/mock.stories.js.mustache +67 -0
- package/src/tasks/create/templates/Constellation/Field/Picklist/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Picklist/suggestions-handler.js +10 -0
- package/src/tasks/create/{template → templates/Constellation/Field/Text}/config.json.mustache +14 -5
- package/src/tasks/create/templates/Constellation/Field/Text/demo.stories.jsx.mustache +51 -0
- package/src/tasks/create/{template → templates/Constellation/Field/Text}/index.jsx.mustache +5 -0
- package/src/tasks/create/templates/Constellation/Field/Text/mock.stories.js.mustache +13 -0
- package/src/tasks/create/templates/Constellation/Field/Text/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Email/config.json.mustache +111 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Email/demo.stories.jsx.mustache +48 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Email/event-utils.js.mustache +18 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Email/index.jsx.mustache +231 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Email/mock.stories.js.mustache +22 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Email/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Email/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Input/StatusWork.jsx +26 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Input/config.json.mustache +111 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Input/demo.stories.jsx.mustache +48 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Input/event-utils.js.mustache +18 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Input/index.jsx.mustache +239 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Input/mock.stories.js.mustache +21 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Input/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Input/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Paragraph/config.json.mustache +111 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Paragraph/demo.stories.jsx.mustache +48 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Paragraph/event-utils.js.mustache +18 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Paragraph/index.jsx.mustache +231 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Paragraph/mock.stories.js.mustache +20 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Paragraph/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Paragraph/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Phone/config.json.mustache +123 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Phone/demo.stories.jsx.mustache +46 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Phone/event-utils.js.mustache +18 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Phone/index.jsx.mustache +267 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Phone/mock.stories.js.mustache +37 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Phone/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Phone/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/Text-URL/config.json.mustache +237 -0
- package/src/tasks/create/templates/Constellation/Field/Text-URL/demo.stories.jsx.mustache +46 -0
- package/src/tasks/create/templates/Constellation/Field/Text-URL/event-utils.js.mustache +18 -0
- package/src/tasks/create/templates/Constellation/Field/Text-URL/index.jsx.mustache +232 -0
- package/src/tasks/create/templates/Constellation/Field/Text-URL/mock.stories.js.mustache +22 -0
- package/src/tasks/create/templates/Constellation/Field/Text-URL/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/Text-URL/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/Text-URL/text-url.jsx.mustache +173 -0
- package/src/tasks/create/templates/Constellation/Field/TimeOfDay/config.json.mustache +185 -0
- package/src/tasks/create/templates/Constellation/Field/TimeOfDay/demo.stories.jsx.mustache +57 -0
- package/src/tasks/create/templates/Constellation/Field/TimeOfDay/index.jsx.mustache +213 -0
- package/src/tasks/create/templates/Constellation/Field/TimeOfDay/mock.stories.js.mustache +20 -0
- package/src/tasks/create/templates/Constellation/Field/TimeOfDay/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Field/TimeOfDay/suggestions-handler.js +10 -0
- package/src/tasks/create/templates/Constellation/Field/TimeOfDay/time-of-day.js.mustache +287 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS/OneColumnDetails.svg +22 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS/StatusWork.jsx.mustache +26 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS/config.json.mustache +35 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS/demo.stories.jsx.mustache +132 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS/index.jsx.mustache +86 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS/mock.stories.js.mustache +189 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS/utils.js.mustache +152 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/StatusWork.jsx.mustache +26 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/TwoColumnDetails.svg +28 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/config.json.mustache +42 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/demo.stories.jsx.mustache +136 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/index.jsx.mustache +86 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/mock.stories.js.mustache +230 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/utils.js.mustache +155 -0
- package/src/tasks/create/templates/Constellation/Template/FORM/DefaultForm.svg +29 -0
- package/src/tasks/create/templates/Constellation/Template/FORM/config.json.mustache +45 -0
- package/src/tasks/create/templates/Constellation/Template/FORM/demo.stories.jsx.mustache +169 -0
- package/src/tasks/create/templates/Constellation/Template/FORM/index.jsx.mustache +45 -0
- package/src/tasks/create/templates/Constellation/Template/FORM/mock.stories.js.mustache +137 -0
- package/src/tasks/create/templates/Constellation/Template/FORM/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Template/FORM-region/TwoColumn.svg +38 -0
- package/src/tasks/create/templates/Constellation/Template/FORM-region/config.json.mustache +27 -0
- package/src/tasks/create/templates/Constellation/Template/FORM-region/demo.stories.jsx.mustache +178 -0
- package/src/tasks/create/templates/Constellation/Template/FORM-region/index.jsx.mustache +48 -0
- package/src/tasks/create/templates/Constellation/Template/FORM-region/mock.stories.js.mustache +143 -0
- package/src/tasks/create/templates/Constellation/Template/FORM-region/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Template/PAGE/GetNextWork.jsx.mustache +35 -0
- package/src/tasks/create/templates/Constellation/Template/PAGE/OneColumnPage.svg +36 -0
- package/src/tasks/create/templates/Constellation/Template/PAGE/config.json.mustache +32 -0
- package/src/tasks/create/templates/Constellation/Template/PAGE/demo.stories.jsx.mustache +102 -0
- package/src/tasks/create/templates/Constellation/Template/PAGE/index.jsx.mustache +70 -0
- package/src/tasks/create/templates/Constellation/Template/PAGE/localizations.json.mustache +4 -0
- package/src/tasks/create/templates/Constellation/Template/PAGE/mock.stories.js.mustache +94 -0
- package/src/tasks/create/templates/Constellation/Template/PAGE/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Template/PAGE/utils.js.mustache +229 -0
- package/src/tasks/create/templates/Constellation/Widget/CASE/OneColumnPage.svg +36 -0
- package/src/tasks/create/templates/Constellation/Widget/CASE/config.json.mustache +23 -0
- package/src/tasks/create/templates/Constellation/Widget/CASE/demo.stories.jsx.mustache +78 -0
- package/src/tasks/create/templates/Constellation/Widget/CASE/index.jsx.mustache +76 -0
- package/src/tasks/create/templates/Constellation/Widget/CASE/mock.stories.js.mustache +390 -0
- package/src/tasks/create/{template → templates/Constellation/Widget/CASE}/styles.js.mustache +1 -1
- package/src/tasks/create/templates/Constellation/Widget/PAGE/OneColumnPage.svg +36 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE/config.json.mustache +59 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE/demo.stories.jsx.mustache +30 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE/index.jsx.mustache +48 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE/mock.stories.js.mustache +23 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE/styles.js.mustache +7 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/Avatar.jsx.mustache +75 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/OneColumnPage.svg +36 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/Operator.jsx.mustache +240 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/config.json.mustache +66 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/demo.stories.jsx.mustache +68 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/index.jsx.mustache +110 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/mock.stories.js.mustache +51 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/styles.js.mustache +7 -0
- package/src/tasks/create-all/index.js +398 -0
- package/src/tasks/delete/helper.js +6 -4
- package/src/tasks/delete/index.js +4 -0
- package/src/tasks/delete-all/helper.js +153 -0
- package/src/tasks/delete-all/index.js +49 -0
- package/src/tasks/generate-ai/aiPrompt.txt.mustache +121 -0
- package/src/tasks/generate-ai/helper.js +184 -0
- package/src/tasks/generate-ai/index.js +33 -0
- package/src/tasks/index.js +7 -0
- package/src/tasks/init/index.js +9 -3
- package/src/tasks/init/template/.eslintignore +8 -0
- package/src/tasks/init/template/.eslintrc.json +186 -5
- package/src/tasks/init/template/.vscode/extensions.json +1 -1
- package/src/tasks/init/template/README.md +80 -61
- package/src/tasks/init/template/keys/DX-ComponentDev.zip +0 -0
- package/src/tasks/init/template/keys/dxcb.crt +32 -0
- package/src/tasks/init/template/keys/dxcb.key +51 -0
- package/src/tasks/init/template/package.json.mustache +44 -21
- package/src/tasks/init/template/tasks.config.json +19 -5
- package/src/tasks/init/template/templateNPMRC.txt +8 -0
- package/src/tasks/linter/index.js +46 -0
- package/src/tasks/list/helper.js +19 -6
- package/src/tasks/list/index.js +4 -0
- package/src/tasks/publish/helper.js +13 -4
- package/src/tasks/publish/index.js +14 -1
- package/src/tasks/publish-all/helper.js +154 -0
- package/src/tasks/publish-all/index.js +95 -0
- package/src/tasks/rename/index.js +314 -0
- package/src/tasks/validator/index.js +291 -18
- package/src/util.js +247 -6
- package/src/tasks/create/template/demo.stories.jsx.mustache +0 -44
- package/src/tasks/init/template/src/components/MBTAList/MBTAList.stories.tsx +0 -10
- package/src/tasks/init/template/src/components/MBTAList/MBTAList.tsx +0 -122
- package/src/tasks/init/template/src/components/MBTAList/icons/accessible.icon.tsx +0 -14
- package/src/tasks/init/template/src/components/MBTAList/icons/bus.icon.tsx +0 -13
- package/src/tasks/init/template/src/components/MBTAList/icons/mbta.icon.tsx +0 -10
- package/src/tasks/init/template/src/components/MBTAList/icons/subway.icon.tsx +0 -14
- package/src/tasks/init/template/src/components/MBTAList/index.ts +0 -2
- /package/src/tasks/{publish/bundle → bundle}/builder/modules.js +0 -0
- /package/src/tasks/{publish/bundle → bundle}/builder/paths.js +0 -0
|
@@ -4,10 +4,15 @@ import chalk from 'chalk';
|
|
|
4
4
|
|
|
5
5
|
import validate from '../validator/index.js';
|
|
6
6
|
|
|
7
|
-
import bundleComponent from '
|
|
7
|
+
import bundleComponent from '../bundle/index.js';
|
|
8
|
+
import { lintComponent } from '../linter/index.js';
|
|
9
|
+
|
|
10
|
+
import { getComponentDirectoryPath, showVersion } from '../../util.js';
|
|
8
11
|
import { getPublishComponentQuestions, publishComponentToServer, zipComponent } from './helper.js';
|
|
9
12
|
|
|
10
13
|
export default async options => {
|
|
14
|
+
showVersion();
|
|
15
|
+
|
|
11
16
|
const questions = await getPublishComponentQuestions();
|
|
12
17
|
const answers = await inquirer.prompt(questions);
|
|
13
18
|
const { componentKey, sourceMap, devBuild } = answers;
|
|
@@ -24,6 +29,14 @@ export default async options => {
|
|
|
24
29
|
await validate(componentKey);
|
|
25
30
|
}
|
|
26
31
|
},
|
|
32
|
+
{
|
|
33
|
+
title: 'Lint component',
|
|
34
|
+
task: async () => {
|
|
35
|
+
const targetDirectory = await getComponentDirectoryPath(componentKey);
|
|
36
|
+
// console.log(`in buildComponent Lint component task: componentKey: ${componentKey} targetDirectory: ${targetDirectory}`);
|
|
37
|
+
await lintComponent(targetDirectory);
|
|
38
|
+
}
|
|
39
|
+
},
|
|
27
40
|
{
|
|
28
41
|
title: 'Bundle Component',
|
|
29
42
|
task: async () => await bundleComponent(componentKey, sourceMap, devBuild),
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import https from 'https';
|
|
4
|
+
|
|
5
|
+
import fetch from 'node-fetch';
|
|
6
|
+
import AdmZip from 'adm-zip';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
constructCompleteUrl,
|
|
11
|
+
getComponentDirectoryPath,
|
|
12
|
+
getComponents,
|
|
13
|
+
getPegaServerConfig,
|
|
14
|
+
validateRulesetVersion
|
|
15
|
+
} from '../../util.js';
|
|
16
|
+
import { PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT, TOKEN_PATH } from '../../constants.js';
|
|
17
|
+
|
|
18
|
+
export const getPublishComponentQuestions = async () => {
|
|
19
|
+
const components = await getComponents();
|
|
20
|
+
const defaultPegaConfig = await getPegaServerConfig();
|
|
21
|
+
|
|
22
|
+
return [
|
|
23
|
+
{
|
|
24
|
+
name: 'rulesetName',
|
|
25
|
+
message: 'Enter ruleset name',
|
|
26
|
+
default: defaultPegaConfig.rulesetName,
|
|
27
|
+
validate: value => {
|
|
28
|
+
if (value.trim()) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return 'Ruleset name cannot be empty';
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'rulesetVersion',
|
|
36
|
+
message: 'Enter ruleset version',
|
|
37
|
+
default: defaultPegaConfig.rulesetVersion,
|
|
38
|
+
validate: value => {
|
|
39
|
+
if (validateRulesetVersion(value)) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return 'Please provide compatible version e.g 01-01-01';
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'sourceMap',
|
|
47
|
+
message: 'Generate source map ?',
|
|
48
|
+
default: defaultPegaConfig.sourceMap,
|
|
49
|
+
when: () => false && !process.env.SOURCE_MAP
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'devBuild',
|
|
53
|
+
message: 'Generate development build ?',
|
|
54
|
+
default: defaultPegaConfig.devBuild
|
|
55
|
+
}
|
|
56
|
+
];
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const zipComponent = async componentKey => {
|
|
60
|
+
const srcDirectory = await getComponentDirectoryPath(componentKey);
|
|
61
|
+
const buildDirectory = await path.join(path.resolve(), 'dist/components', componentKey);
|
|
62
|
+
const configJson = `${srcDirectory}/config.json`;
|
|
63
|
+
|
|
64
|
+
const zip = new AdmZip();
|
|
65
|
+
|
|
66
|
+
zip.addLocalFolder(srcDirectory, 'src/');
|
|
67
|
+
zip.addLocalFile(configJson);
|
|
68
|
+
zip.addLocalFolder(buildDirectory);
|
|
69
|
+
const zipContent = zip.toBuffer().toString('base64');
|
|
70
|
+
|
|
71
|
+
const configContent = Buffer.from(fs.readFileSync(`${srcDirectory}/config.json`)).toString();
|
|
72
|
+
// clean up now happens in function cleanUp
|
|
73
|
+
//fs.rmdir('dist', { recursive: true }, err => {
|
|
74
|
+
// if (err) {
|
|
75
|
+
// throw err;
|
|
76
|
+
// }
|
|
77
|
+
//});
|
|
78
|
+
return { zipContent, configContent };
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const cleanUp = async () => {
|
|
82
|
+
fs.rm('dist/components', { recursive: true }, err => {
|
|
83
|
+
if (err) {
|
|
84
|
+
throw err;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
fs.rm('lib', { recursive: true }, err => {
|
|
89
|
+
if (err) {
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const publishComponentToServer = async data => {
|
|
96
|
+
const { configContent, zipContent, componentKey, rulesetName, rulesetVersion } = data;
|
|
97
|
+
|
|
98
|
+
const apiBody = {
|
|
99
|
+
configContent,
|
|
100
|
+
zipContent,
|
|
101
|
+
componentKey: JSON.parse(configContent).componentKey,
|
|
102
|
+
publishFor: 'constellation',
|
|
103
|
+
rulesetName,
|
|
104
|
+
rulesetVersion,
|
|
105
|
+
category: ''
|
|
106
|
+
};
|
|
107
|
+
const defaultPegaConfig = await getPegaServerConfig();
|
|
108
|
+
const url = constructCompleteUrl(
|
|
109
|
+
defaultPegaConfig.server,
|
|
110
|
+
PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT
|
|
111
|
+
);
|
|
112
|
+
try {
|
|
113
|
+
const OauthData = fs.readFileSync(TOKEN_PATH, 'utf8');
|
|
114
|
+
if (OauthData) {
|
|
115
|
+
const {
|
|
116
|
+
access_token: accessToken,
|
|
117
|
+
token_type: tokenType,
|
|
118
|
+
refresh_token: refreshToken
|
|
119
|
+
} = JSON.parse(OauthData);
|
|
120
|
+
let status = 500;
|
|
121
|
+
fetch(url, {
|
|
122
|
+
method: 'POST',
|
|
123
|
+
agent: new https.Agent({ rejectUnauthorized: false }),
|
|
124
|
+
headers: {
|
|
125
|
+
Authorization: `${tokenType} ${accessToken}`
|
|
126
|
+
},
|
|
127
|
+
body: JSON.stringify(apiBody)
|
|
128
|
+
})
|
|
129
|
+
.then(response => {
|
|
130
|
+
status = response.status;
|
|
131
|
+
return response.text();
|
|
132
|
+
})
|
|
133
|
+
.then(resp => {
|
|
134
|
+
const respData = JSON.parse(resp);
|
|
135
|
+
if (status === 401) {
|
|
136
|
+
throw new Error(
|
|
137
|
+
'Error occurred in authentication. Please regenerate using authenticate'
|
|
138
|
+
);
|
|
139
|
+
// console.log(accessTokenUri, refreshToken);
|
|
140
|
+
/* TODO - Handle refresh_token */
|
|
141
|
+
} else if (status == 200) {
|
|
142
|
+
console.log(chalk.bold.green(`Success : ${respData.message}`));
|
|
143
|
+
} else {
|
|
144
|
+
throw new Error(`${respData.message}`);
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
.catch(e => Promise.reject(`${chalk.bold.red(e)}`));
|
|
148
|
+
} else {
|
|
149
|
+
throw new Error(`Error occurred in authentication. Please regenerate using authenticate`);
|
|
150
|
+
}
|
|
151
|
+
} catch (err) {
|
|
152
|
+
throw new Error(`Error occurred in authentication. Please regenerate using authenticate`);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import Listr from 'listr';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
|
|
5
|
+
import validate from '../validator/index.js';
|
|
6
|
+
|
|
7
|
+
import bundleComponent from '../bundle/index.js';
|
|
8
|
+
import { lintComponent } from '../linter/index.js';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
import { getPublishComponentQuestions, publishComponentToServer, zipComponent, cleanUp } from './helper.js';
|
|
12
|
+
import {
|
|
13
|
+
getComponents,
|
|
14
|
+
getComponentDirectoryPath,
|
|
15
|
+
showVersion
|
|
16
|
+
} from '../../util.js';
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
export function getCustomTasks(componentKey, sourceMap, devBuild, content, options) {
|
|
21
|
+
const customTasks = new Listr(
|
|
22
|
+
[
|
|
23
|
+
{
|
|
24
|
+
title: 'Validate config schema',
|
|
25
|
+
task: async () => {
|
|
26
|
+
await validate(componentKey);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
title: 'Bundle Component',
|
|
31
|
+
task: async () => await bundleComponent(componentKey, sourceMap, devBuild),
|
|
32
|
+
skip: () => (options.skipBundle ? 'Skipped bundling component' : undefined)
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
title: 'Lint component',
|
|
36
|
+
task: async () => {
|
|
37
|
+
const targetDirectory = await getComponentDirectoryPath(componentKey);
|
|
38
|
+
// console.log(`in buildComponent Lint component task: componentKey: ${componentKey} targetDirectory: ${targetDirectory}`);
|
|
39
|
+
await lintComponent(targetDirectory);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
title: 'Zip Component',
|
|
44
|
+
task: async () => {
|
|
45
|
+
const output = await zipComponent(componentKey);
|
|
46
|
+
content = { ...content, ...output };
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
title: 'Publish Component',
|
|
51
|
+
task: async () => {
|
|
52
|
+
await publishComponentToServer(content);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
{
|
|
57
|
+
exitOnError: true
|
|
58
|
+
}
|
|
59
|
+
);
|
|
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
|
+
|
|
79
|
+
for (var index in components) {
|
|
80
|
+
componentKey = components[index];
|
|
81
|
+
console.log(chalk.bold.green("Publishing: " + componentKey));
|
|
82
|
+
|
|
83
|
+
let myCustomTasks = getCustomTasks(componentKey, sourceMap, devBuild, content, options);
|
|
84
|
+
|
|
85
|
+
await myCustomTasks.run().catch(err => {
|
|
86
|
+
console.log(chalk.bold.red(err.toString()));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// once done, remove leftover directories
|
|
91
|
+
cleanUp();
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
return true;
|
|
95
|
+
};
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { promisify } from 'util';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
import ncp from 'ncp';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
|
|
10
|
+
import { checkPathAccess, showVersion, getComponentsObj, getDirectoryFiles } from '../../util.js';
|
|
11
|
+
import { TASKS_CONFIG_JSON_FILENAME, COMPONENTS_DIRECTORY_PATH, COMPONENTS_PATH } from '../../constants.js';
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export const DXCB_CONFIG_INTERNAL_JSON_FILENAME = 'src/dxcb.config.json';
|
|
16
|
+
const currentDirectory = process.cwd();
|
|
17
|
+
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
convertIntoPascalCase,
|
|
22
|
+
getComponentDirectoryPath,
|
|
23
|
+
getPegaConfig,
|
|
24
|
+
getComponentDefaults,
|
|
25
|
+
sanitize,
|
|
26
|
+
validateSemver
|
|
27
|
+
} from '../../util.js';
|
|
28
|
+
import { COMPONENT_SCHEMA } from '../../constants.js';
|
|
29
|
+
|
|
30
|
+
const copy = promisify(ncp);
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
export const updateConfig = async (
|
|
34
|
+
{
|
|
35
|
+
oldComponentKey,
|
|
36
|
+
newComponentKey,
|
|
37
|
+
library,
|
|
38
|
+
organization,
|
|
39
|
+
componentName,
|
|
40
|
+
componentLabel,
|
|
41
|
+
version,
|
|
42
|
+
description,
|
|
43
|
+
allowedApplications,
|
|
44
|
+
targetDirectory,
|
|
45
|
+
},
|
|
46
|
+
options,
|
|
47
|
+
onlyCompanion = false
|
|
48
|
+
) => {
|
|
49
|
+
|
|
50
|
+
let configData = fs.readFileSync(join(targetDirectory, "/config.json"), { encoding: 'utf8' });
|
|
51
|
+
configData = configData && JSON.parse(configData);
|
|
52
|
+
|
|
53
|
+
configData.name = newComponentKey;
|
|
54
|
+
configData.label = componentLabel;
|
|
55
|
+
configData.organization = organization;
|
|
56
|
+
if (configData.componentKey) configData.componentKey = newComponentKey;
|
|
57
|
+
configData.library = library;
|
|
58
|
+
configData.version = version;
|
|
59
|
+
configData.description = (description != '') ? description : componentLabel;
|
|
60
|
+
|
|
61
|
+
if (allowedApplications.trim() === '') {
|
|
62
|
+
allowedApplications = [];
|
|
63
|
+
} else {
|
|
64
|
+
if (allowedApplications.indexOf(',') !== -1) {
|
|
65
|
+
allowedApplications = allowedApplications.split(',');
|
|
66
|
+
}
|
|
67
|
+
allowedApplications = [].concat(allowedApplications);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
allowedApplications = allowedApplications.filter(el => !!el.trim()).map(el => el.trim());
|
|
71
|
+
|
|
72
|
+
configData.allowedApplications = allowedApplications;
|
|
73
|
+
|
|
74
|
+
// stringify "4", makes the json string look like JSON in the file, formated instead of a single line
|
|
75
|
+
fs.writeFileSync(join(targetDirectory, "/config.json"), JSON.stringify(configData, null, 4), { encoding: 'utf8' });
|
|
76
|
+
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const updateFile = async (
|
|
80
|
+
fileName,
|
|
81
|
+
oldComponentKeyPC,
|
|
82
|
+
newComponentKeyPC,
|
|
83
|
+
targetDirectory,
|
|
84
|
+
) => {
|
|
85
|
+
|
|
86
|
+
let fileData = fs.readFileSync(join(targetDirectory, "/", fileName), { encoding: 'utf8' });
|
|
87
|
+
|
|
88
|
+
if (fileData.indexOf(oldComponentKeyPC) >= 0) {
|
|
89
|
+
fileData = fileData.replaceAll(oldComponentKeyPC, newComponentKeyPC);
|
|
90
|
+
|
|
91
|
+
fs.writeFileSync(join(targetDirectory, "/", fileName), fileData, { encoding: 'utf8' });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
export const renameComponent = async (
|
|
98
|
+
{
|
|
99
|
+
library,
|
|
100
|
+
organization,
|
|
101
|
+
componentKey,
|
|
102
|
+
componentName,
|
|
103
|
+
componentLabel,
|
|
104
|
+
version,
|
|
105
|
+
description,
|
|
106
|
+
allowedApplications
|
|
107
|
+
},
|
|
108
|
+
options,
|
|
109
|
+
onlyCompanion = false
|
|
110
|
+
) => {
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
let pegaConfig = await getPegaConfig();
|
|
114
|
+
|
|
115
|
+
const newComponentKey = `${organization}_${library}_${componentName}`;
|
|
116
|
+
|
|
117
|
+
const oldComponentKey = componentKey;
|
|
118
|
+
const newComponentKeyPC = convertIntoPascalCase(newComponentKey);
|
|
119
|
+
const oldComponentKeyPC = convertIntoPascalCase(oldComponentKey);
|
|
120
|
+
|
|
121
|
+
const currentDirectory = await getComponentDirectoryPath(componentKey);
|
|
122
|
+
const targetDirectory = await getComponentDirectoryPath(newComponentKey);
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
// custom component
|
|
128
|
+
try {
|
|
129
|
+
fs.renameSync(currentDirectory, targetDirectory);
|
|
130
|
+
} catch(err) {
|
|
131
|
+
console.log(err)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const targetFileList = await getDirectoryFiles(targetDirectory);
|
|
135
|
+
|
|
136
|
+
for (var fileIndex in targetFileList) {
|
|
137
|
+
const fileName = targetFileList[fileIndex];
|
|
138
|
+
|
|
139
|
+
if (fileName === "config.json") {
|
|
140
|
+
await updateConfig(
|
|
141
|
+
{
|
|
142
|
+
oldComponentKey,
|
|
143
|
+
newComponentKey,
|
|
144
|
+
componentName,
|
|
145
|
+
componentLabel,
|
|
146
|
+
library,
|
|
147
|
+
version,
|
|
148
|
+
description,
|
|
149
|
+
allowedApplications,
|
|
150
|
+
organization,
|
|
151
|
+
targetDirectory,
|
|
152
|
+
},
|
|
153
|
+
options
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
await updateFile(
|
|
158
|
+
fileName,
|
|
159
|
+
oldComponentKeyPC,
|
|
160
|
+
newComponentKeyPC,
|
|
161
|
+
targetDirectory );
|
|
162
|
+
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
} // for
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
console.log(chalk.green(`Component ${oldComponentKey} renamed to ${newComponentKey}`));
|
|
169
|
+
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
export default async options => {
|
|
177
|
+
showVersion();
|
|
178
|
+
|
|
179
|
+
await checkPathAccess(pegaConfigJsonPath);
|
|
180
|
+
|
|
181
|
+
let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
|
|
182
|
+
data = data && JSON.parse(data);
|
|
183
|
+
|
|
184
|
+
if (!data[COMPONENTS_DIRECTORY_PATH]) {
|
|
185
|
+
console.error(
|
|
186
|
+
`${chalk.red.bold('ERROR')} Could not able find components directory path in config.json`
|
|
187
|
+
);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const componentData = data[COMPONENTS_PATH];
|
|
192
|
+
|
|
193
|
+
const { library } = componentData;
|
|
194
|
+
const { organization } = JSON.parse(fs.readFileSync(path.resolve('package.json'), 'utf8'));
|
|
195
|
+
|
|
196
|
+
let componentDefaults = await getComponentDefaults();
|
|
197
|
+
componentDefaults.library = library;
|
|
198
|
+
|
|
199
|
+
const localComponents = await getComponentsObj();
|
|
200
|
+
|
|
201
|
+
const questions = [
|
|
202
|
+
{
|
|
203
|
+
name: 'componentKey',
|
|
204
|
+
type: 'rawlist',
|
|
205
|
+
pageSize: 15,
|
|
206
|
+
message: 'Select component to rename',
|
|
207
|
+
choices: localComponents
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: 'componentName',
|
|
211
|
+
message: 'Enter new component name (required, no spaces)',
|
|
212
|
+
validate: value => {
|
|
213
|
+
/* value should not be empty
|
|
214
|
+
It should not have spaces
|
|
215
|
+
It should not start with a number
|
|
216
|
+
Only case-insensitive alphanumeric values are allowed
|
|
217
|
+
*/
|
|
218
|
+
if (value && !/^\d/.test(value) && value === sanitize(value)) {
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
return 'Only alphanumeric values are allowed, starting with alphabets';
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: 'componentLabel',
|
|
226
|
+
message: 'Enter new component label for display (required)',
|
|
227
|
+
validate: value => {
|
|
228
|
+
if (value) {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
return 'Please provide value for label';
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: 'organization',
|
|
236
|
+
message: 'Enter new component organization',
|
|
237
|
+
default: organization,
|
|
238
|
+
validate: value => {
|
|
239
|
+
if (value) {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
return 'Please provide value for organization';
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
name: 'version',
|
|
247
|
+
message: 'Enter new component version',
|
|
248
|
+
default: componentDefaults.version,
|
|
249
|
+
validate: value => {
|
|
250
|
+
if (validateSemver(value)) {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
return 'Please provide semver compatible version e.g 0.0.1';
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
name: 'library',
|
|
258
|
+
message: 'Enter new library name (required)',
|
|
259
|
+
default: componentDefaults.library,
|
|
260
|
+
validate: value => {
|
|
261
|
+
/* value should not be empty
|
|
262
|
+
It should not have spaces
|
|
263
|
+
It should not start with a number
|
|
264
|
+
Only case-insensitive alphanumeric values are allowed
|
|
265
|
+
*/
|
|
266
|
+
if (value && !/^\d/.test(value) && value === sanitize(value)) {
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
return 'Only alphanumeric values are allowed, starting with alphabets';
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: 'allowedApplications',
|
|
274
|
+
message: 'Please enter the application names to be supported (comma-separated). ',
|
|
275
|
+
suffix: 'Keep empty for all applications'
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
name: 'description',
|
|
279
|
+
message: 'Enter new description for the component (defaults to new label)',
|
|
280
|
+
default: componentDefaults.description,
|
|
281
|
+
/* if left blank and no defaults, mustache will use componentLabel, because description is used in app studio and
|
|
282
|
+
shouldn't be blank */
|
|
283
|
+
}
|
|
284
|
+
];
|
|
285
|
+
|
|
286
|
+
await inquirer.prompt(questions).then(async answers => {
|
|
287
|
+
const {
|
|
288
|
+
componentKey,
|
|
289
|
+
componentName,
|
|
290
|
+
componentLabel,
|
|
291
|
+
organization,
|
|
292
|
+
library,
|
|
293
|
+
version,
|
|
294
|
+
description,
|
|
295
|
+
allowedApplications
|
|
296
|
+
} = answers;
|
|
297
|
+
|
|
298
|
+
await renameComponent(
|
|
299
|
+
{
|
|
300
|
+
componentKey,
|
|
301
|
+
componentName,
|
|
302
|
+
componentLabel,
|
|
303
|
+
library,
|
|
304
|
+
version,
|
|
305
|
+
description,
|
|
306
|
+
allowedApplications,
|
|
307
|
+
organization
|
|
308
|
+
},
|
|
309
|
+
options
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
};
|