npm package diff

Package: @forge/manifest

Versions: 7.5.2-next.0-experimental-10722bc - 7.7.0-next.13

Added:package/out/interpolator/environment-variable-interpolator.js

Added:package/out/utils/i18n/index.js

Added:package/out/interpolator/manifest-interpolator-manager.js

Added:package/out/interpolator/manifest-interpolator.js

Added:package/out/utils/manifest-parser-builder.js

Added:package/out/utils/i18n/module-i18n-helper.js

Added:package/out/interpolator/string-resource-interpolator.js

Added:package/out/validators/translations-validator.js

Added:package/out/utils/i18n/type-check.js

Added:package/out/validators/modules-validators/jira/validate-custom-field.js

Added:package/out/validators/modules-validators/jira/validate-full-page.js

Added:package/out/validators/modules-validators/jira/validate-trigger.js

Added:package/out/validators/modules-validators/rovo/validate-undefined-action-name.js

Added:package/out/validators/modules-validators/rovo/validate-unreferenced-actions.js

Added:package/out/validators/modules-validators/jira/validate-workflow.js

Added:package/out/interpolator/environment-variable-interpolator.d.ts.map

Added:package/out/utils/i18n/index.d.ts.map

Added:package/out/interpolator/manifest-interpolator-manager.d.ts.map

Added:package/out/interpolator/manifest-interpolator.d.ts.map

Added:package/out/utils/manifest-parser-builder.d.ts.map

Added:package/out/utils/i18n/module-i18n-helper.d.ts.map

Added:package/out/interpolator/string-resource-interpolator.d.ts.map

Added:package/out/validators/translations-validator.d.ts.map

Added:package/out/utils/i18n/type-check.d.ts.map

Added:package/out/validators/modules-validators/jira/validate-custom-field.d.ts.map

Added:package/out/validators/modules-validators/jira/validate-full-page.d.ts.map

Added:package/out/validators/modules-validators/jira/validate-trigger.d.ts.map

Added:package/out/validators/modules-validators/rovo/validate-undefined-action-name.d.ts.map

Added:package/out/validators/modules-validators/rovo/validate-unreferenced-actions.d.ts.map

Added:package/out/validators/modules-validators/jira/validate-workflow.d.ts.map

Added:package/out/interpolator/environment-variable-interpolator.d.ts

Added:package/out/utils/i18n/index.d.ts

Added:package/out/interpolator/manifest-interpolator-manager.d.ts

Added:package/out/interpolator/manifest-interpolator.d.ts

Added:package/out/utils/manifest-parser-builder.d.ts

Added:package/out/utils/i18n/module-i18n-helper.d.ts

Added:package/out/interpolator/string-resource-interpolator.d.ts

Added:package/out/validators/translations-validator.d.ts

Added:package/out/utils/i18n/type-check.d.ts

Added:package/out/validators/modules-validators/jira/validate-custom-field.d.ts

Added:package/out/validators/modules-validators/jira/validate-full-page.d.ts

Added:package/out/validators/modules-validators/jira/validate-trigger.d.ts

Added:package/out/validators/modules-validators/rovo/validate-undefined-action-name.d.ts

Added:package/out/validators/modules-validators/rovo/validate-unreferenced-actions.d.ts

Added:package/out/validators/modules-validators/jira/validate-workflow.d.ts

Modified:package/out/validators/connect-modules-validator.js

Index: package/out/validators/connect-modules-validator.js
===================================================================
--- package/out/validators/connect-modules-validator.js
+++ package/out/validators/connect-modules-validator.js
@@ -26,26 +26,15 @@
                     level: 'error',
                     ...(0, utils_1.findPosition)(invalidName, yamlContentByLine, 'connectModules')
                 });
             });
