npm package diff

Package: @forge/cli-shared

Versions: 6.6.1-next.8 - 6.6.1-next.9

File: package/out/service/supported-products-service.js

Index: package/out/service/supported-products-service.js
===================================================================
--- package/out/service/supported-products-service.js
+++ package/out/service/supported-products-service.js
@@ -1,107 +1,117 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.isBitbucketProduct = exports.SupportedProductsService = exports.TEST_ONLY_EXPORTS = void 0;
+exports.TEST_ONLY_EXPORTS = exports.isBitbucketProduct = exports.SupportedProductsService = void 0;
 const url_1 = require("url");
 const shared_1 = require("../shared");
 const ui_1 = require("../ui");
-const SITED_PRODUCTS_ALWAYS_ENABLED = ['Jira', 'Confluence', 'Compass'];
-const SITED_PRODUCTS_UNDER_FEATURE_FLAG = ['Teamwork Graph', 'Atlas'];
-const WORKSPACE_PRODUCTS_ALWAYS_ENABLED = ['Bitbucket'];
-const WORKSPACE_PRODUCTS_UNDER_FEATURE_FLAG = [];
-const SITED_PRODUCTS_ALL = [...SITED_PRODUCTS_ALWAYS_ENABLED, ...SITED_PRODUCTS_UNDER_FEATURE_FLAG];
-const WORKSPACE_PRODUCTS_ALL = [
-    ...WORKSPACE_PRODUCTS_ALWAYS_ENABLED,
-    ...WORKSPACE_PRODUCTS_UNDER_FEATURE_FLAG
+const SUPPORTED_PRODUCTS_DEFINITIONS = [
+    {
+        name: 'Jira',
+        productType: 'sited',
+        special: {
+            supportedByCrossProductApps: true
+        }
+    },
+    {
+        name: 'Confluence',
+        productType: 'sited',
+        special: {
+            supportedByCrossProductApps: true
+        }
+    },
+    {
+        name: 'Compass',
+        productType: 'sited',
+        special: {
+            supportedByCrossProductApps: true
+        }
+    },
+    {
+        name: 'Teamwork Graph',
+        productType: 'sited',
+        special: {
+            isEnabledByFeatureGate: async (statsigService) => statsigService.isTeamworkGraphProductSupported()
+        }
+    },
+    {
+        name: 'Atlas',
+        productType: 'sited',
+        special: {
+            isEnabledByFeatureGate: async (statsigService) => statsigService.isAtlasProductSupported()
+        }
+    },
+    {
+        name: 'Bitbucket',
+        productType: 'workspace'
+    }
 ];
-const SUPPORTED_PRODUCTS_ALWAYS_ENABLED = [
-    ...SITED_PRODUCTS_ALWAYS_ENABLED,
-    ...WORKSPACE_PRODUCTS_ALWAYS_ENABLED
-];
-const SUPPORTED_PRODUCTS_ALL = [...SITED_PRODUCTS_ALL, ...WORKSPACE_PRODUCTS_ALL];
-exports.TEST_ONLY_EXPORTS = {
-    SITED_PRODUCTS_ALL,
-    SITED_PRODUCTS_ALWAYS_ENABLED,
-    WORKSPACE_PRODUCTS_ALL,
-    SUPPORTED_PRODUCTS_ALWAYS_ENABLED
-};
-function arrayContains(arr, e) {
-    return arr.includes(e);
+class SupportedProductEntry {
+    productName;
+    productType;
+    supportedByCrossProductApps;
+    constructor(productName, productType, supportedByCrossProductApps) {
+        this.productName = productName;
+        this.productType = productType;
+        this.supportedByCrossProductApps = supportedByCrossProductApps;
+    }
 }
+async function resolveEnabledProducts(statsigService) {
+    const productDefinitionWithIsEnabledResolved = await Promise.all(SUPPORTED_PRODUCTS_DEFINITIONS.map(async (pd) => {
+        const enabledByFeatureGateResolver = pd.special?.isEnabledByFeatureGate;
+        const isEnabled = enabledByFeatureGateResolver ? await enabledByFeatureGateResolver(statsigService) : true;
+        return { pd, isEnabled };
+    }));
+    const definitionsForEnabledProducts = productDefinitionWithIsEnabledResolved
+        .filter(({ isEnabled }) => isEnabled)
+        .map(({ pd }) => pd);
+    return definitionsForEnabledProducts.map((pd) => {
+        return new SupportedProductEntry(pd.name, pd.productType, pd.special?.supportedByCrossProductApps ?? false);
+    });
+}
 class SupportedProductsService {
-    statsigService;
-    featureGatedProductsCache = null;
-    constructor(statsigService) {
-        this.statsigService = statsigService;
+    supportedProducts;
+    constructor(supportedProducts) {
+        this.supportedProducts = supportedProducts;
     }
-    async buildFeatureGatedProduct(productName, productType, isEnabledPromise) {
-        return {
-            productName,
-            productType,
-            isEnabled: await isEnabledPromise
-        };
-    }
-    async getFeatureGatedProducts() {
-        if (this.featureGatedProductsCache === null) {
-            this.featureGatedProductsCache = await Promise.all([
-                this.buildFeatureGatedProduct('Teamwork Graph', 'sited', this.statsigService.isTeamworkGraphProductSupported()),
-                this.buildFeatureGatedProduct('Atlas', 'sited', this.statsigService.isAtlasProductSupported())
-            ]);
+    async initializeWithSupportedProducts(statsigService) {
+        if (this.supportedProducts) {
+            throw new Error('SupportedProductsService is already initialized');
         }
-        return this.featureGatedProductsCache;
+        this.supportedProducts = await resolveEnabledProducts(statsigService);
     }
-    async getProductsEnabledByFeatureGate(filter = () => true) {
-        const featureGatedProducts = await this.getFeatureGatedProducts();
-        return featureGatedProducts
-            .filter((gatedProductInfo) => gatedProductInfo.isEnabled && filter(gatedProductInfo))
-            .map((product) => product.productName);
-    }
-    ensureProductDisplayName(product) {
-        if (arrayContains(SUPPORTED_PRODUCTS_ALL, product)) {
-            return product;
+    getSupportedProductsNames(filter = () => true) {
+        if (!this.supportedProducts) {
+            throw new Error('SupportedProductsService is not initialized, are you calling it from some constructor?');
         }
-        else {
-            return (0, shared_1.productDisplayName)(product);
-        }
+        return this.supportedProducts.filter((p) => filter(p)).map((p) => p.productName);
     }
-    async getSupportedProducts(requiredProducts) {
-        if (requiredProducts?.length) {
-            const upperCaseRequiredProducts = requiredProducts.map((product) => product.toUpperCase());
-            return [
-                ...SITED_PRODUCTS_ALWAYS_ENABLED.filter((product) => !upperCaseRequiredProducts.includes(product.toUpperCase()))
-            ];
-        }
-        return [
-            ...SITED_PRODUCTS_ALWAYS_ENABLED,
-            ...WORKSPACE_PRODUCTS_ALWAYS_ENABLED,
-            ...(await this.getProductsEnabledByFeatureGate())
-        ];
+    getSupportedProducts() {
+        return this.getSupportedProductsNames();
     }
-    async getSupportedWorkspaceProducts() {
-        return [
-            ...WORKSPACE_PRODUCTS_ALWAYS_ENABLED,
-            ...(await this.getProductsEnabledByFeatureGate((product) => product.productType == 'workspace'))
-        ];
+    getSupportedSecondaryProductsForXPA(requiredProducts) {
+        const requiredProductsNames = requiredProducts.map((p) => (0, shared_1.productDisplayName)(p));
+        return this.getSupportedProductsNames((p) => p.supportedByCrossProductApps && !requiredProductsNames.includes(p.productName));
     }
-    async validateSupportedProduct(productNameInput) {
+    validateSupportedProduct(productNameInput) {
         const productName = (0, shared_1.productDisplayName)(productNameInput);
-        const supportedProducts = await this.getSupportedProducts();
-        if (arrayContains(supportedProducts, productName)) {
+        const supportedProducts = this.getSupportedProducts();
+        if (supportedProducts.includes(productName)) {
             return productName;
         }
         else {
             throw new shared_1.ValidationError(ui_1.Text.error.invalidProduct);
         }
     }
-    async isWorkspaceProduct(product) {
-        return arrayContains(await this.getSupportedWorkspaceProducts(), this.ensureProductDisplayName(product));
+    isWorkspaceProduct(product) {
+        return this.getSupportedProductsNames((p) => p.productType === 'workspace').includes((0, shared_1.productDisplayName)(product));
     }
-    async validateSite(site, product) {
+    validateSite(site, product) {
         const trySites = [site, `https://${site}`];
         for (const trySite of trySites) {
             try {
                 const urlObj = new url_1.URL(trySite);
-                if (product && (await this.isWorkspaceProduct(product))) {
+                if (product && this.isWorkspaceProduct(product)) {
                     return urlObj;
                 }
                 urlObj.pathname = '/';
                 return urlObj;
@@ -116,4 +126,7 @@
 const isBitbucketProduct = (product) => {
     return (0, shared_1.productDisplayName)(product) === 'Bitbucket';
 };
 exports.isBitbucketProduct = isBitbucketProduct;
+exports.TEST_ONLY_EXPORTS = {
+    resolveEnabledProducts
+};