@pega/custom-dx-components 25.1.12 → 25.1.14
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/eslint.config.mjs +8 -19
- package/package.json +1 -1
- package/src/cli.js +7 -1
- package/src/tasks/create/index.js +11 -3
- package/src/tasks/create-all/index.js +11 -2
- package/src/tasks/export-rc/helper.js +356 -0
- package/src/tasks/export-rc/index.js +268 -0
- package/src/tasks/index.js +1 -0
- package/src/tasks/init/template/eslint.config.mjs +7 -16
- package/src/tasks/init/template/package.json.mustache +5 -3
- package/src/util.js +9 -2
package/eslint.config.mjs
CHANGED
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
import { globalIgnores } from 'eslint/config';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import
|
|
5
|
-
import { FlatCompat } from '@eslint/eslintrc';
|
|
3
|
+
import eslint from '@eslint/js';
|
|
6
4
|
import tseslint from 'typescript-eslint';
|
|
7
5
|
import sonarjs from 'eslint-plugin-sonarjs';
|
|
8
6
|
import importPlugin from 'eslint-plugin-import';
|
|
9
7
|
import react from 'eslint-plugin-react';
|
|
10
8
|
import reactHooks from 'eslint-plugin-react-hooks';
|
|
9
|
+
// eslint.config.js
|
|
10
|
+
import { defineConfig } from 'eslint/config';
|
|
11
11
|
|
|
12
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
-
const __dirname = path.dirname(__filename);
|
|
14
|
-
const compat = new FlatCompat({
|
|
15
|
-
baseDirectory: __dirname,
|
|
16
|
-
recommendedConfig: js.configs.recommended,
|
|
17
|
-
sonarjs: sonarjs.configs.recommended,
|
|
18
|
-
importPlugin: importPlugin.configs.recommended,
|
|
19
|
-
react: react.configs.recommended,
|
|
20
|
-
reactHooks: reactHooks.configs.recommended,
|
|
21
|
-
allConfig: js.configs.all
|
|
22
|
-
});
|
|
23
13
|
|
|
24
|
-
export default
|
|
25
|
-
|
|
14
|
+
export default defineConfig([
|
|
15
|
+
eslint.configs.recommended,
|
|
16
|
+
...tseslint.configs.recommended,
|
|
26
17
|
globalIgnores([
|
|
27
18
|
'**/node_modules',
|
|
28
19
|
'packages/*/lib',
|
|
@@ -32,6 +23,7 @@ export default tseslint.config(
|
|
|
32
23
|
'**/mock.stories.js',
|
|
33
24
|
'**/demo.stories.tsx',
|
|
34
25
|
'**/demo.test.tsx',
|
|
26
|
+
'**/*.test.tsx',
|
|
35
27
|
'**/mock.stories.ts',
|
|
36
28
|
'**/*.mdx',
|
|
37
29
|
'**/webpack.config.js',
|
|
@@ -131,7 +123,6 @@ export default tseslint.config(
|
|
|
131
123
|
'no-alert': 'off',
|
|
132
124
|
'no-console': 'error',
|
|
133
125
|
'no-fallthrough': 'error',
|
|
134
|
-
'no-undef': 'error',
|
|
135
126
|
'no-unused-vars': 'off',
|
|
136
127
|
'no-var': 'off',
|
|
137
128
|
yoda: 'error',
|
|
@@ -155,7 +146,6 @@ export default tseslint.config(
|
|
|
155
146
|
'react/no-unused-prop-types': 'error',
|
|
156
147
|
'react/static-property-placement': 'error',
|
|
157
148
|
'array-callback-return': 'error',
|
|
158
|
-
camelcase: 'error',
|
|
159
149
|
'func-names': 'error',
|
|
160
150
|
'no-case-declarations': 'error',
|
|
161
151
|
'no-lonely-if': 'error',
|
|
@@ -208,7 +198,6 @@ export default tseslint.config(
|
|
|
208
198
|
{
|
|
209
199
|
files: ['**/*.@(ts|tsx)'],
|
|
210
200
|
rules: {
|
|
211
|
-
'no-undef': 'error',
|
|
212
201
|
'no-console': 'off',
|
|
213
202
|
'import/prefer-default-export': 'off',
|
|
214
203
|
'import/no-relative-packages': 'off',
|
|
@@ -230,4 +219,4 @@ export default tseslint.config(
|
|
|
230
219
|
'import/prefer-default-export': ['off']
|
|
231
220
|
}
|
|
232
221
|
}
|
|
233
|
-
);
|
|
222
|
+
]);
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
deleteVersion,
|
|
20
20
|
importArchive,
|
|
21
21
|
exportArchive,
|
|
22
|
+
exportRC,
|
|
22
23
|
importComponent,
|
|
23
24
|
initProject,
|
|
24
25
|
listComponents,
|
|
@@ -84,6 +85,7 @@ const TASKS = {
|
|
|
84
85
|
DELETE_VERSION: 'deleteVersion',
|
|
85
86
|
IMPORT_ARCHIVE: 'importArchive',
|
|
86
87
|
EXPORT_ARCHIVE: 'exportArchive',
|
|
88
|
+
EXPORT_RC: 'exportRC',
|
|
87
89
|
IMPORT_COMP: 'importComponent',
|
|
88
90
|
AUTHENTICATE: 'authenticate',
|
|
89
91
|
UPGRADE: 'upgrade',
|
|
@@ -234,6 +236,10 @@ export default async (args = []) => {
|
|
|
234
236
|
exportArchive(options);
|
|
235
237
|
break;
|
|
236
238
|
}
|
|
239
|
+
case TASKS.EXPORT_RC: {
|
|
240
|
+
exportRC(options);
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
237
243
|
case TASKS.IMPORT_COMP: {
|
|
238
244
|
importComponent(options);
|
|
239
245
|
break;
|
|
@@ -287,4 +293,4 @@ export default async (args = []) => {
|
|
|
287
293
|
break;
|
|
288
294
|
}
|
|
289
295
|
}
|
|
290
|
-
}
|
|
296
|
+
}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
getComponentDirectoryPath,
|
|
14
14
|
getComponents,
|
|
15
15
|
getPegaServerConfig,
|
|
16
|
+
getServerType,
|
|
16
17
|
sanitize,
|
|
17
18
|
validateSemver,
|
|
18
19
|
showVersion,
|
|
@@ -37,7 +38,6 @@ const copyComponentTemplate = async options => {
|
|
|
37
38
|
});
|
|
38
39
|
};
|
|
39
40
|
|
|
40
|
-
|
|
41
41
|
const compileMustacheTemplates = async (
|
|
42
42
|
componentDirectory,
|
|
43
43
|
{
|
|
@@ -306,6 +306,7 @@ addDebugLog("create", "", "+");
|
|
|
306
306
|
);
|
|
307
307
|
} else {
|
|
308
308
|
const componentDefaults = getConfigDefaults();
|
|
309
|
+
const serverType = getServerType();
|
|
309
310
|
const maxChars = isLibraryBased ? getMaxComponentNameCount() : getStandaloneMaxComponentNameCount();
|
|
310
311
|
const questions = [
|
|
311
312
|
{
|
|
@@ -354,7 +355,14 @@ addDebugLog("create", "", "+");
|
|
|
354
355
|
},
|
|
355
356
|
{
|
|
356
357
|
name: 'componentName',
|
|
357
|
-
message:
|
|
358
|
+
message: value => {
|
|
359
|
+
if (serverType === "launchpad") {
|
|
360
|
+
return `Enter component name (required)`;
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
return `Enter component name (required) (${maxChars} max chars)`;
|
|
364
|
+
}
|
|
365
|
+
},
|
|
358
366
|
validate: value => {
|
|
359
367
|
/* value should not be empty
|
|
360
368
|
It should not have spaces
|
|
@@ -362,7 +370,7 @@ addDebugLog("create", "", "+");
|
|
|
362
370
|
Only case-insensitive alphanumeric values are allowed
|
|
363
371
|
*/
|
|
364
372
|
if (value && !/^\d/.test(value) && value === sanitize(value)) {
|
|
365
|
-
if (value.length > maxChars) {
|
|
373
|
+
if (value.length > maxChars && serverType != "launchpad") {
|
|
366
374
|
return `${value.length - maxChars} too many characters.`
|
|
367
375
|
}
|
|
368
376
|
return true;
|
|
@@ -14,6 +14,7 @@ import { checkPathAccess, showVersion ,
|
|
|
14
14
|
compileMustacheTemplate,
|
|
15
15
|
getComponentDirectoryPath,
|
|
16
16
|
getPegaServerConfig,
|
|
17
|
+
getServerType,
|
|
17
18
|
getComponents,
|
|
18
19
|
sanitize,
|
|
19
20
|
validateSemver,
|
|
@@ -405,17 +406,25 @@ addDebugLog("createAll", "", "+");
|
|
|
405
406
|
);
|
|
406
407
|
} else {
|
|
407
408
|
const maxPrefixCount = isLibraryBased ? getMaxPrefixCount() : getStandaloneMaxPrefixCount();
|
|
409
|
+
const serverType = getServerType();
|
|
408
410
|
const questions = [
|
|
409
411
|
{
|
|
410
412
|
name: 'prefix',
|
|
411
|
-
message:
|
|
413
|
+
message: value => {
|
|
414
|
+
if (serverType === "launchpad") {
|
|
415
|
+
return `Enter prefix label`;
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
return `Enter prefix label (${maxPrefixCount} max chars)`;
|
|
419
|
+
}
|
|
420
|
+
},
|
|
412
421
|
validate: value => {
|
|
413
422
|
/* value should not be empty
|
|
414
423
|
It should not start with a number
|
|
415
424
|
Only case-insensitive alphanumeric values are allowed
|
|
416
425
|
*/
|
|
417
426
|
if (value && !/^\d/.test(value) ) {
|
|
418
|
-
if (value.length > maxPrefixCount) {
|
|
427
|
+
if (value.length > maxPrefixCount && serverType != "launchpad") {
|
|
419
428
|
return `${value.length - maxPrefixCount} too many characters.`
|
|
420
429
|
}
|
|
421
430
|
return true;
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import fetch from 'node-fetch';
|
|
5
|
+
import archiver from 'archiver';
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import {
|
|
8
|
+
addDebugLog,
|
|
9
|
+
getConfigDefaults,
|
|
10
|
+
getLibraryArchiveDirectories,
|
|
11
|
+
getLibraryArchivesVersions,
|
|
12
|
+
setConfigExportRelativePath,
|
|
13
|
+
getComponentDirectoryPath,
|
|
14
|
+
getPegaServerConfig,
|
|
15
|
+
forceDefaultsUpdate } from '../../util.js';
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
export const SOURCE_OF_COMPONENT_TYPES = {
|
|
20
|
+
SERVER: 'Server',
|
|
21
|
+
LOCAL: 'Local'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export const getFilePathQuestions = async () => {
|
|
26
|
+
addDebugLog("getFilePathQuestions", "", "");
|
|
27
|
+
|
|
28
|
+
console.log("\nFile path examples:");
|
|
29
|
+
if (path.sep === "/") {
|
|
30
|
+
console.log("\tMac OS/Unix:\t/Users/name/...");
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.log("\tWindows:\tC:\\Users\\name\\...\n");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const configDef = getConfigDefaults();
|
|
37
|
+
|
|
38
|
+
const currentDirectory = process.cwd();
|
|
39
|
+
const arPathParts = currentDirectory.split(path.sep);
|
|
40
|
+
let defaultPath = join(arPathParts[0], arPathParts[1], arPathParts[2], configDef.exportRelativePath);
|
|
41
|
+
let startDirectory = join(arPathParts[0], arPathParts[1], arPathParts[2]);
|
|
42
|
+
|
|
43
|
+
if (path.sep === "/") {
|
|
44
|
+
defaultPath = "/".concat(defaultPath);
|
|
45
|
+
startDirectory = "/".concat(startDirectory).concat("/");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return [
|
|
49
|
+
{
|
|
50
|
+
name: 'filePath',
|
|
51
|
+
type: 'fuzzypath',
|
|
52
|
+
message: 'Enter full file path of directory to export zip file:',
|
|
53
|
+
default: defaultPath,
|
|
54
|
+
excludePath: nodePath => nodePath.startsWith('node_modules'),
|
|
55
|
+
// excludePath :: (String) -> Bool
|
|
56
|
+
// excludePath to exclude some paths from the file-system scan
|
|
57
|
+
excludeFilter: nodePath => nodePath.indexOf('/.') >= 0,
|
|
58
|
+
// excludeFilter :: (String) -> Bool
|
|
59
|
+
// excludeFilter to exclude some paths from the final list, e.g. '.'
|
|
60
|
+
itemType: 'directory',
|
|
61
|
+
// itemType :: 'any' | 'directory' | 'file'
|
|
62
|
+
// specify the type of nodes to display
|
|
63
|
+
// default value: 'any'
|
|
64
|
+
// example: itemType: 'file' - hides directories from the item list
|
|
65
|
+
rootPath: startDirectory,
|
|
66
|
+
// rootPath :: String
|
|
67
|
+
// Root search directory
|
|
68
|
+
suggestOnly: true,
|
|
69
|
+
// suggestOnly :: Bool
|
|
70
|
+
// Restrict prompt answer to available choices or use them as suggestions
|
|
71
|
+
depthLimit: 2,
|
|
72
|
+
// depthLimit :: integer >= 0
|
|
73
|
+
// Limit the depth of sub-folders to scan
|
|
74
|
+
// Defaults to infinite depth if undefined
|
|
75
|
+
}
|
|
76
|
+
];
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const getFileNameQuestions = async (zipFileList) => {
|
|
80
|
+
addDebugLog("getFileNameQuestions", "", "");
|
|
81
|
+
|
|
82
|
+
return [
|
|
83
|
+
{
|
|
84
|
+
name: 'fileName',
|
|
85
|
+
type: 'rawlist',
|
|
86
|
+
message: `Select zip file`,
|
|
87
|
+
choices: zipFileList
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const getLibraryQuestion = async () => {
|
|
93
|
+
addDebugLog("getLibraryQuestion", "", "");
|
|
94
|
+
const componentDefaults = getConfigDefaults();
|
|
95
|
+
const orgLib = getConfigDefaults();
|
|
96
|
+
const currentOrgLib = `${orgLib.organization}_${orgLib.library}`;
|
|
97
|
+
|
|
98
|
+
const archVersionList = await getLibraryArchiveDirectories("");
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
return [
|
|
102
|
+
{
|
|
103
|
+
name: 'orgLibName',
|
|
104
|
+
type: 'rawlist',
|
|
105
|
+
message: `Select a library (current library is ${chalk.bold.green(`${currentOrgLib}`)}) `,
|
|
106
|
+
choices: archVersionList
|
|
107
|
+
}
|
|
108
|
+
];
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const getLibraryVersionQuestion = async (newOrgLib) => {
|
|
112
|
+
addDebugLog("getLibraryVersionQuestion", "", "");
|
|
113
|
+
|
|
114
|
+
const archVersionList = await getLibraryArchivesVersions(newOrgLib, "0.0.0");
|
|
115
|
+
|
|
116
|
+
return [
|
|
117
|
+
{
|
|
118
|
+
name: 'selectedVersion',
|
|
119
|
+
type: 'rawlist',
|
|
120
|
+
message: `Select a version `,
|
|
121
|
+
choices: archVersionList
|
|
122
|
+
}
|
|
123
|
+
];
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const getServerOrDirectoryQuestion = async () => {
|
|
127
|
+
addDebugLog("getLibraryVersionQuestion", "", "");
|
|
128
|
+
|
|
129
|
+
return [
|
|
130
|
+
{
|
|
131
|
+
name: 'exportTo',
|
|
132
|
+
type: 'rawlist',
|
|
133
|
+
message: `Export to`,
|
|
134
|
+
choices: [{name: 'Local directory', value: 'Directory'}, {name: 'Server', value: 'Server'}],
|
|
135
|
+
default: 'Directory'
|
|
136
|
+
}
|
|
137
|
+
];
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const getFullArchiveQuestions = async () => {
|
|
141
|
+
|
|
142
|
+
return [
|
|
143
|
+
{
|
|
144
|
+
name: 'fullArchive',
|
|
145
|
+
type: 'rawlist',
|
|
146
|
+
message: 'Type of export',
|
|
147
|
+
choices: [{name: 'Full Archive (code)', value: 'Full'}, {name: 'CL Binary (runtime only)', value: 'Binary'}],
|
|
148
|
+
default: 'Full'
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export const getComponentInfoQuestions = async (rPackageJSON, library) => {
|
|
155
|
+
|
|
156
|
+
return [
|
|
157
|
+
{
|
|
158
|
+
name: 'author',
|
|
159
|
+
message: 'Author of this component',
|
|
160
|
+
default: rPackageJSON.author
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'isLocalized',
|
|
164
|
+
type: 'confirm',
|
|
165
|
+
message: 'Is this component fully localized',
|
|
166
|
+
default: false
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: 'isAccessible',
|
|
170
|
+
type: 'confirm',
|
|
171
|
+
message: 'Is this component accessible',
|
|
172
|
+
default: false
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: 'isSecure',
|
|
176
|
+
type: 'confirm',
|
|
177
|
+
message: 'Is this component and dependent modules secure',
|
|
178
|
+
default: false
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'license',
|
|
182
|
+
message: 'License of this component (MIT, Apache, GPL, etc.)',
|
|
183
|
+
default: rPackageJSON.license
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: 'organization',
|
|
187
|
+
message: 'Organization name',
|
|
188
|
+
default: rPackageJSON.organization
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: 'library',
|
|
192
|
+
message: 'Library name',
|
|
193
|
+
default: library
|
|
194
|
+
}
|
|
195
|
+
];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export const zipComponent = async componentKey => {
|
|
199
|
+
addDebugLog("zipComponent", `componentKey: ${componentKey}`, "");
|
|
200
|
+
const srcDirectory = await getComponentDirectoryPath(componentKey);
|
|
201
|
+
const buildDirectory = await path.join(path.resolve(), 'dist/components', componentKey);
|
|
202
|
+
const configJson = `${srcDirectory}/config.json`;
|
|
203
|
+
const localizationJson = `${srcDirectory}/localizations.json`;
|
|
204
|
+
|
|
205
|
+
const archive = archiver('zip', { zlib: { level: 9 } });
|
|
206
|
+
const zipChunks = [];
|
|
207
|
+
archive.on('data', chunk => zipChunks.push(chunk));
|
|
208
|
+
|
|
209
|
+
// Add src directory
|
|
210
|
+
archive.directory(srcDirectory, 'src');
|
|
211
|
+
|
|
212
|
+
// Add config.json file
|
|
213
|
+
if (fs.existsSync(configJson)) {
|
|
214
|
+
archive.file(configJson, { name: path.basename(configJson) });
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let lJson = "";
|
|
218
|
+
|
|
219
|
+
// Add localizations.json file if it exists
|
|
220
|
+
if (fs.existsSync(localizationJson)) {
|
|
221
|
+
archive.file(localizationJson, { name: path.basename(localizationJson) });
|
|
222
|
+
lJson = JSON.parse(Buffer.from(fs.readFileSync((localizationJson))).toString());
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Add build directory
|
|
226
|
+
archive.directory(buildDirectory, false);
|
|
227
|
+
|
|
228
|
+
await archive.finalize();
|
|
229
|
+
|
|
230
|
+
const zipBuffer = Buffer.concat(zipChunks);
|
|
231
|
+
console.log(chalk.green(`component zipped with size: ${Math.ceil(zipBuffer.length / 1024)} KB`));
|
|
232
|
+
const zipContent = zipBuffer.toString('base64');
|
|
233
|
+
|
|
234
|
+
//let configContent = Buffer.from(fs.readFileSync(configJson)).toString();
|
|
235
|
+
const configContent = JSON.parse(Buffer.from(fs.readFileSync(configJson)).toString());
|
|
236
|
+
// configContent = configContent.replaceAll("\n", "");
|
|
237
|
+
|
|
238
|
+
let output = { configContent };
|
|
239
|
+
if (lJson != "") {
|
|
240
|
+
output = { ...output, localizationJson: lJson};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (fs.existsSync('dist')) {
|
|
244
|
+
fs.rm('dist', { recursive: true }, err => {
|
|
245
|
+
if (err) {
|
|
246
|
+
throw err;
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
return { zipContent, ...output};
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
export const zipRC = async (content, archiveDirectory, archiveFileName) => {
|
|
256
|
+
addDebugLog("zipRC", ``, "");
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
// const configContent = Buffer.from(fs.readFileSync(configJson)).toString();
|
|
261
|
+
// const mainDirectory = process.cwd();
|
|
262
|
+
// const archiveDirectory = join (mainDirectory, ARCHIVES_PATH, `${componentKey}`, `${version}`);
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
if (!fs.existsSync(archiveDirectory)) {
|
|
266
|
+
fs.mkdirSync(archiveDirectory, { recursive: true });
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const archiveFile = join(archiveDirectory, archiveFileName);
|
|
270
|
+
|
|
271
|
+
const output = fs.createWriteStream(archiveFile);
|
|
272
|
+
const archive = archiver('zip', {
|
|
273
|
+
zlib: { level: 9 } // Sets the compression level.
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
const zipChunks = [];
|
|
277
|
+
archive.on('data', chunk => zipChunks.push(chunk));
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
archive.append( JSON.stringify(content), { name: 'componentData.json' });
|
|
281
|
+
|
|
282
|
+
// pipe archive data to the file
|
|
283
|
+
archive.pipe(output);
|
|
284
|
+
|
|
285
|
+
output.on('end', function() {
|
|
286
|
+
console.log('Data has been drained');
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
// good practice to catch warnings (ie stat failures and other non-blocking errors)
|
|
291
|
+
archive.on('warning', function(err) {
|
|
292
|
+
if (err.code === 'ENOENT') {
|
|
293
|
+
// log warning
|
|
294
|
+
} else {
|
|
295
|
+
// throw error
|
|
296
|
+
throw err;
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// good practice to catch this error explicitly
|
|
301
|
+
archive.on('error', function(err) {
|
|
302
|
+
throw err;
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
await archive.finalize();
|
|
306
|
+
|
|
307
|
+
return output;
|
|
308
|
+
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
export const updateSavedExportFilePath = async(filePath) => {
|
|
314
|
+
const currentDirectory = process.cwd();
|
|
315
|
+
const arPathParts = currentDirectory.split(path.sep);
|
|
316
|
+
const configDef = getConfigDefaults();
|
|
317
|
+
|
|
318
|
+
let defaultPath = join(path.sep, arPathParts[0], arPathParts[1], arPathParts[2]);
|
|
319
|
+
|
|
320
|
+
if (path.sep != "/") {
|
|
321
|
+
// windows
|
|
322
|
+
if (defaultPath.indexOf(path.sep) === 0) {
|
|
323
|
+
// if start with \\, then remove
|
|
324
|
+
defaultPath = defaultPath.substring(1);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (filePath.indexOf(defaultPath) === 0) {
|
|
328
|
+
let relativePath = "";
|
|
329
|
+
if (filePath !== defaultPath) {
|
|
330
|
+
// same starting path, so we can save the relative
|
|
331
|
+
relativePath = filePath.replace(defaultPath.concat(path.sep), "");
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
await setConfigExportRelativePath(relativePath);
|
|
335
|
+
await forceDefaultsUpdate();
|
|
336
|
+
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
// mac
|
|
341
|
+
if (filePath.indexOf(defaultPath) === 0) {
|
|
342
|
+
|
|
343
|
+
let relativePath = "";
|
|
344
|
+
if (filePath !== defaultPath) {
|
|
345
|
+
// same starting path, so we can save the relative
|
|
346
|
+
relativePath = filePath.replace(defaultPath.concat("/"), "");
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
await setConfigExportRelativePath(relativePath);
|
|
351
|
+
await forceDefaultsUpdate();
|
|
352
|
+
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { Listr } from 'listr2';
|
|
7
|
+
|
|
8
|
+
import validate from '../validator/index.js';
|
|
9
|
+
import bundleComponent from '../bundle/index.js';
|
|
10
|
+
import { lintComponent } from '../linter/index.js';
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
checkPathAccess,
|
|
14
|
+
showVersion,
|
|
15
|
+
addDebugLog,
|
|
16
|
+
getComponents,
|
|
17
|
+
getConfigDefaults,
|
|
18
|
+
getPegaServerConfig,
|
|
19
|
+
getLibraryBased,
|
|
20
|
+
getComponentDirectoryPath,
|
|
21
|
+
getServerType
|
|
22
|
+
} from '../../util.js';
|
|
23
|
+
import { TASKS_CONFIG_JSON_FILENAME, PACKAGE_JSON_FILENAME } from '../../constants.js';
|
|
24
|
+
import { getFilePathQuestions, updateSavedExportFilePath, zipComponent, zipRC, getComponentInfoQuestions } from './helper.js';
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
import inquirerFuzzyPath from '@pega/inquirer-fuzzy-path';
|
|
28
|
+
|
|
29
|
+
const currentDirectory = process.cwd();
|
|
30
|
+
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
|
|
31
|
+
|
|
32
|
+
export default async options => {
|
|
33
|
+
await showVersion();
|
|
34
|
+
|
|
35
|
+
await checkPathAccess(pegaConfigJsonPath);
|
|
36
|
+
|
|
37
|
+
const isLibraryBasedCL = getLibraryBased();
|
|
38
|
+
if (isLibraryBasedCL) {
|
|
39
|
+
console.log(`Command only supported for ${chalk.bold.green('non library mode')} components.`)
|
|
40
|
+
process.exit();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const serverType = getServerType();
|
|
44
|
+
if (serverType != "launchpad") {
|
|
45
|
+
console.log(`Command only supported for ${chalk.green('Launchpad')}.`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
addDebugLog("export RC", "", "+");
|
|
51
|
+
|
|
52
|
+
let exportTo = "";
|
|
53
|
+
|
|
54
|
+
if (options.params.length >= 8) {
|
|
55
|
+
|
|
56
|
+
// params pick full, what library/name and path
|
|
57
|
+
// vs no params then we will select the current library
|
|
58
|
+
// let fullArchive = options.params[3];
|
|
59
|
+
// const libraryName = options.params[4];
|
|
60
|
+
// const libraryVersion = options.params[5];
|
|
61
|
+
// const filePath = options.params[6];
|
|
62
|
+
// exportTo = "Directory";
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
// const currentOrArchive = options.params[7];
|
|
66
|
+
|
|
67
|
+
// await exportArch(filePath, libraryName, libraryVersion, fullArchive, currentOrArchive );
|
|
68
|
+
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
let orgLibName = "";
|
|
72
|
+
let selectedVersion = "";
|
|
73
|
+
let fullArchive = "";
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
// if (options.params.length >= 5) {
|
|
77
|
+
// fullArchive = options.params[3];
|
|
78
|
+
// orgLibName = options.params[4];
|
|
79
|
+
// if (options.params.length >= 6) {
|
|
80
|
+
// selectedVersion = options.params[5];
|
|
81
|
+
// }
|
|
82
|
+
// }
|
|
83
|
+
|
|
84
|
+
// disable question to build "CL"
|
|
85
|
+
// if (fullArchive === "" ) {
|
|
86
|
+
// const fullArchiveQuestions = await getFullArchiveQuestions();
|
|
87
|
+
// const fullArchiveAnswers = await inquirer.prompt(fullArchiveQuestions);
|
|
88
|
+
// ({ fullArchive } = fullArchiveAnswers);
|
|
89
|
+
// }
|
|
90
|
+
|
|
91
|
+
// force full archive, binary deprecated
|
|
92
|
+
fullArchive = "Full";
|
|
93
|
+
|
|
94
|
+
let filePathQuestions;
|
|
95
|
+
let filePathAnswers;
|
|
96
|
+
let filePath;
|
|
97
|
+
let content;
|
|
98
|
+
|
|
99
|
+
const localComponents = await getComponents();
|
|
100
|
+
const defaultPegaConfig = await getPegaServerConfig();
|
|
101
|
+
const configDef = getConfigDefaults();
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
if (localComponents.length > 0) {
|
|
105
|
+
|
|
106
|
+
const compAnswers = await inquirer.prompt([
|
|
107
|
+
{
|
|
108
|
+
name: 'componentKey',
|
|
109
|
+
type: 'rawlist',
|
|
110
|
+
message: 'Select component to export as a runtime component',
|
|
111
|
+
choices: localComponents
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: 'devBuild',
|
|
115
|
+
type: 'confirm',
|
|
116
|
+
message: 'Generate development build ?',
|
|
117
|
+
default: defaultPegaConfig.devBuild
|
|
118
|
+
}
|
|
119
|
+
]);
|
|
120
|
+
|
|
121
|
+
content = {
|
|
122
|
+
...compAnswers
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
inquirer.registerPrompt('fuzzypath', inquirerFuzzyPath);
|
|
127
|
+
const filePathQuestions = await getFilePathQuestions();
|
|
128
|
+
const filePathAnswers = await inquirer.prompt(filePathQuestions);
|
|
129
|
+
const exportPath = filePathAnswers.filePath;
|
|
130
|
+
const componentKey = compAnswers.componentKey;
|
|
131
|
+
const devBuild = compAnswers.devBuild;
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
if (!fs.existsSync(exportPath)) {
|
|
136
|
+
console.log(`\Path: ${chalk.yellow(`${exportPath}`)} doesn't exist.`);
|
|
137
|
+
const newPathAnswer = await inquirer.prompt([
|
|
138
|
+
{
|
|
139
|
+
name: 'createNewPath',
|
|
140
|
+
type: 'confirm',
|
|
141
|
+
message: 'Create path',
|
|
142
|
+
default: true
|
|
143
|
+
},
|
|
144
|
+
]);
|
|
145
|
+
const createNewPath = newPathAnswer.createNewPath;
|
|
146
|
+
if (createNewPath) {
|
|
147
|
+
fs.mkdirSync(exportPath, { recursive: true });
|
|
148
|
+
|
|
149
|
+
await updateSavedExportFilePath(exportPath);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
console.log(chalk.green("Store not exported."));
|
|
153
|
+
process.exit();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const archiveFileName = `${componentKey}_${configDef.version}.RC.zip`;
|
|
158
|
+
|
|
159
|
+
if (fs.existsSync(join(exportPath, archiveFileName))) {
|
|
160
|
+
console.log(`\nFile: ${chalk.yellow(`${archiveFileName}`)} already exists in ${chalk.yellow(`${exportPath}`)}.`);
|
|
161
|
+
const overwriteQuestion = await inquirer.prompt([
|
|
162
|
+
{
|
|
163
|
+
name: 'overWriteFile',
|
|
164
|
+
type: 'confirm',
|
|
165
|
+
message: 'Overwrite',
|
|
166
|
+
default: true
|
|
167
|
+
},
|
|
168
|
+
]);
|
|
169
|
+
|
|
170
|
+
if (!overwriteQuestion.overWriteFile) {
|
|
171
|
+
console.log(chalk.green("Archive not created."));
|
|
172
|
+
process.exit();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
console.log(chalk.yellow(`\n>> You are about to create a zip file containing an independent component `));
|
|
177
|
+
console.log(chalk.yellow(`>> that others can import directly into Launchpad.`));
|
|
178
|
+
console.log(chalk.yellow(`>> You will be asked a series of questions for the benefit of others`));
|
|
179
|
+
console.log(chalk.yellow(`>> who might choose to use your component.`));
|
|
180
|
+
console.log(chalk.yellow(`\n>> These answers will be recorded in a json file within the zip file.`));
|
|
181
|
+
console.log(chalk.yellow(`>> These questions will NOT be used as a gate to prevent the creation of this component.\n`));
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
const currentDirectory = process.cwd();
|
|
185
|
+
const packagePath = join (currentDirectory, PACKAGE_JSON_FILENAME);
|
|
186
|
+
let retrievedPackageData;
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
retrievedPackageData = fs.readFileSync(packagePath);
|
|
190
|
+
}
|
|
191
|
+
catch (ex) {
|
|
192
|
+
console.log(chalk.red(`\nUnable to retrieve package.json.`))
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const rPackage = JSON.parse(retrievedPackageData);
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
const componentInfoQuestions = await getComponentInfoQuestions(rPackage, configDef.library);
|
|
200
|
+
let componentInfo = await inquirer.prompt(componentInfoQuestions);
|
|
201
|
+
|
|
202
|
+
const currentDate = new Date(Date.now());
|
|
203
|
+
const dateStamp = currentDate.toString();
|
|
204
|
+
const timeStamp = currentDate.toJSON();
|
|
205
|
+
|
|
206
|
+
componentInfo = { ...componentInfo, dependencies: rPackage.dependencies, buildDate: dateStamp, timeStamp };
|
|
207
|
+
|
|
208
|
+
console.log("\nBuilding RC...");
|
|
209
|
+
|
|
210
|
+
const sDevBuild = devBuild ? '(dev build)' : '';
|
|
211
|
+
const tasks = new Listr(
|
|
212
|
+
[
|
|
213
|
+
{
|
|
214
|
+
title: 'Validate config schema',
|
|
215
|
+
task: async () => {
|
|
216
|
+
await validate(componentKey);
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
title: 'Lint component',
|
|
221
|
+
task: async () => {
|
|
222
|
+
const targetDirectory = await getComponentDirectoryPath(componentKey);
|
|
223
|
+
// console.log(`in buildComponent Lint component task: componentKey: ${componentKey} targetDirectory: ${targetDirectory}`);
|
|
224
|
+
await lintComponent(targetDirectory);
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
title: `Bundle Component ${sDevBuild}`,
|
|
229
|
+
task: async () => bundleComponent(componentKey, defaultPegaConfig.sourceMap, devBuild),
|
|
230
|
+
skip: () => (options.skipBundle ? 'Skipped bundling component' : undefined)
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
title: 'Create internal zip of component',
|
|
234
|
+
task: async () => {
|
|
235
|
+
const output = await zipComponent(componentKey);
|
|
236
|
+
content = { ...content, ...output, componentInfo: componentInfo };
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
title: 'Create zip file',
|
|
241
|
+
task: async () => {
|
|
242
|
+
const output = await zipRC(content, exportPath, archiveFileName);
|
|
243
|
+
content = { ...content, ...output };
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
],
|
|
247
|
+
{
|
|
248
|
+
exitOnError: true
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
await tasks.run().catch(err => {
|
|
253
|
+
console.log(chalk.bold.red(err.toString()));
|
|
254
|
+
process.exit(1);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
console.log(`\nRuntime component ${chalk.green(`${archiveFileName}`)} has been created in ${chalk.green(`${exportPath}`)}.\n`);
|
|
258
|
+
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
console.log(chalk.bold.red(`\nNo components to export.\n`));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
addDebugLog("export RC", "END", "-");
|
|
267
|
+
|
|
268
|
+
};
|
package/src/tasks/index.js
CHANGED
|
@@ -28,6 +28,7 @@ export { default as setPermanent } from './set-perm/index.js';
|
|
|
28
28
|
export { default as storeComponents } from './store/index.js';
|
|
29
29
|
export { default as importArchive } from './import-archive/index.js';
|
|
30
30
|
export { default as exportArchive } from './export-archive/index.js';
|
|
31
|
+
export { default as exportRC } from './export-rc/index.js';
|
|
31
32
|
export { default as importComponent } from './import-comp/index.js';
|
|
32
33
|
export { default as updateComponent } from './update/index.js';
|
|
33
34
|
export { default as validate } from './validator/index.js';
|
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
import { globalIgnores } from 'eslint/config';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import
|
|
5
|
-
import { FlatCompat } from '@eslint/eslintrc';
|
|
3
|
+
import eslint from '@eslint/js';
|
|
6
4
|
import tseslint from 'typescript-eslint';
|
|
7
5
|
import sonarjs from 'eslint-plugin-sonarjs';
|
|
8
6
|
import importPlugin from 'eslint-plugin-import';
|
|
9
7
|
import react from 'eslint-plugin-react';
|
|
10
8
|
import reactHooks from 'eslint-plugin-react-hooks';
|
|
9
|
+
// eslint.config.js
|
|
10
|
+
import { defineConfig } from 'eslint/config';
|
|
11
11
|
|
|
12
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
-
const __dirname = path.dirname(__filename);
|
|
14
|
-
const compat = new FlatCompat({
|
|
15
|
-
baseDirectory: __dirname,
|
|
16
|
-
recommendedConfig: js.configs.recommended,
|
|
17
|
-
sonarjs: sonarjs.configs.recommended,
|
|
18
|
-
importPlugin: importPlugin.configs.recommended,
|
|
19
|
-
react: react.configs.recommended,
|
|
20
|
-
reactHooks: reactHooks.configs.recommended,
|
|
21
|
-
allConfig: js.configs.all
|
|
22
|
-
});
|
|
23
13
|
|
|
24
|
-
export default
|
|
25
|
-
|
|
14
|
+
export default defineConfig([
|
|
15
|
+
eslint.configs.recommended,
|
|
16
|
+
...tseslint.configs.recommended,
|
|
26
17
|
globalIgnores([
|
|
27
18
|
'**/node_modules',
|
|
28
19
|
'packages/*/lib',
|
|
@@ -228,4 +219,4 @@ export default tseslint.config(
|
|
|
228
219
|
'import/prefer-default-export': ['off']
|
|
229
220
|
}
|
|
230
221
|
}
|
|
231
|
-
);
|
|
222
|
+
]);
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"delete": "custom-dx-components delete",
|
|
26
26
|
"deleteAll": "custom-dx-components deleteAll",
|
|
27
27
|
"importComponent": "custom-dx-components importComponent",
|
|
28
|
+
"exportRC" : "custom-dx-components exportRC",
|
|
28
29
|
"help": "custom-dx-components showHelp",
|
|
29
30
|
"publish": "custom-dx-components publish",
|
|
30
31
|
"_***Component_mode_only***": "Component only commands",
|
|
@@ -107,7 +108,7 @@
|
|
|
107
108
|
"@babel/preset-react": "^7.27.1",
|
|
108
109
|
"@babel/preset-typescript": "^7.27.1",
|
|
109
110
|
"@pega/configs": "^0.16.3",
|
|
110
|
-
"@pega/custom-dx-components": "~25.1.
|
|
111
|
+
"@pega/custom-dx-components": "~25.1.14",
|
|
111
112
|
"@pega/pcore-pconnect-typedefs": "^4.1.0",
|
|
112
113
|
"@storybook/addon-actions": "^8.6.14",
|
|
113
114
|
"@storybook/addon-essentials": "^8.6.14",
|
|
@@ -130,7 +131,8 @@
|
|
|
130
131
|
"@types/react-color": "^3.0.13",
|
|
131
132
|
"@types/react-dom": "^18.3.7",
|
|
132
133
|
"@types/styled-components": "^5.1.34",
|
|
133
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
134
|
+
"@typescript-eslint/eslint-plugin": "^8.44.1",
|
|
135
|
+
"@typescript-eslint/parser": "^8.44.1",
|
|
134
136
|
"core-js": "^3.42.0",
|
|
135
137
|
"eslint": "^9.27.0",
|
|
136
138
|
"eslint-plugin-import": "^2.31.0",
|
|
@@ -155,7 +157,7 @@
|
|
|
155
157
|
"stylelint": "^16.19.1",
|
|
156
158
|
"ts-jest": "^29.3.2",
|
|
157
159
|
"typescript": "~5.5.4",
|
|
158
|
-
"typescript-eslint": "^8.
|
|
160
|
+
"typescript-eslint": "^8.44.1",
|
|
159
161
|
"vite": "^6.3.5"
|
|
160
162
|
}
|
|
161
163
|
}
|
package/src/util.js
CHANGED
|
@@ -1327,15 +1327,17 @@ export const showVersion = async () => {
|
|
|
1327
1327
|
// get package version, so can display at start
|
|
1328
1328
|
// const require = createRequire(import.meta.url);
|
|
1329
1329
|
const require = createRequire(currentPath.default);
|
|
1330
|
-
const
|
|
1330
|
+
const serverType = getServerType();
|
|
1331
|
+
const sLibMode = getLibraryBased() ? "(library mode)" : serverType === "launchpad" ? "(LaunchPad)" : "";
|
|
1331
1332
|
|
|
1332
1333
|
const pData = require('@pega/custom-dx-components/package.json');
|
|
1333
1334
|
const serverConfig = await getPegaServerConfig();
|
|
1334
1335
|
|
|
1336
|
+
|
|
1335
1337
|
console.log(chalk.green(`DX Component Builder${sLibMode} v${pData.version}`));
|
|
1336
1338
|
showDebug = getShowDebug();
|
|
1337
1339
|
|
|
1338
|
-
if (getLibraryBased() &&
|
|
1340
|
+
if (getLibraryBased() && serverType === "launchpad") {
|
|
1339
1341
|
console.log(`\nLaunchpad commands only supported for ${chalk.bold.green('non library mode')} components.\n`);
|
|
1340
1342
|
process.exit();
|
|
1341
1343
|
}
|
|
@@ -2848,6 +2850,11 @@ export const getStandaloneMaxPrefixCount = () => {
|
|
|
2848
2850
|
}
|
|
2849
2851
|
|
|
2850
2852
|
export const isComponentValidLength = (componentKey) => {
|
|
2853
|
+
const serverType = getServerType();
|
|
2854
|
+
if (serverType === "launchpad") {
|
|
2855
|
+
return true;
|
|
2856
|
+
}
|
|
2857
|
+
|
|
2851
2858
|
const configDef = getConfigDefaults();
|
|
2852
2859
|
const componentName = componentKey.replace(configDef.currentOrgLib + "_", "");
|
|
2853
2860
|
if (componentName.length <= getMaxComponentNameCount()) {
|