-            const modules = connectModuleNames.map((moduleName) => connectModules[moduleName]);
-            const moduleKeys = [].concat(...modules).map((item) => item.key);
-            const duplicateKeys = [...new Set(moduleKeys.filter((item, index) => moduleKeys.indexOf(item) != index))];
-            duplicateKeys.forEach((duplicateKey) => {
-                validationErrors.push({
-                    message: text_1.errors.connectModules.duplicateKeyFound(duplicateKey),
-                    reference: text_1.References.ConnectModules,
-                    level: 'error',
-                    ...(0, utils_1.findPosition)(duplicateKey, yamlContentByLine)
-                });
-            });
             const lifecycleModules = connectModuleNames.filter((m) => m.endsWith(':lifecycle'));
             if (lifecycleModules) {
                 lifecycleModules.forEach((lifecycle) => {
                     const lifecycleModule = connectModules[lifecycle];
                     if (Array.isArray(lifecycleModule) && lifecycleModule.length > 1) {
                         validationErrors.push({
-                            message: text_1.errors.connectModules.duplicatateLifecycleFound(lifecycle),
+                            message: text_1.errors.connectModules.duplicateLifecycleFound(lifecycle),
                             reference: text_1.References.ConnectModules,
                             level: 'error',
                             ...(0, utils_1.findPosition)(lifecycle, yamlContentByLine)
                         });

Modified:package/out/text/errors.js

Index: package/out/text/errors.js
===================================================================
--- package/out/text/errors.js
+++ package/out/text/errors.js
@@ -21,9 +21,13 @@
         additionalProperties: (additionalProperty) => `should NOT have additional property '${additionalProperty}'`,
         notAllowed: (props) => props
             ? `does not support the following Forge properties - ${props.map((v) => "'" + v + "'").join(', ')}`
             : 'provided properties do not match schema. Learn more about modules at https://go.atlassian.com/forge-modules',
-        missingEnvironmentVariable: (variable) => `could not find environment variable '${variable}'`
+        missingEnvironmentVariable: (variable) => `could not find environment variable '${variable}'`,
+        errorReadingResourceFile: (variable, errorMessage) => `error while reading resource file: '${variable}'. Error: ${errorMessage}`,
+        resourceNotFound: (variable) => `could not find resource: '${variable}'`,
+        resourcePathNotDefined: (variable) => `resource path not defined for resource: '${variable}'`,
+        resourceFileNotSupported: (variable) => `resource file type not supported: '${variable}'`
     },
     permissions: {
         invalidPermission: (element, value) => `Invalid '${element}' permission in the manifest.yml file - '${value}'. Learn more about permissions at: https://go.atlassian.com/forge-permissions.`,
         missingPermissionFromScope: (scope, event) => `Trigger event: '${event}' requires '${scope}' scope`,
@@ -32,11 +36,9 @@
         deprecatedPermission: (element, value) => `There are deprecated scopes '${element}' in the manifest.yml file: '${value.join(', ')}'. You need to update this app to use new scopes and remove the deprecated scopes. Learn more at: https://go.atlassian.com/forge-permissions.`
     },
     connectModules: {
         invalidConnectModule: (module) => `invalid value '${module}' in connectModules`,
-        missingConnectModule: () => `document must have at least 1 valid connect module when 'connectModules' is declared`,
-        duplicateKeyFound: (key) => `found duplicate connect module key '${key}'`,
-        duplicatateLifecycleFound: (module) => `'${module}' should contain only one element`
+        duplicateLifecycleFound: (module) => `'${module}' should contain only one element`
     },
     modules: {
         invalidModule: (module) => `invalid value '${module}' in modules`,
         missingModule: () => 'document must have at least 1 module',
@@ -121,9 +123,11 @@
         remote: {
             missingModuleRemoteStorageInScopeEUD: (key) => `missing storage.inScopeEUD in ${key} module. storage.inScopeEUD is required if storage is present in operations.`
         },
         rovo: {
-            incorrectAgentActionReference: (module, moduleKey) => `${module} references undefined action module with key '${moduleKey}'.`
+            incorrectAgentActionReference: (module, moduleKey) => `${module} references undefined action module with key '${moduleKey}'.`,
+            unreferencedAction: (action) => `Action '${action}' is not referenced by any Rovo agent.`,
+            undefinedActionName: (action) => `Action '${action}' does not have a name property. 'name' property will be required when Forge Agents are GA.`
         }
     },
     resources: {
         missingResource: (folder, key) => `missing resource '${folder}' is being referenced by '${key}' in resources`,
@@ -170,8 +174,18 @@
             extraFiles: {
                 missing: (glob) => `Extra files specification '${glob}' does not match any files.`
             }
         }
+    },
+    translations: {
+        missingTranslationsJsonFile: (languageLocaleCode) => `There is no available translations JSON file for the specified fallback language: '${languageLocaleCode}'`,
+        duplicateFallbackConfig: (languageLocaleCode) => `Duplicated fallback configuration found for: '${languageLocaleCode}'`,
+        invalidLanguageFile: (languageLocaleCode, path) => `An error occurred while reading JSON file for '${languageLocaleCode}' at the specified path: ${path}`,
+        duplicateResourceKey: (languageLocaleCode) => `Duplicate translations resource key found: '${languageLocaleCode}'`,
+        i18nKeyNotFound: (keyName) => `i18n key '${keyName}' could not be found in default locale file.`,
+        missingTranslationsPropertyError: 'i18n key(s) found but translations property is missing in manifest file',
+        internalI18nPropertyKeyFound: (propertyKey, moduleKey) => `Unexpected property key '${propertyKey}' found in '${moduleKey}' module`,
+        i18nValueValidationError: (keyName, languageLocaleCode, errorMsg) => `i18n value for key '${keyName}' for locale '${languageLocaleCode}' ${errorMsg}`
     }
 };
 var References;
 (function (References) {
@@ -181,9 +195,8 @@
     References["Permissions"] = "valid-permissions-required";
     References["MissingScopes"] = "permission-scope-required";
     References["Modules"] = "valid-module-required";
     References["ConnectModules"] = "valid-connect-module-required";
-    References["DuplicateModuleKeys"] = "duplicate-module-keys";
     References["Resources"] = "valid-resource-required";
     References["Providers"] = "valid-provider-required";
     References["Deprecated"] = "deprecated-property";
     References["App"] = "valid-app-config-required";

Modified:package/out/processor/full-validation-processor.js

Index: package/out/processor/full-validation-processor.js
===================================================================
--- package/out/processor/full-validation-processor.js
+++ package/out/processor/full-validation-processor.js
@@ -29,9 +29,10 @@
             new validators_1.SnapshotValidator(),
             new jql_function_validator_1.JqlFunctionValidator(),
             new validators_1.PackageValidator(),
             new app_features_validator_1.AppFeaturesValidator(),
-            new data_classification_validator_1.DataClassificationValidator()
+            new data_classification_validator_1.DataClassificationValidator(),
+            new validators_1.TranslationsValidator()
         ]);
     }
 }
 exports.FullValidationProcessor = FullValidationProcessor;

Modified:package/out/utils/index.js

Index: package/out/utils/index.js
===================================================================
--- package/out/utils/index.js
+++ package/out/utils/index.js
@@ -4,5 +4,6 @@
 tslib_1.__exportStar(require("./get-all-modules"), exports);
 tslib_1.__exportStar(require("./line-finder"), exports);
 tslib_1.__exportStar(require("./module-key-cleaner"), exports);
 tslib_1.__exportStar(require("./module-references"), exports);
-tslib_1.__exportStar(require("./manifest-parser"), exports);
+tslib_1.__exportStar(require("./manifest-parser-builder"), exports);
+tslib_1.__exportStar(require("./i18n"), exports);

Modified:package/out/validators/index.js

Index: package/out/validators/index.js
===================================================================
--- package/out/validators/index.js
+++ package/out/validators/index.js
@@ -16,4 +16,5 @@
 tslib_1.__exportStar(require("./connect-authentication-validator"), exports);
 tslib_1.__exportStar(require("./entity-property-validator"), exports);
 tslib_1.__exportStar(require("./snapshot-validator"), exports);
 tslib_1.__exportStar(require("./package-validator"), exports);
+tslib_1.__exportStar(require("./translations-validator"), exports);

Modified:package/out/validators/modules-validators/rovo/index.js

Index: package/out/validators/modules-validators/rovo/index.js
===================================================================
--- package/out/validators/modules-validators/rovo/index.js
+++ package/out/validators/modules-validators/rovo/index.js
@@ -1,10 +1,14 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.validateRovoModules = void 0;
 const validate_rovo_agent_actions_1 = require("./validate-rovo-agent-actions");
