@sap-ux/project-input-validator 0.1.2 → 0.2.0
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/dist/{validators.d.ts → deploy/validators.d.ts} +1 -15
- package/dist/{validators.js → deploy/validators.js} +14 -47
- package/dist/general/validators.d.ts +15 -0
- package/dist/general/validators.js +38 -0
- package/dist/i18n.d.ts +1 -1
- package/dist/i18n.js +7 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/translations/project-input-validator.i18n.json +49 -0
- package/dist/ui5/validators.d.ts +32 -0
- package/dist/ui5/validators.js +182 -0
- package/package.json +9 -4
- package/dist/translations/common.i18n.json +0 -14
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Validator Fiori app name is
|
|
2
|
+
* Validator Fiori app name is compatble with Fiori project requirements.
|
|
3
3
|
*
|
|
4
4
|
* @param name Fiori app name
|
|
5
5
|
* @param prefix Prefix required by backend system
|
|
@@ -13,13 +13,6 @@ export declare function validateAppName(name: string, prefix?: string): boolean
|
|
|
13
13
|
* @returns true or error message
|
|
14
14
|
*/
|
|
15
15
|
export declare function validateAppDescription(description: string): boolean | string;
|
|
16
|
-
/**
|
|
17
|
-
* Client number is either empty or 3 digit string.
|
|
18
|
-
*
|
|
19
|
-
* @param client ABAP system client number
|
|
20
|
-
* @returns true or error message
|
|
21
|
-
*/
|
|
22
|
-
export declare function validateClient(client: string): boolean | string;
|
|
23
16
|
/**
|
|
24
17
|
* Transport request number is not required for local package.
|
|
25
18
|
*
|
|
@@ -35,11 +28,4 @@ export declare function validateTransportRequestNumber(transportRequest: string,
|
|
|
35
28
|
* @returns true or error message
|
|
36
29
|
*/
|
|
37
30
|
export declare function validatePackage(input: string): boolean | string;
|
|
38
|
-
/**
|
|
39
|
-
* Validate url input is valid url format.
|
|
40
|
-
*
|
|
41
|
-
* @param input Backend ABAP system url
|
|
42
|
-
* @returns true or error message
|
|
43
|
-
*/
|
|
44
|
-
export declare function validateUrl(input: string): boolean | string;
|
|
45
31
|
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const i18n_1 = require("
|
|
3
|
+
exports.validatePackage = exports.validateTransportRequestNumber = exports.validateAppDescription = exports.validateAppName = void 0;
|
|
4
|
+
const i18n_1 = require("../i18n");
|
|
5
5
|
const os_1 = require("os");
|
|
6
6
|
/**
|
|
7
|
-
* Validator Fiori app name is
|
|
7
|
+
* Validator Fiori app name is compatble with Fiori project requirements.
|
|
8
8
|
*
|
|
9
9
|
* @param name Fiori app name
|
|
10
10
|
* @param prefix Prefix required by backend system
|
|
@@ -14,20 +14,20 @@ function validateAppName(name, prefix) {
|
|
|
14
14
|
const errorMessages = [];
|
|
15
15
|
const length = name ? name.trim().length : 0;
|
|
16
16
|
if (!length) {
|
|
17
|
-
return (0, i18n_1.t)('
|
|
17
|
+
return (0, i18n_1.t)('deploy.abapAppNameRequired');
|
|
18
18
|
}
|
|
19
19
|
if (name.split('/').length > 3) {
|
|
20
|
-
errorMessages.push((0, i18n_1.t)('
|
|
20
|
+
errorMessages.push((0, i18n_1.t)('deploy.abapInvalidNamespace'));
|
|
21
21
|
}
|
|
22
22
|
else if (/^\/.*\/\w*$/g.test(name)) {
|
|
23
23
|
const splitNames = name.split('/');
|
|
24
24
|
let accumulatedMsg = '';
|
|
25
25
|
if (splitNames[1].length > 10) {
|
|
26
|
-
const errMsg = (0, i18n_1.t)('
|
|
26
|
+
const errMsg = (0, i18n_1.t)('deploy.abapInvalidNamespaceLength', { length: splitNames[1].length });
|
|
27
27
|
accumulatedMsg += `${errMsg}, `;
|
|
28
28
|
}
|
|
29
29
|
if (splitNames[2].length > 15) {
|
|
30
|
-
const errMsg = (0, i18n_1.t)('
|
|
30
|
+
const errMsg = (0, i18n_1.t)('deploy.abapInvalidAppNameLength', { length: splitNames[2].length });
|
|
31
31
|
accumulatedMsg += `${errMsg}, `;
|
|
32
32
|
}
|
|
33
33
|
if (accumulatedMsg) {
|
|
@@ -36,13 +36,13 @@ function validateAppName(name, prefix) {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
else if (length > 15) {
|
|
39
|
-
errorMessages.push((0, i18n_1.t)('
|
|
39
|
+
errorMessages.push((0, i18n_1.t)('deploy.abapInvalidAppNameLength', { length }));
|
|
40
40
|
}
|
|
41
41
|
if (prefix && !name.toUpperCase().startsWith(prefix.toUpperCase())) {
|
|
42
|
-
errorMessages.push((0, i18n_1.t)('
|
|
42
|
+
errorMessages.push((0, i18n_1.t)('deploy.abapInvalidAppName', { prefix }));
|
|
43
43
|
}
|
|
44
44
|
if (!/^[A-Za-z0-9_/]*$/.test(name)) {
|
|
45
|
-
errorMessages.push((0, i18n_1.t)('
|
|
45
|
+
errorMessages.push((0, i18n_1.t)('deploy.charactersForbiddenInAppName'));
|
|
46
46
|
}
|
|
47
47
|
return processErrorMessages(errorMessages);
|
|
48
48
|
}
|
|
@@ -61,7 +61,7 @@ function processErrorMessages(errorMessages) {
|
|
|
61
61
|
return errorMessages[0];
|
|
62
62
|
}
|
|
63
63
|
else {
|
|
64
|
-
return `${(0, i18n_1.t)('
|
|
64
|
+
return `${(0, i18n_1.t)('deploy.invalidAppNameMultipleReason')}${os_1.EOL}${errorMessages.join(os_1.EOL)}${os_1.EOL}`;
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
@@ -72,30 +72,13 @@ function processErrorMessages(errorMessages) {
|
|
|
72
72
|
*/
|
|
73
73
|
function validateAppDescription(description) {
|
|
74
74
|
if (description.length > 60) {
|
|
75
|
-
return (0, i18n_1.t)('
|
|
75
|
+
return (0, i18n_1.t)('deploy.abapAppDescLength');
|
|
76
76
|
}
|
|
77
77
|
else {
|
|
78
78
|
return true;
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
exports.validateAppDescription = validateAppDescription;
|
|
82
|
-
/**
|
|
83
|
-
* Client number is either empty or 3 digit string.
|
|
84
|
-
*
|
|
85
|
-
* @param client ABAP system client number
|
|
86
|
-
* @returns true or error message
|
|
87
|
-
*/
|
|
88
|
-
function validateClient(client) {
|
|
89
|
-
const formattedInput = (client === null || client === void 0 ? void 0 : client.trim()) || '';
|
|
90
|
-
const isValid = formattedInput === '' || /^\d{3}$/.test(formattedInput);
|
|
91
|
-
if (isValid) {
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
return (0, i18n_1.t)('InvalidClient', { client });
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
exports.validateClient = validateClient;
|
|
99
82
|
/**
|
|
100
83
|
* Transport request number is not required for local package.
|
|
101
84
|
*
|
|
@@ -106,7 +89,7 @@ exports.validateClient = validateClient;
|
|
|
106
89
|
function validateTransportRequestNumber(transportRequest, packageName) {
|
|
107
90
|
const regex = /^[$LlTt]/;
|
|
108
91
|
if (!regex.test(packageName) && !(transportRequest === null || transportRequest === void 0 ? void 0 : transportRequest.trim())) {
|
|
109
|
-
return (0, i18n_1.t)('
|
|
92
|
+
return (0, i18n_1.t)('deploy.abapTransportNumRequired');
|
|
110
93
|
}
|
|
111
94
|
else {
|
|
112
95
|
return true;
|
|
@@ -121,27 +104,11 @@ exports.validateTransportRequestNumber = validateTransportRequestNumber;
|
|
|
121
104
|
*/
|
|
122
105
|
function validatePackage(input) {
|
|
123
106
|
if (!(input === null || input === void 0 ? void 0 : input.trim())) {
|
|
124
|
-
return (0, i18n_1.t)('
|
|
107
|
+
return (0, i18n_1.t)('deploy.abapPackageWarn');
|
|
125
108
|
}
|
|
126
109
|
else {
|
|
127
110
|
return true;
|
|
128
111
|
}
|
|
129
112
|
}
|
|
130
113
|
exports.validatePackage = validatePackage;
|
|
131
|
-
/**
|
|
132
|
-
* Validate url input is valid url format.
|
|
133
|
-
*
|
|
134
|
-
* @param input Backend ABAP system url
|
|
135
|
-
* @returns true or error message
|
|
136
|
-
*/
|
|
137
|
-
function validateUrl(input) {
|
|
138
|
-
try {
|
|
139
|
-
const url = new URL(input);
|
|
140
|
-
return !!url.protocol && !!url.host;
|
|
141
|
-
}
|
|
142
|
-
catch (_a) {
|
|
143
|
-
return (0, i18n_1.t)('InvalidUrl', { input });
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
exports.validateUrl = validateUrl;
|
|
147
114
|
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SAP client number is either empty or 3 digit string.
|
|
3
|
+
*
|
|
4
|
+
* @param client ABAP system client number
|
|
5
|
+
* @returns true or error message
|
|
6
|
+
*/
|
|
7
|
+
export declare function validateClient(client: string): boolean | string;
|
|
8
|
+
/**
|
|
9
|
+
* Validate url input is valid url format.
|
|
10
|
+
*
|
|
11
|
+
* @param input Backend ABAP system url
|
|
12
|
+
* @returns true or error message
|
|
13
|
+
*/
|
|
14
|
+
export declare function validateUrl(input: string): boolean | string;
|
|
15
|
+
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateUrl = exports.validateClient = void 0;
|
|
4
|
+
const i18n_1 = require("../i18n");
|
|
5
|
+
/**
|
|
6
|
+
* SAP client number is either empty or 3 digit string.
|
|
7
|
+
*
|
|
8
|
+
* @param client ABAP system client number
|
|
9
|
+
* @returns true or error message
|
|
10
|
+
*/
|
|
11
|
+
function validateClient(client) {
|
|
12
|
+
const formattedInput = (client === null || client === void 0 ? void 0 : client.trim()) || '';
|
|
13
|
+
const isValid = formattedInput === '' || /^\d{3}$/.test(formattedInput);
|
|
14
|
+
if (isValid) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
return (0, i18n_1.t)('general.invalidClient', { client });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.validateClient = validateClient;
|
|
22
|
+
/**
|
|
23
|
+
* Validate url input is valid url format.
|
|
24
|
+
*
|
|
25
|
+
* @param input Backend ABAP system url
|
|
26
|
+
* @returns true or error message
|
|
27
|
+
*/
|
|
28
|
+
function validateUrl(input) {
|
|
29
|
+
try {
|
|
30
|
+
const url = new URL(input);
|
|
31
|
+
return !!url.protocol && !!url.host;
|
|
32
|
+
}
|
|
33
|
+
catch (_a) {
|
|
34
|
+
return (0, i18n_1.t)('general.invalidUrl', { input });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.validateUrl = validateUrl;
|
|
38
|
+
//# sourceMappingURL=validators.js.map
|
package/dist/i18n.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare const PROJECT_INPUT_VALIDATOR_NS = "project-input-validator";
|
|
|
5
5
|
*/
|
|
6
6
|
export declare function initI18n(): Promise<void>;
|
|
7
7
|
/**
|
|
8
|
-
* Helper function facading the call to i18next.
|
|
8
|
+
* Helper function facading the call to i18next. Unless a namespace option is provided the local namespace will be used.
|
|
9
9
|
*
|
|
10
10
|
* @param key i18n key
|
|
11
11
|
* @param options additional options
|
package/dist/i18n.js
CHANGED
|
@@ -14,7 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.t = exports.initI18n = exports.PROJECT_INPUT_VALIDATOR_NS = void 0;
|
|
16
16
|
const i18next_1 = __importDefault(require("i18next"));
|
|
17
|
-
const
|
|
17
|
+
const project_input_validator_i18n_json_1 = __importDefault(require("./translations/project-input-validator.i18n.json"));
|
|
18
18
|
exports.PROJECT_INPUT_VALIDATOR_NS = 'project-input-validator';
|
|
19
19
|
/**
|
|
20
20
|
* Initialize i18next with the translations for this module.
|
|
@@ -24,7 +24,7 @@ function initI18n() {
|
|
|
24
24
|
yield i18next_1.default.init({
|
|
25
25
|
resources: {
|
|
26
26
|
en: {
|
|
27
|
-
[exports.PROJECT_INPUT_VALIDATOR_NS]:
|
|
27
|
+
[exports.PROJECT_INPUT_VALIDATOR_NS]: project_input_validator_i18n_json_1.default
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
lng: 'en',
|
|
@@ -36,17 +36,20 @@ function initI18n() {
|
|
|
36
36
|
}
|
|
37
37
|
exports.initI18n = initI18n;
|
|
38
38
|
/**
|
|
39
|
-
* Helper function facading the call to i18next.
|
|
39
|
+
* Helper function facading the call to i18next. Unless a namespace option is provided the local namespace will be used.
|
|
40
40
|
*
|
|
41
41
|
* @param key i18n key
|
|
42
42
|
* @param options additional options
|
|
43
43
|
* @returns {string} localized string stored for the given key
|
|
44
44
|
*/
|
|
45
45
|
function t(key, options) {
|
|
46
|
+
if (!(options === null || options === void 0 ? void 0 : options.ns)) {
|
|
47
|
+
options = Object.assign(options !== null && options !== void 0 ? options : {}, { ns: exports.PROJECT_INPUT_VALIDATOR_NS });
|
|
48
|
+
}
|
|
46
49
|
return i18next_1.default.t(key, options);
|
|
47
50
|
}
|
|
48
51
|
exports.t = t;
|
|
49
52
|
initI18n().catch(() => {
|
|
50
|
-
//
|
|
53
|
+
// needed by lint
|
|
51
54
|
});
|
|
52
55
|
//# sourceMappingURL=i18n.js.map
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -14,5 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./validators"), exports);
|
|
17
|
+
__exportStar(require("./deploy/validators"), exports);
|
|
18
|
+
__exportStar(require("./ui5/validators"), exports);
|
|
19
|
+
__exportStar(require("./general/validators"), exports);
|
|
18
20
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"deploy": {
|
|
3
|
+
"a": "Deployment Description should not exceed 60 characters",
|
|
4
|
+
"abapTransportNumRequired": "Provide a transport request for your application",
|
|
5
|
+
"abapPackageWarn": "Provide a package",
|
|
6
|
+
"abapAppNameRequired": "Application name required",
|
|
7
|
+
"abapInvalidNamespace": "Namespace invalid as there are too many forward slashes",
|
|
8
|
+
"abapInvalidNamespaceLength": "Namespace limited to 10 characters, entered {{length}}",
|
|
9
|
+
"abapInvalidAppNameLength": "Application name limited to 15 characters, entered {{length}}",
|
|
10
|
+
"abapInvalidAppName": "Application name needs to be prefixed with [{{prefix}}]",
|
|
11
|
+
"charactersForbiddenInAppName": "Only alphanumeric, underscore and slash characters are allowed",
|
|
12
|
+
"invalidAppNameMultipleReason": "Application name is invalid for multiple reasons:"
|
|
13
|
+
},
|
|
14
|
+
"ui5": {
|
|
15
|
+
"namespaceMustStartWithLetter": "The namespace must start with a letter",
|
|
16
|
+
"namespaceEndInPeriod": "The namespace cannot end with a period",
|
|
17
|
+
"namespaceCannotBeSap": "The namespace cannot be {{str}}",
|
|
18
|
+
"namespaceStartsWithNew": "The namespace cannot start with {{str}}",
|
|
19
|
+
"namespaceNumberAfterPeriod": "A number cannot follow a period in the namespace",
|
|
20
|
+
"lowerAlphaNumericOnly": "Please use lowercase alpha numeric characters only",
|
|
21
|
+
"lowerAlphaNumericDotsOnly": "Please use lowercase alpha numeric characters and dots only for the namespace.",
|
|
22
|
+
"namespaceSpecialCharacter": "The namespace can only contain letters, digits, dots, and underscores",
|
|
23
|
+
"moduleNameMustStartWithLetter": "The module name must start with a letter",
|
|
24
|
+
"nameCombinedTooLong": "The combined length of the namespace and module name must not exceed {{length}} characters",
|
|
25
|
+
"folderDoesNotExist": "Folder does not exist. Please enter the root folder for your project",
|
|
26
|
+
"folderDoesNotHaveCorrectPermissions": "Selected folder does not have required permissions. Please ensure you have permission to write to the selected folder and try again.",
|
|
27
|
+
"enterProjectFolder": "Please enter a project folder",
|
|
28
|
+
"nameNull": "Module name cannot be null",
|
|
29
|
+
"nameUndefined": "Module name cannot be undefined",
|
|
30
|
+
"nameNotString": "Module name must be a string",
|
|
31
|
+
"nameLengthZero": "Module name's length must be greater than zero",
|
|
32
|
+
"nameStartsWithPeriod": "Module name cannot start with a period",
|
|
33
|
+
"nameStartsWithUnderscore": "Module name cannot start with an underscore",
|
|
34
|
+
"nameStartsOrEndsWithSpace": "Module name cannot contain leading or trailing spaces",
|
|
35
|
+
"nameBlocklisted": "{{modName}} is a blocklisted module name",
|
|
36
|
+
"nameIsCoreModule": "{{modName}} is a core module name",
|
|
37
|
+
"nameTooLong": "Module name cannot contain more than {{length}} characters",
|
|
38
|
+
"nameTooShort": "Module name must be at least {{length}} characters",
|
|
39
|
+
"inputValueContainsCapital": "{{promptName}} cannot contain capital letters",
|
|
40
|
+
"nameContainsSpecialCharacters": "Module name cannot contain special characters (\"~'!()*)",
|
|
41
|
+
"nameNotUrlFriendly": "Module name can only contain URL-friendly characters",
|
|
42
|
+
"invalidModuleName": "Invalid module name",
|
|
43
|
+
"moduleAlreadyExists": "The folder: {{folderName}} already exists at the specified path"
|
|
44
|
+
},
|
|
45
|
+
"general": {
|
|
46
|
+
"invalidUrl": "Invalid URL: [{{-input}}]",
|
|
47
|
+
"invalidClient": "[{{client}}] is invalid. Enter blank or a value between 000-999"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validator: UI5 namespace.
|
|
3
|
+
*
|
|
4
|
+
* @param namespace - namepsace to validate
|
|
5
|
+
* @param moduleName - module name
|
|
6
|
+
* @param allowUnderscore - is underscore characters allowed
|
|
7
|
+
* @returns true if valid, otherwise an error message string for use in Inquirer validation functions
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateNamespace(namespace: string, moduleName?: string, allowUnderscore?: boolean): boolean | string;
|
|
10
|
+
/**
|
|
11
|
+
* Validator: UI5 library module name.
|
|
12
|
+
*
|
|
13
|
+
* @param libName - library module name
|
|
14
|
+
* @returns true if valid, otherwise an error message string for use in Inquirer validation functions
|
|
15
|
+
*/
|
|
16
|
+
export declare function validateLibModuleName(libName: string): boolean | string;
|
|
17
|
+
/**
|
|
18
|
+
* Validator: UI5 project directory can be used to create a UI5 application.
|
|
19
|
+
*
|
|
20
|
+
* @param targetFolder - the directory path not including the application folder (UI5 application name)
|
|
21
|
+
* @param projectName - the UI5 application directory name
|
|
22
|
+
* @returns true if valid, otherwise an error message string for use in Inquirer validation function
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateProjectFolder(targetFolder: string, projectName: string): boolean | string;
|
|
25
|
+
/**
|
|
26
|
+
* Validator: UI5 package json module name validator. Validates a module name accoding to npm package rules and some additional UI5 specific rules.
|
|
27
|
+
*
|
|
28
|
+
* @param moduleName - module name to validate
|
|
29
|
+
* @returns true if valid, otherwise an error message string for use in Inquirer validation functions
|
|
30
|
+
*/
|
|
31
|
+
export declare function validateModuleName(moduleName: string): boolean | string;
|
|
32
|
+
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateModuleName = exports.validateProjectFolder = exports.validateLibModuleName = exports.validateNamespace = void 0;
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
const i18n_1 = require("../i18n");
|
|
9
|
+
const fs_1 = require("fs");
|
|
10
|
+
const validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
|
|
11
|
+
/**
|
|
12
|
+
* Validator: UI5 application namespace.
|
|
13
|
+
*
|
|
14
|
+
* @param namespace - namespace
|
|
15
|
+
* @param moduleName - module name
|
|
16
|
+
* @param allowUnderscore - should allow underscores in namespace
|
|
17
|
+
* @returns true if valid, otherwise an error message string for use in Inquirer validation functions
|
|
18
|
+
*/
|
|
19
|
+
function validateNamespacePattern(namespace, moduleName = '', allowUnderscore = true) {
|
|
20
|
+
// Since namespace is concatenated with name to write the app id to the yamls we must comply with the yaml specVersion validation
|
|
21
|
+
// https://sap.github.io/ui5-tooling/stable/pages/Configuration/#name
|
|
22
|
+
if (!/^[a-zA-Z]/.test(namespace)) {
|
|
23
|
+
return (0, i18n_1.t)('ui5.namespaceMustStartWithLetter');
|
|
24
|
+
}
|
|
25
|
+
if (namespace.endsWith('.')) {
|
|
26
|
+
return (0, i18n_1.t)('ui5.namespaceEndInPeriod');
|
|
27
|
+
}
|
|
28
|
+
if (namespace.toUpperCase() === 'SAP') {
|
|
29
|
+
return (0, i18n_1.t)('ui5.namespaceCannotBeSap', { str: namespace });
|
|
30
|
+
}
|
|
31
|
+
if (namespace.toLowerCase().startsWith('new')) {
|
|
32
|
+
return (0, i18n_1.t)('ui5.namespaceStartsWithNew', { str: namespace.substring(0, 3) });
|
|
33
|
+
}
|
|
34
|
+
if (/\.\d/.test(namespace)) {
|
|
35
|
+
return (0, i18n_1.t)('ui5.namespaceNumberAfterPeriod');
|
|
36
|
+
}
|
|
37
|
+
if (allowUnderscore && !/^[\w.]+$/.test(namespace)) {
|
|
38
|
+
return (0, i18n_1.t)('ui5.namespaceSpecialCharacter');
|
|
39
|
+
}
|
|
40
|
+
else if (!allowUnderscore && !/^[a-z0-9.]*$/g.test(namespace)) {
|
|
41
|
+
return (0, i18n_1.t)('ui5.lowerAlphaNumericDotsOnly');
|
|
42
|
+
}
|
|
43
|
+
if ((moduleName + namespace).length > 70) {
|
|
44
|
+
return (0, i18n_1.t)('ui5.nameCombinedTooLong', { length: 70 });
|
|
45
|
+
}
|
|
46
|
+
if (namespace.toLowerCase() !== namespace) {
|
|
47
|
+
return (0, i18n_1.t)('ui5.inputValueContainsCapital', { promptName: 'Namespace' });
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Validator: UI5 namespace.
|
|
53
|
+
*
|
|
54
|
+
* @param namespace - namepsace to validate
|
|
55
|
+
* @param moduleName - module name
|
|
56
|
+
* @param allowUnderscore - is underscore characters allowed
|
|
57
|
+
* @returns true if valid, otherwise an error message string for use in Inquirer validation functions
|
|
58
|
+
*/
|
|
59
|
+
function validateNamespace(namespace, moduleName, allowUnderscore = true) {
|
|
60
|
+
if (!namespace) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return validateNamespacePattern(namespace, moduleName, allowUnderscore);
|
|
64
|
+
}
|
|
65
|
+
exports.validateNamespace = validateNamespace;
|
|
66
|
+
/**
|
|
67
|
+
* Validator: UI5 library module name.
|
|
68
|
+
*
|
|
69
|
+
* @param libName - library module name
|
|
70
|
+
* @returns true if valid, otherwise an error message string for use in Inquirer validation functions
|
|
71
|
+
*/
|
|
72
|
+
function validateLibModuleName(libName) {
|
|
73
|
+
const isValid = validateModuleName(libName);
|
|
74
|
+
if (typeof isValid === 'string') {
|
|
75
|
+
return isValid;
|
|
76
|
+
}
|
|
77
|
+
if (!/^[a-z0-9]*$/g.test(libName)) {
|
|
78
|
+
return (0, i18n_1.t)('ui5.lowerAlphaNumericOnly');
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
exports.validateLibModuleName = validateLibModuleName;
|
|
83
|
+
/**
|
|
84
|
+
* Validator: UI5 project directory can be used to create a UI5 application.
|
|
85
|
+
*
|
|
86
|
+
* @param targetFolder - the directory path not including the application folder (UI5 application name)
|
|
87
|
+
* @param projectName - the UI5 application directory name
|
|
88
|
+
* @returns true if valid, otherwise an error message string for use in Inquirer validation function
|
|
89
|
+
*/
|
|
90
|
+
function validateProjectFolder(targetFolder, projectName) {
|
|
91
|
+
if (!folderExists(targetFolder)) {
|
|
92
|
+
return (0, i18n_1.t)('ui5.folderDoesNotExist');
|
|
93
|
+
}
|
|
94
|
+
if (!folderWritePermExists(targetFolder)) {
|
|
95
|
+
return (0, i18n_1.t)('ui5.folderDoesNotHaveCorrectPermissions');
|
|
96
|
+
}
|
|
97
|
+
if (targetFolder && targetFolder.length > 0 && !folderExists((0, path_1.join)(targetFolder, projectName))) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
else if (targetFolder && targetFolder.length > 0 && folderExists((0, path_1.join)(targetFolder, projectName))) {
|
|
101
|
+
return (0, i18n_1.t)('ui5.moduleAlreadyExists', { folderName: projectName });
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
return (0, i18n_1.t)('ui5.enterProjectFolder');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.validateProjectFolder = validateProjectFolder;
|
|
108
|
+
/**
|
|
109
|
+
* Validator: UI5 package json module name validator. Validates a module name accoding to npm package rules and some additional UI5 specific rules.
|
|
110
|
+
*
|
|
111
|
+
* @param moduleName - module name to validate
|
|
112
|
+
* @returns true if valid, otherwise an error message string for use in Inquirer validation functions
|
|
113
|
+
*/
|
|
114
|
+
function validateModuleName(moduleName) {
|
|
115
|
+
var _a, _b;
|
|
116
|
+
if (/^[^a-zA-Z]/.test(moduleName)) {
|
|
117
|
+
return (0, i18n_1.t)('ui5.moduleNameMustStartWithLetter');
|
|
118
|
+
}
|
|
119
|
+
if ((moduleName === null || moduleName === void 0 ? void 0 : moduleName.length) > 70) {
|
|
120
|
+
return (0, i18n_1.t)('ui5.nameTooLong', { length: 70 });
|
|
121
|
+
}
|
|
122
|
+
if ((moduleName === null || moduleName === void 0 ? void 0 : moduleName.length) < 3) {
|
|
123
|
+
return (0, i18n_1.t)('ui5.nameTooShort', { length: 3 });
|
|
124
|
+
}
|
|
125
|
+
// convert the validation strings from `validateNpmPackageName` to required texts
|
|
126
|
+
const messageMap = {
|
|
127
|
+
'name cannot be null': (0, i18n_1.t)('ui5.nameNull'),
|
|
128
|
+
'name cannot be undefined': (0, i18n_1.t)('ui5.nameUndefined'),
|
|
129
|
+
'name must be a string': (0, i18n_1.t)('ui5.nameNotString'),
|
|
130
|
+
'name length must be greater than zero': (0, i18n_1.t)('ui5.nameLengthZero'),
|
|
131
|
+
'name cannot start with a period': (0, i18n_1.t)('ui5.nameStartsWithPeriod'),
|
|
132
|
+
'name cannot start with an underscore': (0, i18n_1.t)('ui5.nameStartsWithUnderscore'),
|
|
133
|
+
'name cannot contain leading or trailing spaces': (0, i18n_1.t)('ui5.nameStartsOrEndsWithSpace'),
|
|
134
|
+
[moduleName + ' is a blocklisted name']: (0, i18n_1.t)('ui5.nameBlocklisted', { moduleName }),
|
|
135
|
+
[moduleName + ' is a core module name']: (0, i18n_1.t)('ui5.nameIsCoreModule', { moduleName }),
|
|
136
|
+
'name can no longer contain more than 214 characters': (0, i18n_1.t)('ui5.nameTooLong', { length: 214 }),
|
|
137
|
+
'name can no longer contain capital letters': (0, i18n_1.t)('ui5.INPUT_VALUE_CONTAINS_CAPITAL', {
|
|
138
|
+
promptName: 'Module'
|
|
139
|
+
}),
|
|
140
|
+
'name can no longer contain special characters ("~\'!()*")': (0, i18n_1.t)('ui5.NAME_CONTAINS_SPECIAL_CHARACTERS'),
|
|
141
|
+
'name can only contain URL-friendly characters': (0, i18n_1.t)('ui5.NAME_NOT_URL_FRIENDLY')
|
|
142
|
+
};
|
|
143
|
+
const valid = (0, validate_npm_package_name_1.default)(moduleName);
|
|
144
|
+
if (valid.validForNewPackages && valid.validForOldPackages) {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
return [...((_a = valid.errors) !== null && _a !== void 0 ? _a : []), ...((_b = valid.warnings) !== null && _b !== void 0 ? _b : [])]
|
|
148
|
+
.filter((msg) => !!msg)
|
|
149
|
+
.map((msg) => { var _a; return (_a = messageMap[msg]) !== null && _a !== void 0 ? _a : (0, i18n_1.t)('ui5.invalidModuleName'); })
|
|
150
|
+
.join(', ');
|
|
151
|
+
}
|
|
152
|
+
exports.validateModuleName = validateModuleName;
|
|
153
|
+
/**
|
|
154
|
+
* Test for existence of specified directory path.
|
|
155
|
+
*
|
|
156
|
+
* @param dirPath - directory path
|
|
157
|
+
* @returns true if the directory exists, false if not or validation error message
|
|
158
|
+
*/
|
|
159
|
+
function folderExists(dirPath) {
|
|
160
|
+
if (dirPath && typeof dirPath !== 'string') {
|
|
161
|
+
return (0, i18n_1.t)('ERROR_NAME_NOT_STRING');
|
|
162
|
+
}
|
|
163
|
+
return (0, fs_1.existsSync)(dirPath) && (0, fs_1.lstatSync)(dirPath).isDirectory();
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Test for directory write permissions.
|
|
167
|
+
*
|
|
168
|
+
* @param dirPath - path to the directory to test
|
|
169
|
+
* @returns true, if write is allowed
|
|
170
|
+
*/
|
|
171
|
+
function folderWritePermExists(dirPath) {
|
|
172
|
+
let folderPerm = true;
|
|
173
|
+
const isWin = process.platform === 'win32';
|
|
174
|
+
try {
|
|
175
|
+
(0, fs_1.accessSync)(isWin ? path_1.posix.basename(dirPath) : dirPath, fs_1.constants.W_OK);
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
folderPerm = false;
|
|
179
|
+
}
|
|
180
|
+
return folderPerm;
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=validators.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap-ux/project-input-validator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Library to validate Fiori project input formats",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,9 +14,14 @@
|
|
|
14
14
|
"private": false,
|
|
15
15
|
"main": "dist/index.js",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"i18next": "20.6.1"
|
|
17
|
+
"i18next": "20.6.1",
|
|
18
|
+
"validate-npm-package-name": "5.0.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/validate-npm-package-name": "4.0.1",
|
|
22
|
+
"@types/i18next": "13.0.0",
|
|
23
|
+
"jest-extended": "3.2.4"
|
|
18
24
|
},
|
|
19
|
-
"devDependencies": {},
|
|
20
25
|
"files": [
|
|
21
26
|
"dist",
|
|
22
27
|
"LICENSE",
|
|
@@ -25,7 +30,7 @@
|
|
|
25
30
|
],
|
|
26
31
|
"engines": {
|
|
27
32
|
"pnpm": ">=6.26.1 < 7.0.0 || >=7.1.0",
|
|
28
|
-
"node": ">=
|
|
33
|
+
"node": ">=18.x"
|
|
29
34
|
},
|
|
30
35
|
"scripts": {
|
|
31
36
|
"build": "tsc --build",
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"AbapAppDescLength": "Deployment Description should not exceed 60 characters",
|
|
3
|
-
"InvalidClient": "[{{client}}] is invalid. Enter blank or a value between 000-999",
|
|
4
|
-
"AbapTransportNumRequired": "Provide a transport request for your application",
|
|
5
|
-
"AbapPackageWarn": "Provide a package",
|
|
6
|
-
"InvalidUrl": "Invalid URL: [{{input}}]",
|
|
7
|
-
"AbapAppNameRequired": "Application name required",
|
|
8
|
-
"AbapInvalidNamespace": "Namespace invalid as there are too many forward slashes",
|
|
9
|
-
"AbapInvalidNamespaceLength": "Namespace limited to 10 characters, entered {{length}}",
|
|
10
|
-
"AbapInvalidAppNameLength": "Application name limited to 15 characters, entered {{length}}",
|
|
11
|
-
"AbapInvalidAppName": "Application name needs to be prefixed with [{{prefix}}]",
|
|
12
|
-
"CharactersForbiddenInAppName": "Only alphanumeric, underscore and slash characters are allowed",
|
|
13
|
-
"InvalidAppNameMultipleReason": "Application name is invalid for multiple reasons:"
|
|
14
|
-
}
|