npm package diff

Package: @forge/cli-shared

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

Modified: package/out/graphql/graphql-types.js

Large diffs are not rendered by default.

Modified: 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
+};

Modified: package/package.json

Index: package/package.json
===================================================================
--- package/package.json
+++ package/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@forge/cli-shared",
-  "version": "6.6.1-next.8",
+  "version": "6.6.1-next.9",
   "description": "Common functionality for Forge CLI",
   "author": "Atlassian",
   "license": "SEE LICENSE IN LICENSE.txt",
   "main": "out/index.js",

Modified: package/out/graphql/graphql-types.d.ts.map

Large diffs are not rendered by default.

Modified: package/out/service/supported-products-service.d.ts.map

Index: package/out/service/supported-products-service.d.ts.map
===================================================================
--- package/out/service/supported-products-service.d.ts.map
+++ package/out/service/supported-products-service.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"supported-products-service.d.ts","sourceRoot":"","sources":["../../src/service/supported-products-service.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAuC,MAAM,WAAW,CAAC;AAgCpF,QAAA,MAAM,sBAAsB,oFAA8D,CAAC;AAO3F,eAAO,MAAM,iBAAiB;;;;;CAK7B,CAAC;AAGF,oBAAY,gBAAgB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,GAAG,kBAAkB,CAAC;AAa5F,qBAAa,wBAAwB;IAGvB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAF3C,OAAO,CAAC,yBAAyB,CAAsC;gBAE1C,cAAc,EAAE,cAAc;YAE7C,wBAAwB;YAYxB,uBAAuB;YAUvB,+BAA+B;IAS7C,OAAO,CAAC,wBAAwB;IAWnB,oBAAoB,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAe7E,6BAA6B;IAO9B,wBAAwB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAW7E,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrD,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC;CAmB/F;AAID,eAAO,MAAM,kBAAkB,YAAa,MAAM,KAAG,OAEpD,CAAC"}
\ No newline at end of file
+{"version":3,"file":"supported-products-service.d.ts","sourceRoot":"","sources":["../../src/service/supported-products-service.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAuC,MAAM,WAAW,CAAC;AAKpF,oBAAY,gBAAgB,GAAG,MAAM,GAAG,YAAY,GAAG,SAAS,GAAG,gBAAgB,GAAG,OAAO,GAAG,WAAW,CAAC;AA8C5G,aAAK,WAAW,GAAG,OAAO,GAAG,WAAW,CAAC;AAEzC,oBAAY,iBAAiB,GAAG;IAC9B,IAAI,EAAE,gBAAgB,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,CAAC,EAAE;QACR,2BAA2B,CAAC,EAAE,OAAO,CAAC;QACtC,sBAAsB,CAAC,EAAE,CAAC,cAAc,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAC/E,CAAC;CACH,CAAC;AAEF,cAAM,qBAAqB;IAEhB,WAAW,EAAE,gBAAgB;IAC7B,WAAW,EAAE,WAAW;IACxB,2BAA2B,EAAE,OAAO;gBAFpC,WAAW,EAAE,gBAAgB,EAC7B,WAAW,EAAE,WAAW,EACxB,2BAA2B,EAAE,OAAO;CAE9C;AAED,iBAAe,sBAAsB,CAAC,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAgBtG;AAED,qBAAa,wBAAwB;IAKvB,OAAO,CAAC,iBAAiB,CAAC;gBAAlB,iBAAiB,CAAC,qCAAyB;IAElD,+BAA+B,CAAC,cAAc,EAAE,cAAc;IAS3E,OAAO,CAAC,yBAAyB;IAS1B,oBAAoB,IAAI,gBAAgB,EAAE;IAI1C,mCAAmC,CAAC,gBAAgB,EAAE,MAAM,EAAE,GAAG,gBAAgB,EAAE;IAOnF,wBAAwB,CAAC,gBAAgB,EAAE,MAAM,GAAG,gBAAgB;IAWpE,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAO5C,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,SAAS,GAAG,GAAG;CAqBhF;AAID,eAAO,MAAM,kBAAkB,YAAa,MAAM,KAAG,OAEpD,CAAC;AAGF,eAAO,MAAM,iBAAiB;;CAE7B,CAAC"}
\ No newline at end of file

Modified: package/CHANGELOG.md

Large diffs are not rendered by default.

Modified: package/out/graphql/graphql-types.d.ts

Large diffs are not rendered by default.

Modified: package/out/service/supported-products-service.d.ts

Index: package/out/service/supported-products-service.d.ts
===================================================================
--- package/out/service/supported-products-service.d.ts
+++ package/out/service/supported-products-service.d.ts
@@ -1,29 +1,38 @@
 /// <reference types="node" />
 import { StatsigService } from './statsig-service';
 import { URL } from 'url';
 import { ProductDisplayName } from '../shared';
-declare const SUPPORTED_PRODUCTS_ALL: readonly ["Jira", "Confluence", "Compass", "Teamwork Graph", "Atlas", "Bitbucket"];
-export declare const TEST_ONLY_EXPORTS: {
-    SITED_PRODUCTS_ALL: readonly ["Jira", "Confluence", "Compass", "Teamwork Graph", "Atlas"];
-    SITED_PRODUCTS_ALWAYS_ENABLED: readonly ["Jira", "Confluence", "Compass"];
-    WORKSPACE_PRODUCTS_ALL: readonly ["Bitbucket"];
-    SUPPORTED_PRODUCTS_ALWAYS_ENABLED: readonly ["Jira", "Confluence", "Compass", "Bitbucket"];
+export declare type SupportedProduct = 'Jira' | 'Confluence' | 'Compass' | 'Teamwork Graph' | 'Atlas' | 'Bitbucket';
+declare type ProductType = 'sited' | 'workspace';
+export declare type ProductDefinition = {
+    name: SupportedProduct;
+    productType: ProductType;
+    special?: {
+        supportedByCrossProductApps?: boolean;
+        isEnabledByFeatureGate?: (statsigService: StatsigService) => Promise<boolean>;
+    };
 };
-export declare type SupportedProduct = (typeof SUPPORTED_PRODUCTS_ALL)[number] & ProductDisplayName;
+declare class SupportedProductEntry {
+    productName: SupportedProduct;
+    productType: ProductType;
+    supportedByCrossProductApps: boolean;
+    constructor(productName: SupportedProduct, productType: ProductType, supportedByCrossProductApps: boolean);
+}
+declare function resolveEnabledProducts(statsigService: StatsigService): Promise<SupportedProductEntry[]>;
 export declare class SupportedProductsService {
-    private readonly statsigService;
-    private featureGatedProductsCache;
-    constructor(statsigService: StatsigService);
-    private buildFeatureGatedProduct;
-    private getFeatureGatedProducts;
-    private getProductsEnabledByFeatureGate;
-    private ensureProductDisplayName;
-    getSupportedProducts(requiredProducts?: string[]): Promise<SupportedProduct[]>;
-    private getSupportedWorkspaceProducts;
-    validateSupportedProduct(productNameInput: string): Promise<SupportedProduct>;
-    isWorkspaceProduct(product: string): Promise<boolean>;
-    validateSite(site: string, product: ProductDisplayName | undefined): Promise<URL>;
+    private supportedProducts?;
+    constructor(supportedProducts?: SupportedProductEntry[] | undefined);
+    initializeWithSupportedProducts(statsigService: StatsigService): Promise<void>;
+    private getSupportedProductsNames;
+    getSupportedProducts(): SupportedProduct[];
+    getSupportedSecondaryProductsForXPA(requiredProducts: string[]): SupportedProduct[];
+    validateSupportedProduct(productNameInput: string): SupportedProduct;
+    isWorkspaceProduct(product: string): boolean;
+    validateSite(site: string, product: ProductDisplayName | undefined): URL;
 }
 export declare const isBitbucketProduct: (product: string) => boolean;
+export declare const TEST_ONLY_EXPORTS: {
+    resolveEnabledProducts: typeof resolveEnabledProducts;
+};
 export {};
 //# sourceMappingURL=supported-products-service.d.ts.map
\ No newline at end of file