+const validate_unreferenced_actions_1 = require("./validate-unreferenced-actions");
+const validate_undefined_action_name_1 = require("./validate-undefined-action-name");
 const validateRovoModules = (modules, yamlContentByLine) => {
     const validationErrors = [];
     validationErrors.push(...(0, validate_rovo_agent_actions_1.validateRovoAgentActions)(modules, yamlContentByLine));
+    validationErrors.push(...(0, validate_unreferenced_actions_1.validateUnreferencedActions)(modules, yamlContentByLine));
+    validationErrors.push(...(0, validate_undefined_action_name_1.validateUndefinedActionName)(modules, yamlContentByLine));
     return validationErrors;
 };
 exports.validateRovoModules = validateRovoModules;

Modified:package/out/utils/manifest-parser.js

Index: package/out/utils/manifest-parser.js
===================================================================
--- package/out/utils/manifest-parser.js
+++ package/out/utils/manifest-parser.js
@@ -1,11 +1,9 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.ManifestParser = exports.ManifestParserError = void 0;
-const tslib_1 = require("tslib");
 const yaml_1 = require("yaml");
-const errors_1 = require("../text/errors");
-const Sentry = tslib_1.__importStar(require("@sentry/node"));
+const manifest_interpolator_1 = require("../interpolator/manifest-interpolator");
 const yamlConfigOptions = { indent: 2, skipInvalid: true };
 class ManifestParserError extends Error {
     constructor(message) {
         super(message);
@@ -16,37 +14,23 @@
         };
     }
 }
 exports.ManifestParserError = ManifestParserError;
-const POSSIBLE_ENVIRONMENT_VARIABLE = /\$\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g;
 class ManifestParser {
-    envVarsRecord;
-    envVarsToReplace;
-    constructor(envVarsRecord = {}) {
-        this.envVarsRecord = envVarsRecord;
-        this.envVarsToReplace = [];
+    manifestInterpolator;
+    constructor(manifestInterpolator) {
+        this.manifestInterpolator = manifestInterpolator;
     }
     parseManifest(manifest) {
-        const rawManifest = (0, yaml_1.parse)(manifest);
-        this.envVarsToReplace = rawManifest.environment?.variables ?? [];
-        return (0, yaml_1.parse)(manifest, this.environmentVariableReviver);
-    }
-    parseManifestAsString = (manifest) => (0, yaml_1.stringify)(this.parseManifest(manifest), yamlConfigOptions);
-    environmentVariableReviver = (_, value) => {
-        if (!(typeof value == 'string')) {
-            return value;
+        try {
+            return this.manifestInterpolator.interpolate(manifest);
         }
-        value = value.replace(POSSIBLE_ENVIRONMENT_VARIABLE, (original, envVarName) => {
-            if (!this.envVarsToReplace.includes(envVarName)) {
-                return original;
+        catch (error) {
+            if (error instanceof manifest_interpolator_1.ManifestInterpolatorError) {
+                throw new ManifestParserError(error.message);
             }
-            const envVar = this.envVarsRecord[envVarName];
-            if (envVar === undefined) {
-                throw new ManifestParserError(errors_1.errors.schema.missingEnvironmentVariable(envVarName));
-            }
-            Sentry.captureMessage('replaced environment variable');
-            return envVar;
-        });
-        return value;
-    };
+            throw error;
+        }
+    }
+    parseManifestAsString = (manifest) => (0, yaml_1.stringify)(this.parseManifest(manifest), yamlConfigOptions);
 }
 exports.ManifestParser = ManifestParser;

Modified: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,189 +8,34 @@
 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 || !manifest.typedContent || !manifest.filePath) {
+        if (!manifest?.typedContent || !manifest.filePath) {
             return {
                 success: false,
                 manifestObject: manifest
             };
         }
-        const validationErrors = [];
-        this.connectModuleValidation(manifest, validationErrors);
+        let validationErrors = [...this.connectModuleValidation(manifest)];
         if (manifest.typedContent.modules) {
-            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));
+            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));
         }
+        else {
+            const { typedContent: { connectModules }, yamlContentByLine } = manifest;
+            validationErrors = validationErrors.concat(this.duplicateModuleKeyValidation({}, connectModules || {}, yamlContentByLine));
+        }
         return {
             success: validationErrors.length === 0,
             manifestObject: manifest,
             errors: validationErrors
@@ -198,9 +43,36 @@
     }
     isNotFunctionOrEndpoint(moduleKey) {
         return moduleKey !== (0, utils_1.cleanKey)(types_1.AllModuleTypes.CoreFunction) && moduleKey !== (0, utils_1.cleanKey)(types_1.AllModuleTypes.CoreEndpoint);
     }
-    checkUnsupportedModules(modules, validationErrors, yamlContentByLine) {
+    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 = [];
         Object.keys(modules)
             .filter((key) => !types_1.SUPPORTED_MODULES.map((key) => (0, utils_1.cleanKey)(key)).includes(key))
             .forEach((invalidKey) => {
             validationErrors.push({
@@ -209,10 +81,12 @@
                 level: 'error',
                 ...(0, utils_1.findPosition)(invalidKey, yamlContentByLine)
             });
         });
+        return validationErrors;
     }
-    connectModuleValidation(manifest, validationErrors) {
+    connectModuleValidation(manifest) {
+        const 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,
@@ -220,15 +94,43 @@
                 line: 1,
                 column: 0
             });
         }
+        return validationErrors;
     }
-    endpointValidations(_endpoint, validationErrors, yamlContentByLine, remotes, scopes, modules) {
+    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 = [];
         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) {
@@ -305,7 +207,58 @@
                     ...(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;

Modified:package/out/validators/modules-validators/jira/validate-full-admin-page.js

Index: package/out/validators/modules-validators/jira/validate-full-admin-page.js
===================================================================
--- package/out/validators/modules-validators/jira/validate-full-admin-page.js
+++ package/out/validators/modules-validators/jira/validate-full-admin-page.js
@@ -1,7 +1,7 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.validateFullAdminPage = void 0;
+exports.validateJiraFullAdminPage = void 0;
 const types_1 = require("../../../types");
 const text_1 = require("../../../text");
 const utils_1 = require("../../../utils");
 const validate_subpages_in_module_1 = require("./validate-subpages-in-module");
@@ -33,9 +33,9 @@
         }
     }
     return validationErrors;
 };
