@forge/cli-shared 6.6.1-next.7 → 6.6.1-next.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,106 +1,116 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isBitbucketProduct = exports.SupportedProductsService = exports.TEST_ONLY_EXPORTS = void 0;
3
+ exports.TEST_ONLY_EXPORTS = exports.isBitbucketProduct = exports.SupportedProductsService = void 0;
4
4
  const url_1 = require("url");
5
5
  const shared_1 = require("../shared");
6
6
  const ui_1 = require("../ui");
7
- const SITED_PRODUCTS_ALWAYS_ENABLED = ['Jira', 'Confluence', 'Compass'];
8
- const SITED_PRODUCTS_UNDER_FEATURE_FLAG = ['Teamwork Graph', 'Atlas'];
9
- const WORKSPACE_PRODUCTS_ALWAYS_ENABLED = ['Bitbucket'];
10
- const WORKSPACE_PRODUCTS_UNDER_FEATURE_FLAG = [];
11
- const SITED_PRODUCTS_ALL = [...SITED_PRODUCTS_ALWAYS_ENABLED, ...SITED_PRODUCTS_UNDER_FEATURE_FLAG];
12
- const WORKSPACE_PRODUCTS_ALL = [
13
- ...WORKSPACE_PRODUCTS_ALWAYS_ENABLED,
14
- ...WORKSPACE_PRODUCTS_UNDER_FEATURE_FLAG
15
- ];
16
- const SUPPORTED_PRODUCTS_ALWAYS_ENABLED = [
17
- ...SITED_PRODUCTS_ALWAYS_ENABLED,
18
- ...WORKSPACE_PRODUCTS_ALWAYS_ENABLED
7
+ const SUPPORTED_PRODUCTS_DEFINITIONS = [
8
+ {
9
+ name: 'Jira',
10
+ productType: 'sited',
11
+ special: {
12
+ supportedByCrossProductApps: true
13
+ }
14
+ },
15
+ {
16
+ name: 'Confluence',
17
+ productType: 'sited',
18
+ special: {
19
+ supportedByCrossProductApps: true
20
+ }
21
+ },
22
+ {
23
+ name: 'Compass',
24
+ productType: 'sited',
25
+ special: {
26
+ supportedByCrossProductApps: true
27
+ }
28
+ },
29
+ {
30
+ name: 'Teamwork Graph',
31
+ productType: 'sited',
32
+ special: {
33
+ isEnabledByFeatureGate: async (statsigService) => statsigService.isTeamworkGraphProductSupported()
34
+ }
35
+ },
36
+ {
37
+ name: 'Atlas',
38
+ productType: 'sited',
39
+ special: {
40
+ isEnabledByFeatureGate: async (statsigService) => statsigService.isAtlasProductSupported()
41
+ }
42
+ },
43
+ {
44
+ name: 'Bitbucket',
45
+ productType: 'workspace'
46
+ }
19
47
  ];
20
- const SUPPORTED_PRODUCTS_ALL = [...SITED_PRODUCTS_ALL, ...WORKSPACE_PRODUCTS_ALL];
21
- exports.TEST_ONLY_EXPORTS = {
22
- SITED_PRODUCTS_ALL,
23
- SITED_PRODUCTS_ALWAYS_ENABLED,
24
- WORKSPACE_PRODUCTS_ALL,
25
- SUPPORTED_PRODUCTS_ALWAYS_ENABLED
26
- };
27
- function arrayContains(arr, e) {
28
- return arr.includes(e);
48
+ class SupportedProductEntry {
49
+ productName;
50
+ productType;
51
+ supportedByCrossProductApps;
52
+ constructor(productName, productType, supportedByCrossProductApps) {
53
+ this.productName = productName;
54
+ this.productType = productType;
55
+ this.supportedByCrossProductApps = supportedByCrossProductApps;
56
+ }
57
+ }
58
+ async function resolveEnabledProducts(statsigService) {
59
+ const productDefinitionWithIsEnabledResolved = await Promise.all(SUPPORTED_PRODUCTS_DEFINITIONS.map(async (pd) => {
60
+ const enabledByFeatureGateResolver = pd.special?.isEnabledByFeatureGate;
61
+ const isEnabled = enabledByFeatureGateResolver ? await enabledByFeatureGateResolver(statsigService) : true;
62
+ return { pd, isEnabled };
63
+ }));
64
+ const definitionsForEnabledProducts = productDefinitionWithIsEnabledResolved
65
+ .filter(({ isEnabled }) => isEnabled)
66
+ .map(({ pd }) => pd);
67
+ return definitionsForEnabledProducts.map((pd) => {
68
+ return new SupportedProductEntry(pd.name, pd.productType, pd.special?.supportedByCrossProductApps ?? false);
69
+ });
29
70
  }
30
71
  class SupportedProductsService {
31
- statsigService;
32
- featureGatedProductsCache = null;
33
- constructor(statsigService) {
34
- this.statsigService = statsigService;
35
- }
36
- async buildFeatureGatedProduct(productName, productType, isEnabledPromise) {
37
- return {
38
- productName,
39
- productType,
40
- isEnabled: await isEnabledPromise
41
- };
72
+ supportedProducts;
73
+ constructor(supportedProducts) {
74
+ this.supportedProducts = supportedProducts;
42
75
  }
43
- async getFeatureGatedProducts() {
44
- if (this.featureGatedProductsCache === null) {
45
- this.featureGatedProductsCache = await Promise.all([
46
- this.buildFeatureGatedProduct('Teamwork Graph', 'sited', this.statsigService.isTeamworkGraphProductSupported()),
47
- this.buildFeatureGatedProduct('Atlas', 'sited', this.statsigService.isAtlasProductSupported())
48
- ]);
76
+ async initializeWithSupportedProducts(statsigService) {
77
+ if (this.supportedProducts) {
78
+ throw new Error('SupportedProductsService is already initialized');
49
79
  }
50
- return this.featureGatedProductsCache;
80
+ this.supportedProducts = await resolveEnabledProducts(statsigService);
51
81
  }
52
- async getProductsEnabledByFeatureGate(filter = () => true) {
53
- const featureGatedProducts = await this.getFeatureGatedProducts();
54
- return featureGatedProducts
55
- .filter((gatedProductInfo) => gatedProductInfo.isEnabled && filter(gatedProductInfo))
56
- .map((product) => product.productName);
57
- }
58
- ensureProductDisplayName(product) {
59
- if (arrayContains(SUPPORTED_PRODUCTS_ALL, product)) {
60
- return product;
61
- }
62
- else {
63
- return (0, shared_1.productDisplayName)(product);
82
+ getSupportedProductsNames(filter = () => true) {
83
+ if (!this.supportedProducts) {
84
+ throw new Error('SupportedProductsService is not initialized, are you calling it from some constructor?');
64
85
  }
86
+ return this.supportedProducts.filter((p) => filter(p)).map((p) => p.productName);
65
87
  }
66
- async getSupportedProducts(requiredProducts) {
67
- if (requiredProducts?.length) {
68
- const upperCaseRequiredProducts = requiredProducts.map((product) => product.toUpperCase());
69
- return [
70
- ...SITED_PRODUCTS_ALWAYS_ENABLED.filter((product) => !upperCaseRequiredProducts.includes(product.toUpperCase()))
71
- ];
72
- }
73
- return [
74
- ...SITED_PRODUCTS_ALWAYS_ENABLED,
75
- ...WORKSPACE_PRODUCTS_ALWAYS_ENABLED,
76
- ...(await this.getProductsEnabledByFeatureGate())
77
- ];
88
+ getSupportedProducts() {
89
+ return this.getSupportedProductsNames();
78
90
  }
79
- async getSupportedWorkspaceProducts() {
80
- return [
81
- ...WORKSPACE_PRODUCTS_ALWAYS_ENABLED,
82
- ...(await this.getProductsEnabledByFeatureGate((product) => product.productType == 'workspace'))
83
- ];
91
+ getSupportedSecondaryProductsForXPA(requiredProducts) {
92
+ const requiredProductsNames = requiredProducts.map((p) => (0, shared_1.productDisplayName)(p));
93
+ return this.getSupportedProductsNames((p) => p.supportedByCrossProductApps && !requiredProductsNames.includes(p.productName));
84
94
  }
85
- async validateSupportedProduct(productNameInput) {
95
+ validateSupportedProduct(productNameInput) {
86
96
  const productName = (0, shared_1.productDisplayName)(productNameInput);
87
- const supportedProducts = await this.getSupportedProducts();
88
- if (arrayContains(supportedProducts, productName)) {
97
+ const supportedProducts = this.getSupportedProducts();
98
+ if (supportedProducts.includes(productName)) {
89
99
  return productName;
90
100
  }
91
101
  else {
92
102
  throw new shared_1.ValidationError(ui_1.Text.error.invalidProduct);
93
103
  }
94
104
  }
95
- async isWorkspaceProduct(product) {
96
- return arrayContains(await this.getSupportedWorkspaceProducts(), this.ensureProductDisplayName(product));
105
+ isWorkspaceProduct(product) {
106
+ return this.getSupportedProductsNames((p) => p.productType === 'workspace').includes((0, shared_1.productDisplayName)(product));
97
107
  }
98
- async validateSite(site, product) {
108
+ validateSite(site, product) {
99
109
  const trySites = [site, `https://${site}`];
100
110
  for (const trySite of trySites) {
101
111
  try {
102
112
  const urlObj = new url_1.URL(trySite);
103
- if (product && (await this.isWorkspaceProduct(product))) {
113
+ if (product && this.isWorkspaceProduct(product)) {
104
114
  return urlObj;
105
115
  }
106
116
  urlObj.pathname = '/';
@@ -117,3 +127,6 @@ const isBitbucketProduct = (product) => {
117
127
  return (0, shared_1.productDisplayName)(product) === 'Bitbucket';
118
128
  };
119
129
  exports.isBitbucketProduct = isBitbucketProduct;
130
+ exports.TEST_ONLY_EXPORTS = {
131
+ resolveEnabledProducts
132
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forge/cli-shared",
3
- "version": "6.6.1-next.7",
3
+ "version": "6.6.1-next.9",
4
4
  "description": "Common functionality for Forge CLI",
5
5
  "author": "Atlassian",
6
6
  "license": "SEE LICENSE IN LICENSE.txt",
@@ -12,7 +12,7 @@
12
12
  "generate-graphql-types": "graphql-codegen --config src/graphql/codegen.yml"
13
13
  },
14
14
  "dependencies": {
15
- "@forge/manifest": "8.7.0-next.3",
15
+ "@forge/manifest": "8.7.0-next.4",
16
16
  "@forge/util": "1.4.8-next.0",
17
17
  "@forge/i18n": "0.0.3",
18
18
  "@sentry/node": "7.106.0",