@forge/cli

13.3.0-next.12-experimental-4b981ef-experimental-5b8eb3c13.3.0-next.25
out/module-add/manifest-merger.js
~out/module-add/manifest-merger.jsModified
+39−18
Index: package/out/module-add/manifest-merger.js
===================================================================
--- package/out/module-add/manifest-merger.js
+++ package/out/module-add/manifest-merger.js
@@ -8,9 +8,10 @@
 const path_1 = tslib_1.__importDefault(require("path"));
 const yaml_1 = tslib_1.__importStar(require("yaml"));
 const diff_1 = require("diff");
 const cli_shared_1 = require("@forge/cli-shared");
-const COMPATIBILITY_PRODUCTS = new Set(['jira', 'confluence', 'compass']);
+const COMPATIBILITY_PRODUCTS = new Set(['jira', 'confluence']);
+const GLOBAL_COMPATIBILITY_PRODUCTS = ['jira', 'confluence'];
 const ROOT_SECTION_ORDER = ['modules', 'resources', 'permissions', 'app'];
 const RESOURCE_FIELD_ORDER = ['key', 'path', 'entry'];
 const ROOT_INSERT_OPTIONS = { orderedKeys: ROOT_SECTION_ORDER };
 const MODULE_INSERT_OPTIONS = { appendBeforeKey: 'function' };
@@ -271,35 +272,55 @@
     return value !== null && typeof value === 'object' && !Array.isArray(value);
 }
 function applyCrossProductCompatibility(existingManifest, manifestFragment, template, warnings) {
     const newProduct = template.product;
-    if (!newProduct || !COMPATIBILITY_PRODUCTS.has(newProduct))
-        return;
     const existingProducts = collectProductPrefixes(existingManifest.modules);
-    existingProducts.delete(newProduct);
-    const compatProducts = [...existingProducts].filter((p) => COMPATIBILITY_PRODUCTS.has(p));
-    if (compatProducts.length === 0)
-        return;
     const existingApp = isObject(existingManifest.app) ? existingManifest.app : undefined;
     const existingCompatibility = existingApp && isObject(existingApp.compatibility) ? existingApp.compatibility : {};
     const fragmentApp = isObject(manifestFragment.app) ? manifestFragment.app : {};
     const fragmentCompatibility = isObject(fragmentApp.compatibility) ? fragmentApp.compatibility : {};
-    const hasRequiredContext = Object.values(existingCompatibility).some((value) => isObject(value) && value.required === true);
     const nextCompatibility = { ...fragmentCompatibility };
-    let primaryAssigned = hasRequiredContext;
-    for (const existingProduct of compatProducts) {
-        if (isObject(existingCompatibility[existingProduct]) || isObject(nextCompatibility[existingProduct]))
-            continue;
-        nextCompatibility[existingProduct] = { required: !primaryAssigned };
-        primaryAssigned = true;
+    const entriesToAdd = [];
+    let warningMessage;
+    if (newProduct === 'global') {
+        const requiredProduct = existingProducts.has('jira') || !existingProducts.has('confluence') ? 'jira' : 'confluence';
+        for (const product of GLOBAL_COMPATIBILITY_PRODUCTS) {
+            if (isObject(existingCompatibility[product]) || isObject(nextCompatibility[product])) {
+                continue;
+            }
+            entriesToAdd.push({ product, required: product === requiredProduct });
+        }
+        warningMessage = cli_shared_1.Text.module.add.warnAddedGlobalAppCompatibility(requiredProduct);
     }
-    if (!isObject(existingCompatibility[newProduct]) && !isObject(nextCompatibility[newProduct])) {
-        nextCompatibility[newProduct] = { required: false };
+    else {
+        if (!newProduct || !COMPATIBILITY_PRODUCTS.has(newProduct))
+            return;
+        existingProducts.delete(newProduct);
+        const compatProducts = [...existingProducts].filter((product) => COMPATIBILITY_PRODUCTS.has(product));
+        if (compatProducts.length === 0)
+            return;
+        const hasRequiredContext = Object.values(existingCompatibility).some((value) => isObject(value) && value.required === true);
+        let primaryAssigned = hasRequiredContext;
+        for (const existingProduct of compatProducts) {
+            if (isObject(existingCompatibility[existingProduct]) || isObject(nextCompatibility[existingProduct])) {
+                continue;
+            }
+            entriesToAdd.push({ product: existingProduct, required: !primaryAssigned });
+            primaryAssigned = true;
+        }
+        if (!isObject(existingCompatibility[newProduct]) && !isObject(nextCompatibility[newProduct])) {
+            entriesToAdd.push({ product: newProduct, required: false });
+        }
+        warningMessage = cli_shared_1.Text.module.add.warnAddedAppCompatibility(compatProducts, newProduct);
     }
-    if (Object.keys(nextCompatibility).length === Object.keys(fragmentCompatibility).length)
+    if (entriesToAdd.length === 0 || !warningMessage) {
         return;
+    }
+    for (const { product, required } of entriesToAdd) {
+        nextCompatibility[product] = { required };
+    }
     manifestFragment.app = { ...fragmentApp, compatibility: nextCompatibility };
-    warnings.push(cli_shared_1.Text.module.add.warnAddedAppCompatibility(compatProducts, newProduct));
+    warnings.push(warningMessage);
 }
 function collectProductPrefixes(modules) {
     const prefixes = new Set();
     if (!isObject(modules))