-const validateFullAdminPage = (modules, yamlContentByLine) => {
+const validateJiraFullAdminPage = (modules, yamlContentByLine) => {
     const validationErrors = [];
     const moduleArray = modules[jiraAdminPageType];
     const adminPageModules = moduleArray?.filter((module) => !module?.useAsGetStarted && !module?.useAsConfig);
     const getStartedModules = moduleArray?.filter((module) => module?.useAsGetStarted);
@@ -50,5 +50,5 @@
         validationErrors.push(...validateSeparateAdminPageModule('config', modules, configModules, text_1.errors.modules.singleEntryOfModuleWithConfigureParam(jiraAdminPageType), yamlContentByLine));
     }
     return validationErrors;
 };
-exports.validateFullAdminPage = validateFullAdminPage;
+exports.validateJiraFullAdminPage = validateJiraFullAdminPage;

Modified:package/out/validators/yaml-validator.js

Index: package/out/validators/yaml-validator.js
===================================================================
--- package/out/validators/yaml-validator.js
+++ package/out/validators/yaml-validator.js
@@ -4,14 +4,10 @@
 const tslib_1 = require("tslib");
 const yaml_1 = require("yaml");
 const fs_1 = tslib_1.__importDefault(require("fs"));
 const text_1 = require("../text");
