npm package diff
Package: @forge/manifest
Versions: 7.7.0-next.12 - 7.5.2-next.0-experimental-204139e
File: package/out/validators/modules-validator.js
Index: package/out/validators/modules-validator.js
===================================================================
--- package/out/validators/modules-validator.js
+++ package/out/validators/modules-validator.js
@@ -8,34 +8,189 @@
const path_1 = require("path");
const ui_modifications_1 = require("./modules-validators/jira/ui-modifications");
const confluence_1 = require("./modules-validators/confluence");
const validate_full_admin_page_1 = require("./modules-validators/jira/validate-full-admin-page");
+const validate_subpages_in_module_1 = require("./modules-validators/jira/validate-subpages-in-module");
const remote_1 = require("./modules-validators/remote");
const validateModuleScopes_1 = require("./modules-validators/validateModuleScopes");
const bitbucket_1 = require("./modules-validators/bitbucket");
const rovo_1 = require("./modules-validators/rovo");
-const validate_workflow_1 = require("./modules-validators/jira/validate-workflow");
-const validate_full_page_1 = require("./modules-validators/jira/validate-full-page");
-const validate_custom_field_1 = require("./modules-validators/jira/validate-custom-field");
-const validate_trigger_1 = require("./modules-validators/jira/validate-trigger");
class ModulesValidator {
functionHandlerRegex = /^([a-zA-Z0-9-_]+)\.([a-zA-Z0-9-_]+)$/;
async validate(manifest) {
- if (!manifest?.typedContent || !manifest.filePath) {
+ if (!manifest || !manifest.typedContent || !manifest.filePath) {
return {
success: false,
manifestObject: manifest
};
}
- let validationErrors = [...this.connectModuleValidation(manifest)];
+ const validationErrors = [];
+ this.connectModuleValidation(manifest, validationErrors);
if (manifest.typedContent.modules) {
- const { typedContent: { modules, connectModules, remotes, permissions }, yamlContentByLine, filePath } = manifest;
- validationErrors = validationErrors.concat(this.checkUnsupportedModules(manifest.typedContent.modules, yamlContentByLine), this.functionKeyLength(modules, yamlContentByLine), this.minimumModuleCountValidation(modules, yamlContentByLine), this.functionKeyDefinedValidation(modules, yamlContentByLine), this.endpointValidations(modules, yamlContentByLine, remotes, permissions?.scopes || []), this.duplicateModuleKeyValidation(modules, connectModules || {}, yamlContentByLine), this.functionHandlerValidation(modules, yamlContentByLine, filePath), (0, validate_workflow_1.validateJiraWorkflowValidator)(modules, yamlContentByLine), (0, validate_workflow_1.validateJiraWorkflowCondition)(modules, yamlContentByLine), (0, ui_modifications_1.validateUiModificationsModule)(modules, yamlContentByLine), (0, validate_full_admin_page_1.validateJiraFullAdminPage)(modules, yamlContentByLine), (0, validate_full_page_1.validateJiraFullPage)(modules, yamlContentByLine), (0, validate_custom_field_1.validateJiraCustomField)(modules, yamlContentByLine), (0, confluence_1.validateConfluenceModules)(modules, yamlContentByLine), (0, bitbucket_1.validateBitbucketModules)(modules, yamlContentByLine), (0, validate_trigger_1.validateJiraTriggers)(modules, yamlContentByLine), (0, remote_1.validateRemoteModules)(modules, yamlContentByLine), (0, validateModuleScopes_1.validateModuleScopes)(modules, yamlContentByLine, permissions), (0, rovo_1.validateRovoModules)(modules, yamlContentByLine));
+ const { typedContent: { modules, remotes, permissions }, yamlContentByLine, filePath } = manifest;
+ const { function: _function, endpoint: _endpoint } = modules;
+ this.checkUnsupportedModules(manifest.typedContent.modules, validationErrors, yamlContentByLine);
+ _function?.forEach((f) => {
+ if (f.key.length > 23) {
+ validationErrors.push({
+ message: text_1.errors.modules.function.invalidKeyLength(f.key),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(f.key, yamlContentByLine)
+ });
+ }
+ });
+ if (Object.keys(modules).filter((moduleKey) => this.isNotFunctionOrEndpoint(moduleKey)).length < 1) {
+ validationErrors.push({
+ message: text_1.errors.modules.missingModule(),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)('app', yamlContentByLine)
+ });
+ }
+ const validModules = Object.keys(modules).filter((moduleKey) => this.isNotFunctionOrEndpoint(moduleKey));
+ validModules.forEach((moduleKey) => {
+ modules[moduleKey]?.forEach((module) => {
+ (0, utils_1.findInvalidFunctionReferences)(module, _function).forEach((functionKey) => {
+ validationErrors.push({
+ message: text_1.errors.modules.wrongFunctionReference(moduleKey, functionKey),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(moduleKey, yamlContentByLine)
+ });
+ });
+ (0, utils_1.findInvalidEndpointReferences)(module, _endpoint).forEach((endpointKey) => {
+ validationErrors.push({
+ message: text_1.errors.modules.wrongEndpointReference(moduleKey, endpointKey),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(moduleKey, yamlContentByLine)
+ });
+ });
+ });
+ });
+ this.endpointValidations(_endpoint, validationErrors, yamlContentByLine, remotes, permissions?.scopes || [], modules);
+ const moduleKeys = [];
+ Object.keys(modules).forEach((moduleKey) => {
+ modules[moduleKey]?.forEach((module) => moduleKeys.push(module.key));
+ });
+ const duplicateKeys = [...new Set(moduleKeys.filter((item, index) => moduleKeys.indexOf(item) != index))];
+ duplicateKeys.forEach((duplicateKey) => {
+ validationErrors.push({
+ message: text_1.errors.modules.duplicateKeyFound(duplicateKey),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(duplicateKey, yamlContentByLine)
+ });
+ });
+ _function?.forEach((func) => {
+ if (!this.functionHandlerRegex.test(func.handler)) {
+ validationErrors.push({
+ message: text_1.errors.modules.function.handler.invalidRegex(func.handler, this.functionHandlerRegex),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(func.handler, yamlContentByLine)
+ });
+ }
+ else {
+ const matches = this.functionHandlerRegex.exec(func.handler);
+ const fileName = matches ? matches[1] : undefined;
+ const _checkFileExists = (fileName) => {
+ return (['tsx', 'jsx', 'ts', 'js'].find((ext) => (0, fs_1.existsSync)((0, path_1.resolve)((0, path_1.dirname)(filePath), 'src', `${fileName}.${ext}`))) !== undefined);
+ };
+ if (!_checkFileExists(fileName)) {
+ validationErrors.push({
+ message: text_1.errors.modules.function.handler.fileNotExists(func.handler, fileName),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(func.handler, yamlContentByLine)
+ });
+ }
+ }
+ });
+ modules[types_1.AllModuleTypes.JiraWorkflowValidator]?.forEach((module) => {
+ if (!module.expression && !module.function) {
+ validationErrors.push({
+ message: text_1.errors.modules.jiraWorkflowValidator.missingProperty(module.key),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(module.key, yamlContentByLine)
+ });
+ }
+ if (module.expression && module.function) {
+ validationErrors.push({
+ message: text_1.errors.modules.jiraWorkflowValidator.invalidProperty(module.key),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(module.key, yamlContentByLine)
+ });
+ }
+ });
+ modules[types_1.AllModuleTypes.JiraWorkflowCondition]?.forEach((module) => {
+ if (!(module.expression && module.expression.trim())) {
+ validationErrors.push({
+ message: text_1.errors.modules.jiraWorkflowCondition.missingExpression(module.key),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(module.key, yamlContentByLine)
+ });
+ }
+ });
+ validationErrors.push(...(0, ui_modifications_1.validateUiModificationsModule)(modules, yamlContentByLine));
+ validationErrors.push(...(0, validate_full_admin_page_1.validateFullAdminPage)(modules, yamlContentByLine));
+ [types_1.AllModuleTypes.JiraProjectPage, types_1.AllModuleTypes.JiraProjectSettingsPage, types_1.AllModuleTypes.JiraGlobalPage].forEach((moduleType) => {
+ const moduleArray = modules[moduleType];
+ if (moduleArray && moduleArray.length > 1) {
+ validationErrors.push({
+ message: text_1.errors.modules.singleEntryOfTheModule(moduleType),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(moduleArray[1].key, yamlContentByLine)
+ });
+ }
+ if (moduleArray && moduleArray.length === 1) {
+ validationErrors.push(...(0, validate_subpages_in_module_1.validateSubpagesInModule)(modules, moduleType, yamlContentByLine));
+ }
+ });
+ [types_1.AllModuleTypes.JiraCustomField, types_1.AllModuleTypes.JiraCustomFieldType].forEach((moduleType) => {
+ modules[moduleType]?.forEach((module) => {
+ if (!module || module.type !== 'object' || !module.schema)
+ return;
+ const getAliases = (properties = {}) => Object.values(properties)
+ .map((v) => [v.searchAlias, ...getAliases(v.properties)])
+ .reduce((acc, val) => acc.concat(val), [])
+ .filter(Boolean);
+ const aliases = getAliases(module.schema.properties);
+ const duplicates = Array.from(new Set(aliases.filter((item, index) => aliases.indexOf(item) != index)));
+ if (duplicates.length) {
+ validationErrors.push({
+ message: text_1.errors.modules.customFields.searchAlias(duplicates),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(module.key, yamlContentByLine)
+ });
+ }
+ });
+ });
+ validationErrors.push(...(0, confluence_1.validateConfluenceModules)(modules, yamlContentByLine));
+ validationErrors.push(...(0, bitbucket_1.validateBitbucketModules)(modules, yamlContentByLine));
+ modules?.trigger?.forEach((module) => {
+ if (module.filter) {
+ const onlyJiraEvents = module.events.every((e) => e.includes('jira'));
+ if (!onlyJiraEvents) {
+ validationErrors.push({
+ message: text_1.errors.modules.trigger.filteringWorksOnlyWithJiraEvents(),
+ reference: text_1.References.Modules,
+ level: 'error',
+ ...(0, utils_1.findPosition)(module.key, yamlContentByLine)
+ });
+ }
+ }
+ });
+ validationErrors.push(...(0, remote_1.validateRemoteModules)(modules, yamlContentByLine));
+ validationErrors.push(...(0, validateModuleScopes_1.validateModuleScopes)(modules, yamlContentByLine, permissions));
+ validationErrors.push(...(0, rovo_1.validateRovoModules)(modules, yamlContentByLine));
}
- else {
- const { typedContent: { connectModules }, yamlContentByLine } = manifest;
- validationErrors = validationErrors.concat(this.duplicateModuleKeyValidation({}, connectModules || {}, yamlContentByLine));
- }
return {
success: validationErrors.length === 0,
manifestObject: manifest,
errors: validationErrors
@@ -43,36 +198,9 @@
}
isNotFunctionOrEndpoint(moduleKey) {
return moduleKey !== (0, utils_1.cleanKey)(types_1.AllModuleTypes.CoreFunction) && moduleKey !== (0, utils_1.cleanKey)(types_1.AllModuleTypes.CoreEndpoint);
}
- functionKeyLength(modules, yamlContentByLine) {
- const validationErrors = [];
- modules.function?.forEach((f) => {
- if (f.key.length > 23) {
- validationErrors.push({
- message: text_1.errors.modules.function.invalidKeyLength(f.key),
- reference: text_1.References.Modules,
- level: 'error',
- ...(0, utils_1.findPosition)(f.key, yamlContentByLine)
- });
- }
- });
- return validationErrors;
- }
- minimumModuleCountValidation(modules, yamlContentByLine) {
- const validationErrors = [];
- if (Object.keys(modules).filter((moduleKey) => this.isNotFunctionOrEndpoint(moduleKey)).length < 1) {
- validationErrors.push({
- message: text_1.errors.modules.missingModule(),
- reference: text_1.References.Modules,
- level: 'error',
- ...(0, utils_1.findPosition)('app', yamlContentByLine)
- });
- }
- return validationErrors;
- }
- checkUnsupportedModules(modules, yamlContentByLine) {
- const validationErrors = [];
+ checkUnsupportedModules(modules, validationErrors, yamlContentByLine) {
Object.keys(modules)
.filter((key) => !types_1.SUPPORTED_MODULES.map((key) => (0, utils_1.cleanKey)(key)).includes(key))
.forEach((invalidKey) => {
validationErrors.push({
@@ -81,12 +209,10 @@
level: 'error',
...(0, utils_1.findPosition)(invalidKey, yamlContentByLine)
});
});
- return validationErrors;
}
- connectModuleValidation(manifest) {
- const validationErrors = [];
+ connectModuleValidation(manifest, validationErrors) {
if (!manifest.typedContent?.modules && !manifest.typedContent?.connectModules) {
validationErrors.push({
message: text_1.errors.schemaError(undefined, [], text_1.errors.schema.oneOf([['modules'], ['connectModules']])),
reference: text_1.References.SchemaError,
@@ -94,43 +220,15 @@
line: 1,
column: 0
});
}
- return validationErrors;
}
- functionKeyDefinedValidation(modules, yamlContentByLine) {
- const validationErrors = [];
- const validModules = Object.keys(modules).filter((moduleKey) => this.isNotFunctionOrEndpoint(moduleKey));
- validModules.forEach((moduleKey) => {
- modules[moduleKey]?.forEach((module) => {
- (0, utils_1.findInvalidFunctionReferences)(module, modules.function).forEach((functionKey) => {
- validationErrors.push({
- message: text_1.errors.modules.wrongFunctionReference(moduleKey, functionKey),
- reference: text_1.References.Modules,
- level: 'error',
- ...(0, utils_1.findPosition)(moduleKey, yamlContentByLine)
- });
- });
- (0, utils_1.findInvalidEndpointReferences)(module, modules.endpoint).forEach((endpointKey) => {
- validationErrors.push({
- message: text_1.errors.modules.wrongEndpointReference(moduleKey, endpointKey),
- reference: text_1.References.Modules,
- level: 'error',
- ...(0, utils_1.findPosition)(moduleKey, yamlContentByLine)
- });
- });
- });
- });
- return validationErrors;
- }
- endpointValidations(modules, yamlContentByLine, remotes, scopes) {
- const validationErrors = [];
+ endpointValidations(_endpoint, validationErrors, yamlContentByLine, remotes, scopes, modules) {
const SYSTEM_TOKEN_SCOPE = 'read:app-system-token';
const USER_TOKEN_SCOPE = 'read:app-user-token';
const _checkRemoteExists = (remoteKey) => {
return remotes?.find((remote) => remote.key === remoteKey) !== undefined;
};
- const { endpoint: _endpoint } = modules;
const eventModulesWithEndpoint = modules?.trigger?.filter((trigger) => trigger.endpoint != null) || [];
eventModulesWithEndpoint.forEach((event) => {
const endpointModule = _endpoint?.find((remoteEndpoint) => remoteEndpoint.key === event.endpoint);
if (endpointModule) {
@@ -207,58 +305,7 @@
...(0, utils_1.findPosition)('scopes', yamlContentByLine)
});
}
});
- return validationErrors;
}
- duplicateModuleKeyValidation(modules, connectModules, yamlContentByLine) {
- const validationErrors = [];
- const moduleKeys = [];
- [modules, connectModules].forEach((modules) => {
- Object.values(modules).forEach((moduleList) => {
- if (Array.isArray(moduleList)) {
- moduleList.forEach((module) => moduleKeys.push(module.key));
- }
- });
- });
- const duplicateKeys = [...new Set(moduleKeys.filter((item, index) => moduleKeys.indexOf(item) != index))];
- duplicateKeys.forEach((duplicateKey) => {
- validationErrors.push({
- message: text_1.errors.modules.duplicateKeyFound(duplicateKey),
- reference: text_1.References.Modules,
- level: 'error',
- ...(0, utils_1.findPosition)(duplicateKey, yamlContentByLine)
- });
- });
- return validationErrors;
- }
- functionHandlerValidation(modules, yamlContentByLine, filePath) {
- const validationErrors = [];
- modules.function?.forEach((func) => {
- if (!this.functionHandlerRegex.test(func.handler)) {
- validationErrors.push({
- message: text_1.errors.modules.function.handler.invalidRegex(func.handler, this.functionHandlerRegex),
- reference: text_1.References.Modules,
- level: 'error',
- ...(0, utils_1.findPosition)(func.handler, yamlContentByLine)
- });
- }
- else {
- const matches = this.functionHandlerRegex.exec(func.handler);
- const fileName = matches ? matches[1] : undefined;
- const _checkFileExists = (fileName) => {
- return (['tsx', 'jsx', 'ts', 'js'].find((ext) => (0, fs_1.existsSync)((0, path_1.resolve)((0, path_1.dirname)(filePath), 'src', `${fileName}.${ext}`))) !== undefined);
- };
- if (!_checkFileExists(fileName)) {
- validationErrors.push({
- message: text_1.errors.modules.function.handler.fileNotExists(func.handler, fileName),
- reference: text_1.References.Modules,
- level: 'error',
- ...(0, utils_1.findPosition)(func.handler, yamlContentByLine)
- });
- }
- }
- });
- return validationErrors;
- }
}
exports.ModulesValidator = ModulesValidator;