-const __1 = require("..");
+const utils_1 = require("../utils");
 class YamlValidator {
-    manifestParser;
-    constructor() {
-        this.manifestParser = new __1.ManifestParser(process.env);
-    }
     async validate(manifest) {
         if (!manifest || !manifest.filePath) {
             return {
                 success: false,
@@ -19,9 +15,9 @@
             };
         }
         try {
             const content = fs_1.default.readFileSync(manifest.filePath, 'utf8');
-            const manifestContent = this.manifestParser.parseManifest(content);
+            const manifestContent = new utils_1.ManifestParserBuilder().withInterpolators().build().parseManifest(content);
             return {
                 success: true,
                 manifestObject: {
                     filePath: manifest.filePath,

Modified:package/out/schema/manifest-schema.json

too-big

Modified:package/package.json

Index: package/package.json
===================================================================
--- package/package.json
+++ package/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@forge/manifest",
-  "version": "7.5.2-next.0-experimental-10722bc",
+  "version": "7.7.0-next.13",
   "description": "Definitions and validations of the Forge manifest",
   "main": "out/index.js",
   "scripts": {
     "build": "yarn run compile",
@@ -16,22 +16,22 @@
   },
   "devDependencies": {
     "@types/jest": "^29.5.12",
     "@types/node": "14.18.63",
-    "@types/node-fetch": "^2.6.11",
     "json-schema-to-typescript": "^10.1.5",
+    "typescript": "4.8.4",
     "typescript-json-schema": "^0.62.0"
   },
   "author": "Atlassian",
   "license": "UNLICENSED",
   "dependencies": {
-    "@forge/util": "1.4.4",
+    "@forge/i18n": "0.0.1-next.12",
     "@sentry/node": "7.100.1",
     "ajv": "^8.12.0",
     "ajv-formats": "2.1.1",
     "cheerio": "^0.22.0",
     "glob": "^10.3.10",
     "lodash": "^4.17.21",
-    "node-fetch": "2.7.0",
+    "mime-types": "^2.1.35",
     "yaml": "^2.3.4"
   }
 }

Modified:package/out/scopes/shipyard-scopes.json

Index: package/out/scopes/shipyard-scopes.json
===================================================================
--- package/out/scopes/shipyard-scopes.json
+++ package/out/scopes/shipyard-scopes.json
@@ -25,8 +25,9 @@
     "delete:comment.property:jira",
     "delete:connect-confluence",
     "delete:connect-jira",
     "delete:content:confluence",
+    "delete:conversation-info:jira",
     "delete:custom-content:confluence",
     "delete:customer.detail-field:jira-service-management",
     "delete:dashboard:jira",
     "delete:dashboard.property:jira",
@@ -43,8 +44,9 @@
     "delete:field:jira",
     "delete:field.option:jira",
     "delete:filter:jira",
     "delete:filter.column:jira",
+    "delete:folder:confluence",
     "delete:group:jira",
     "delete:issue-adjustments:jira",
     "delete:issue-link-type:jira",
     "delete:issue-link:jira",
@@ -104,8 +106,10 @@
     "manage:jira-data-provider",
     "manage:jira-project",
     "manage:jira-webhook",
     "manage:servicedesk-customer",
+    "moderate:comment:confluence",
+    "moderate:core-content:confluence",
     "project-admin:connect-jira",
     "read:account",
     "read:account:brie",
     "read:airtrack-object:jira",
@@ -150,8 +154,9 @@
     "read:content.metadata:confluence",
     "read:content.permission:confluence",
     "read:content.property:confluence",
     "read:content.restriction:confluence",
+    "read:conversation-info:jira",
     "read:custom-content:confluence",
     "read:custom-field-contextual-configuration:jira",
     "read:customer:entitlement:jira-service-management",
     "read:customer:jira-service-management",
@@ -164,8 +169,10 @@
     "read:deployment:jira-software",
     "read:design:jira",
     "read:dev-info:jira",
     "read:document-info:jira",
+    "read:email-address:confluence",
+    "read:email-address:jira",
     "read:embed:confluence",
     "read:entitlement:jira-service-management",
     "read:entitlement.detail-field:jira-service-management",
     "read:entitlement.detail:jira-service-management",
@@ -183,8 +190,9 @@
     "read:field.options:jira",
     "read:filter:jira",
     "read:filter.column:jira",
     "read:filter.default-share-scope:jira",
+    "read:folder:confluence",
     "read:group:confluence",
     "read:group:jira",
     "read:incident:jira-service-management",
     "read:inlinetask:confluence",
@@ -354,8 +362,9 @@
     "write:connect-jira",
     "write:content:confluence",
     "write:content.property:confluence",
     "write:content.restriction:confluence",
+    "write:conversation-info:jira",
     "write:custom-content:confluence",
     "write:custom-field-contextual-configuration:jira",
     "write:customer:entitlement:jira-service-management",
     "write:customer:jira-service-management",
@@ -384,8 +393,9 @@
     "write:field.option:jira",
     "write:filter:jira",
     "write:filter.column:jira",
     "write:filter.default-share-scope:jira",
+    "write:folder:confluence",
     "write:group:confluence",
     "write:group:jira",
     "write:incident:jira-service-management",
     "write:inlinetask:confluence",

Modified:package/out/validators/connect-modules-validator.d.ts.map

Index: package/out/validators/connect-modules-validator.d.ts.map
===================================================================
--- package/out/validators/connect-modules-validator.d.ts.map
+++ package/out/validators/connect-modules-validator.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"connect-modules-validator.d.ts","sourceRoot":"","sources":["../../src/validators/connect-modules-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,cAAc,EAAE,wBAAwB,EAAmB,MAAM,UAAU,CAAC;AAGxG,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,qBAAa,uBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IAEnF,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;CA0ErD"}
\ No newline at end of file
+{"version":3,"file":"connect-modules-validator.d.ts","sourceRoot":"","sources":["../../src/validators/connect-modules-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,cAAc,EAAE,wBAAwB,EAAmB,MAAM,UAAU,CAAC;AAGxG,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,qBAAa,uBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IAEnF,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;CA0DrD"}
\ No newline at end of file

Modified:package/out/text/errors.d.ts.map

Index: package/out/text/errors.d.ts.map
===================================================================
--- package/out/text/errors.d.ts.map
+++ package/out/text/errors.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/text/errors.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/text/errors.ts"],"names":[],"mappings":"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"}
\ No newline at end of file

Modified:package/out/processor/full-validation-processor.d.ts.map

Index: package/out/processor/full-validation-processor.d.ts.map
===================================================================
--- package/out/processor/full-validation-processor.d.ts.map
+++ package/out/processor/full-validation-processor.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"full-validation-processor.d.ts","sourceRoot":"","sources":["../../src/processor/full-validation-processor.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAMpD,qBAAa,uBAAwB,SAAQ,2BAA2B,CAAC,cAAc,CAAC;;CAuBvF"}
\ No newline at end of file
+{"version":3,"file":"full-validation-processor.d.ts","sourceRoot":"","sources":["../../src/processor/full-validation-processor.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAMpD,qBAAa,uBAAwB,SAAQ,2BAA2B,CAAC,cAAc,CAAC;;CAwBvF"}
\ No newline at end of file

Modified:package/out/index.d.ts.map

Index: package/out/index.d.ts.map
===================================================================
--- package/out/index.d.ts.map
+++ package/out/index.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAmB,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAG9D,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,OAAO,EACL,OAAO,EACP,cAAc,EACd,GAAG,EACH,SAAS,EACT,WAAW,EACX,OAAO,EACP,KAAK,EACL,SAAS,EACT,OAAO,EACP,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,QAAQ,EACR,OAAO,EACP,MAAM,EACN,QAAQ,EACR,KAAK,EACN,MAAM,mBAAmB,CAAC;AAE3B,eAAO,MAAM,QAAQ,+BAET,MAAM,GAAG,SAAS,KAC3B,QAAQ,yBAAyB,cAAc,GAAG,mBAAmB,CAAC,CAInD,CAAC"}
\ No newline at end of file
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAmB,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAG9D,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,OAAO,EACL,OAAO,EACP,cAAc,EACd,GAAG,EACH,SAAS,EACT,WAAW,EACX,OAAO,EACP,KAAK,EACL,SAAS,EACT,OAAO,EACP,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,QAAQ,EACR,OAAO,EACP,MAAM,EACN,QAAQ,EACR,KAAK,EACL,YAAY,EACZ,wBAAwB,EACzB,MAAM,mBAAmB,CAAC;AAE3B,eAAO,MAAM,QAAQ,+BAET,MAAM,GAAG,SAAS,KAC3B,QAAQ,yBAAyB,cAAc,GAAG,mBAAmB,CAAC,CAInD,CAAC"}
\ No newline at end of file

Modified:package/out/utils/index.d.ts.map

Index: package/out/utils/index.d.ts.map
===================================================================
--- package/out/utils/index.d.ts.map
+++ package/out/utils/index.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC"}
\ No newline at end of file
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,cAAc,QAAQ,CAAC"}
\ No newline at end of file

Modified:package/out/validators/index.d.ts.map

Index: package/out/validators/index.d.ts.map
===================================================================
--- package/out/validators/index.d.ts.map
+++ package/out/validators/index.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validators/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC;AACnD,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"}
\ No newline at end of file
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validators/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC;AACnD,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC"}
\ No newline at end of file

Modified:package/out/validators/modules-validators/rovo/index.d.ts.map

Index: package/out/validators/modules-validators/rovo/index.d.ts.map
===================================================================
--- package/out/validators/modules-validators/rovo/index.d.ts.map
+++ package/out/validators/modules-validators/rovo/index.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/validators/modules-validators/rovo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAGnD,eAAO,MAAM,mBAAmB,YAAa,OAAO,sBAAsB,MAAM,EAAE,KAAG,eAAe,EAMnG,CAAC"}
\ No newline at end of file
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/validators/modules-validators/rovo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAKnD,eAAO,MAAM,mBAAmB,YAAa,OAAO,sBAAsB,MAAM,EAAE,KAAG,eAAe,EAQnG,CAAC"}
\ No newline at end of file

Modified:package/out/utils/manifest-parser.d.ts.map

Index: package/out/utils/manifest-parser.d.ts.map
===================================================================
--- package/out/utils/manifest-parser.d.ts.map
+++ package/out/utils/manifest-parser.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"manifest-parser.d.ts","sourceRoot":"","sources":["../../src/utils/manifest-parser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAKpD,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;IAMpB,aAAa;;;CAKrB;AAMD,qBAAa,cAAc;IAGb,OAAO,CAAC,QAAQ,CAAC,aAAa;IAF1C,OAAO,CAAC,gBAAgB,CAAW;gBAEN,aAAa,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAM;IAI5E,aAAa,CAAC,QAAQ,EAAE,MAAM;IAMrC,qBAAqB,aAAc,MAAM,YAAgE;IAEzG,OAAO,CAAC,0BAA0B,CAkBhC;CACH"}
\ No newline at end of file
+{"version":3,"file":"manifest-parser.d.ts","sourceRoot":"","sources":["../../src/utils/manifest-parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AAK5F,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;IAMpB,aAAa;;;CAKrB;AAKD,qBAAa,cAAc;IACb,OAAO,CAAC,oBAAoB;gBAApB,oBAAoB,EAAE,2BAA2B;IAQrE,aAAa,CAAC,QAAQ,EAAE,MAAM;IAgB9B,qBAAqB,aAAc,MAAM,YAAgE;CAC1G"}
\ No newline at end of file

Modified:package/out/validators/modules-validator.d.ts.map

Index: package/out/validators/modules-validator.d.ts.map
===================================================================
--- package/out/validators/modules-validator.d.ts.map
+++ package/out/validators/modules-validator.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"modules-validator.d.ts","sourceRoot":"","sources":["../../src/validators/modules-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EACd,wBAAwB,EAIzB,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,cAAc,EAAoB,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAY3D,qBAAa,gBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IAEzF,OAAO,CAAC,oBAAoB,CAA0C;IAEhE,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;IAgPpD,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,uBAAuB;IAiB/B,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,mBAAmB;CAsG5B"}
\ No newline at end of file
+{"version":3,"file":"modules-validator.d.ts","sourceRoot":"","sources":["../../src/validators/modules-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,cAAc,EAAE,wBAAwB,EAAsC,MAAM,UAAU,CAAC;AAGxH,OAAO,EAAkB,cAAc,EAAqC,MAAM,oBAAoB,CAAC;AACvG,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAkB3D,qBAAa,gBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IAEzF,OAAO,CAAC,oBAAoB,CAA0C;IAEhE,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;IAyDpD,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,iBAAiB;IAkBzB,OAAO,CAAC,4BAA4B;IAapC,OAAO,CAAC,uBAAuB;IAe/B,OAAO,CAAC,uBAAuB;IAiB/B,OAAO,CAAC,4BAA4B;IA0BpC,OAAO,CAAC,mBAAmB;IA2G3B,OAAO,CAAC,4BAA4B;IA2BpC,OAAO,CAAC,yBAAyB;CAkClC"}
\ No newline at end of file

Modified:package/out/validators/modules-validators/jira/validate-full-admin-page.d.ts.map

Index: package/out/validators/modules-validators/jira/validate-full-admin-page.d.ts.map
===================================================================
--- package/out/validators/modules-validators/jira/validate-full-admin-page.d.ts.map
+++ package/out/validators/modules-validators/jira/validate-full-admin-page.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"validate-full-admin-page.d.ts","sourceRoot":"","sources":["../../../../src/validators/modules-validators/jira/validate-full-admin-page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AA+CnD,eAAO,MAAM,qBAAqB,YAAa,OAAO,sBAAsB,MAAM,EAAE,KAAG,eAAe,EA4CrG,CAAC"}
\ No newline at end of file
+{"version":3,"file":"validate-full-admin-page.d.ts","sourceRoot":"","sources":["../../../../src/validators/modules-validators/jira/validate-full-admin-page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AA+CnD,eAAO,MAAM,yBAAyB,YAAa,OAAO,sBAAsB,MAAM,EAAE,KAAG,eAAe,EA4CzG,CAAC"}
\ No newline at end of file

Modified:package/out/validators/yaml-validator.d.ts.map

Index: package/out/validators/yaml-validator.d.ts.map
===================================================================
--- package/out/validators/yaml-validator.d.ts.map
+++ package/out/validators/yaml-validator.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"yaml-validator.d.ts","sourceRoot":"","sources":["../../src/validators/yaml-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAIpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG3D,qBAAa,aAAa,CAAC,CAAC,CAAE,YAAW,kBAAkB,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,CAAC,CAAC;IAC3F,OAAO,CAAC,cAAc,CAAiB;;IAIjC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC;CAiD9F"}
\ No newline at end of file
+{"version":3,"file":"yaml-validator.d.ts","sourceRoot":"","sources":["../../src/validators/yaml-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAIpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG3D,qBAAa,aAAa,CAAC,CAAC,CAAE,YAAW,kBAAkB,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,CAAC,CAAC;IACrF,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC;CAiD9F"}
\ No newline at end of file

Modified:package/CHANGELOG.md

Index: package/CHANGELOG.md
===================================================================
--- package/CHANGELOG.md
+++ package/CHANGELOG.md
@@ -1,12 +1,188 @@
 # @forge/manifest
 
-## 7.5.2-next.0-experimental-10722bc
+## 7.7.0-next.13
 
 ### Patch Changes
 
-- 01323ff: Update manifest definitions
+- 23f6675: Make `@forge/manifest` depends on `@forge/i18n` to access i18n related helper functions.
+- 27249cd: Make i18n fallback syntax confirm to industry convention. That is, `en-US: en-GB` indicate `en-GB` is fallback to `en-US`
+- 5f82d22: Update manifest definitions
+- Updated dependencies [23f6675]
+- Updated dependencies [27249cd]
+  - @forge/[email protected]
 
+## 7.7.0-next.12
+
+### Patch Changes
+
+- ce41b8c: Update manifest definitions
+
+## 7.7.0-next.11
+
+### Minor Changes
+
+- bf34881: Add translations schema to manifest schema template to enable Forge i18n support.
+  Additionally relevant validators (i.e. `translations-validator`) are added to validate the translations schema in the manifest.
+
+## 7.7.0-next.10
+
+### Patch Changes
+
+- 26f8528: Update manifest definitions
+
+## 7.7.0-next.9
+
+### Patch Changes
+
+- 13fb92c: Update forge repo with unit tests for manifest schema changes Jira, Confluence, Bitbucket
+
+## 7.7.0-next.8
+
+### Patch Changes
+
+- f40d3b5: Update manifest definitions
+
+## 7.7.0-next.7
+
+### Patch Changes
+
+- 7160171: Update manifest definitions
+
+## 7.7.0-next.6
+
+### Minor Changes
+
+- be67acb: Interpolate string resources in modules
+
+## 7.7.0-next.5
+
+### Patch Changes
+
+- b0ad6d7: Update manifest definitions
+
+## 7.7.0-next.4
+
+### Minor Changes
+
+- c341349: Show warning if action doesn't have name attribute
+
+## 7.7.0-next.3
+
+### Patch Changes
+
+- 10f4545: Update package readme to include instruction on how to update schema in the package
+
+## 7.7.0-next.2
+
+### Minor Changes
+
+- c113f86: Show warning if action is not referenced by any agent
+- 9a546fd: Lint unique module key across Connect and Forge modules
+
+### Patch Changes
+
+- c6377ba: Update unit test in manifest validator
+- bf0fab6: Update manifest definitions
+
+## 7.6.1-next.1
+
+### Patch Changes
+
+- c74ca63: Add translations section in manifest schema for Forge i18n Support (EAP)
+
+## 7.6.1-next.0
+
+### Patch Changes
+
+- b90e809: Update manifest definitions
+- 313b8e1: Update manifest definitions
+
+## 7.6.0
+
+### Minor Changes
+
+- 90f621b: Revert cheerio upgrade
+
+### Patch Changes
+
+- 114989d: remove unused dependencies: @forge/util and node-fetch
+- c0e7e2f: Add test to validate if the i18n props in manifest json is configured properly
+- 562a25c: Allow updating manifest schema resources with app-host-artifacts changes on staging
+- 09d005e: Fix failing unit tests in pipeline
+- 3f5f84e: Update manifest definitions
+- 03eba4f: Update manifest definitions
+- 9384afe: Update manifest definitions
+
+## 7.6.0-next.6
+
+### Minor Changes
+
+- 90f621b: Revert cheerio upgrade
+
+## 7.6.0-next.5
+
+### Patch Changes
+
+- 114989d: remove unused dependencies: @forge/util and node-fetch
+
+## 7.6.0-next.4
+
+### Patch Changes
+
+- 3f5f84e: Update manifest definitions
+
+## 7.6.0-next.3
+
+### Minor Changes
+
+- 4117f97: Bump cheerio from version 0.22 to version 1.0
+
+## 7.5.4-next.2
+
+### Patch Changes
+
+- c0e7e2f: Add test to validate if the i18n props in manifest json is configured properly
+- 03eba4f: Update manifest definitions
+
+## 7.5.4-next.1
+
+### Patch Changes
+
+- 09d005e: Fix failing unit tests in pipeline
+- 9384afe: Update manifest definitions
+
+## 7.5.4-next.0
+
+### Patch Changes
+
+- 562a25c: Allow updating manifest schema resources with app-host-artifacts changes on staging
+
+## 7.5.3
+
+### Patch Changes
+
+- 9985768: Update manifest definitions
+- f32f860: Update manifest definitions
+
+## 7.5.3-next.1
+
+### Patch Changes
+
+- f32f860: Update manifest definitions
+
+## 7.5.3-next.0
+
+### Patch Changes
+
+- 9985768: Update manifest definitions
+
+## 7.5.2
+
+### Patch Changes
+
+- 0261f2b: Update manifest definitions
+
 ## 7.5.2-next.0
 
 ### Patch Changes

Modified:package/README.md

Index: package/README.md
===================================================================
--- package/README.md
+++ package/README.md
@@ -34,4 +34,7 @@
   success: boolean;
   errors?: ValidationError[];
 }
 ```
+
+## Updating Manifest schemas
+The schemas in this package are automatically updated from Shipyard daily. Any manual changes to these files will be reverted. Please raise a PR in [app-host-artifacts](https://bitbucket.org/atlassian/app-host-artifacts/src/master/) instead.
\ No newline at end of file

Modified:package/out/text/errors.d.ts

Index: package/out/text/errors.d.ts
===================================================================
--- package/out/text/errors.d.ts
+++ package/out/text/errors.d.ts
@@ -1,4 +1,5 @@
+import { type ForgeSupportedLocaleCode } from '../schema/manifest';
 import { AllModuleTypes } from '../types';
 export declare const errors: {
     invalidManifest: (reason: string) => string;
     missingManifest: () => string;
@@ -9,8 +10,12 @@
         deprecatedValue: (section: string, field: string, additionalInfo?: string) => string;
         additionalProperties: (additionalProperty: string) => string;
         notAllowed: (props: string[] | undefined) => string;
         missingEnvironmentVariable: (variable: string) => string;
+        errorReadingResourceFile: (variable: string, errorMessage: string) => string;
+        resourceNotFound: (variable: string) => string;
+        resourcePathNotDefined: (variable: string) => string;
+        resourceFileNotSupported: (variable: string) => string;
     };
     permissions: {
         invalidPermission: (element: string, value: string) => string;
         missingPermissionFromScope: (scope: string, event: string) => string;
@@ -19,11 +24,9 @@
         deprecatedPermission: (element: string, value: string[]) => string;
     };
     connectModules: {
         invalidConnectModule: (module: string) => string;
-        missingConnectModule: () => string;
-        duplicateKeyFound: (key: string) => string;
-        duplicatateLifecycleFound: (module: string) => string;
+        duplicateLifecycleFound: (module: string) => string;
     };
     modules: {
         invalidModule: (module: string) => string;
         missingModule: () => string;
@@ -109,8 +112,10 @@
             missingModuleRemoteStorageInScopeEUD: (key: string) => string;
         };
         rovo: {
             incorrectAgentActionReference: (module: string, moduleKey: string) => string;
+            unreferencedAction: (action: string) => string;
+            undefinedActionName: (action: string) => string;
         };
     };
     resources: {
         missingResource: (folder: string, key: string) => string;
@@ -158,8 +163,18 @@
                 missing: (glob: string) => string;
             };
         };
     };
+    translations: {
+        missingTranslationsJsonFile: (languageLocaleCode: ForgeSupportedLocaleCode) => string;
+        duplicateFallbackConfig: (languageLocaleCode: ForgeSupportedLocaleCode) => string;
+        invalidLanguageFile: (languageLocaleCode: ForgeSupportedLocaleCode, path: string) => string;
+        duplicateResourceKey: (languageLocaleCode: ForgeSupportedLocaleCode) => string;
+        i18nKeyNotFound: (keyName: string) => string;
+        missingTranslationsPropertyError: string;
+        internalI18nPropertyKeyFound: (propertyKey: string, moduleKey: string) => string;
+        i18nValueValidationError: (keyName: string, languageLocaleCode: ForgeSupportedLocaleCode, errorMsg: string) => string;
+    };
 };
 export declare enum References {
     MissingManifest = "manifest-file-required",
     InvalidManifest = "valid-yaml-required",
@@ -167,9 +182,8 @@
     Permissions = "valid-permissions-required",
     MissingScopes = "permission-scope-required",
     Modules = "valid-module-required",
     ConnectModules = "valid-connect-module-required",
-    DuplicateModuleKeys = "duplicate-module-keys",
     Resources = "valid-resource-required",
     Providers = "valid-provider-required",
     Deprecated = "deprecated-property",
     App = "valid-app-config-required",

Modified:package/out/index.d.ts

Index: package/out/index.d.ts
===================================================================
--- package/out/index.d.ts
+++ package/out/index.d.ts
@@ -7,7 +7,7 @@
 export * from './text';
 export * from './types';
 export * from './utils';
 export * from './validators';
-export { Modules, ManifestSchema, App, Resources, Permissions, Remotes, Fetch, Providers, Backend, Frames, Navigation, Images, Media, Scripts1, Styles1, Scopes, Content1, Fonts } from './schema/manifest';
+export { Modules, ManifestSchema, App, Resources, Permissions, Remotes, Fetch, Providers, Backend, Frames, Navigation, Images, Media, Scripts1, Styles1, Scopes, Content1, Fonts, Translations, ForgeSupportedLocaleCode } from './schema/manifest';
 export declare const validate: (basic?: boolean, manifest?: string | undefined) => Promise<ManifestValidationResult<ManifestSchema | BasicManifestSchema>>;
 //# sourceMappingURL=index.d.ts.map
\ No newline at end of file

Modified:package/out/utils/index.d.ts

Index: package/out/utils/index.d.ts
===================================================================
--- package/out/utils/index.d.ts
+++ package/out/utils/index.d.ts
@@ -1,6 +1,8 @@
 export * from './get-all-modules';
 export * from './line-finder';
 export * from './module-key-cleaner';
 export * from './module-references';
-export * from './manifest-parser';
+export * from './manifest-parser-builder';
+export type { ManifestParser } from './manifest-parser';
+export * from './i18n';
 //# sourceMappingURL=index.d.ts.map
\ No newline at end of file

Modified:package/out/validators/index.d.ts

Index: package/out/validators/index.d.ts
===================================================================
--- package/out/validators/index.d.ts
+++ package/out/validators/index.d.ts
@@ -13,5 +13,6 @@
 export * from './connect-authentication-validator';
 export * from './entity-property-validator';
 export * from './snapshot-validator';
 export * from './package-validator';
+export * from './translations-validator';
 //# sourceMappingURL=index.d.ts.map
\ No newline at end of file

Modified:package/out/utils/manifest-parser.d.ts

Index: package/out/utils/manifest-parser.d.ts
===================================================================
--- package/out/utils/manifest-parser.d.ts
+++ package/out/utils/manifest-parser.d.ts
@@ -1,16 +1,14 @@
-import { ManifestSchema } from '../schema/manifest';
+import { ManifestInterpolatorManager } from '../interpolator/manifest-interpolator-manager';
 export declare class ManifestParserError extends Error {
     constructor(message: string);
     getAttributes(): {
         isUserError: boolean;
     };
 }
 export declare class ManifestParser {
-    private readonly envVarsRecord;
-    private envVarsToReplace;
-    constructor(envVarsRecord?: Record<string, string | undefined>);
-    parseManifest(manifest: string): ManifestSchema;
+    private manifestInterpolator;
+    constructor(manifestInterpolator: ManifestInterpolatorManager);
+    parseManifest(manifest: string): import("../index").ManifestSchema;
     parseManifestAsString: (manifest: string) => string;
-    private environmentVariableReviver;
 }
 //# sourceMappingURL=manifest-parser.d.ts.map
\ No newline at end of file

Modified:package/out/schema/manifest.d.ts

too-big

Modified:package/out/validators/modules-validator.d.ts

Index: package/out/validators/modules-validator.d.ts
===================================================================
--- package/out/validators/modules-validator.d.ts
+++ package/out/validators/modules-validator.d.ts
@@ -4,9 +4,14 @@
 export declare class ModulesValidator implements ValidatorInterface<ManifestObject<ManifestSchema> | undefined, ManifestSchema> {
     private functionHandlerRegex;
     validate(manifest: ManifestObject<ManifestSchema> | undefined): Promise<ManifestValidationResult<ManifestSchema>>;
     private isNotFunctionOrEndpoint;
+    private functionKeyLength;
+    private minimumModuleCountValidation;
     private checkUnsupportedModules;
     private connectModuleValidation;
+    private functionKeyDefinedValidation;
     private endpointValidations;
+    private duplicateModuleKeyValidation;
+    private functionHandlerValidation;
 }
 //# sourceMappingURL=modules-validator.d.ts.map
\ No newline at end of file

Modified:package/out/validators/modules-validators/jira/validate-full-admin-page.d.ts

Index: package/out/validators/modules-validators/jira/validate-full-admin-page.d.ts
===================================================================
--- package/out/validators/modules-validators/jira/validate-full-admin-page.d.ts
+++ package/out/validators/modules-validators/jira/validate-full-admin-page.d.ts
@@ -1,4 +1,4 @@
 import { ValidationError } from '../../../types';
 import { Modules } from '../../../schema/manifest';
-export declare const validateFullAdminPage: (modules: Modules, yamlContentByLine?: string[]) => ValidationError[];
+export declare const validateJiraFullAdminPage: (modules: Modules, yamlContentByLine?: string[]) => ValidationError[];
 //# sourceMappingURL=validate-full-admin-page.d.ts.map
\ No newline at end of file

Modified:package/out/validators/yaml-validator.d.ts

Index: package/out/validators/yaml-validator.d.ts
===================================================================
--- package/out/validators/yaml-validator.d.ts
+++ package/out/validators/yaml-validator.d.ts
@@ -1,8 +1,6 @@
 import { ManifestObject, ManifestValidationResult } from '../types';
 import { ValidatorInterface } from './validator-interface';
 export declare class YamlValidator<T> implements ValidatorInterface<ManifestObject<T> | undefined, T> {
-    private manifestParser;
-    constructor();
     validate(manifest: ManifestObject<T> | undefined): Promise<ManifestValidationResult<T>>;
 }
 //# sourceMappingURL=yaml-validator.d.ts.map
\ No newline at end of file