@forge/cli 10.13.6 → 11.0.0-next.18

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +203 -0
  2. package/LICENSE.txt +7 -0
  3. package/npm-shrinkwrap.json +142 -130
  4. package/out/autocomplete/autocomplete-config.json +26 -0
  5. package/out/command-line/command.d.ts +15 -2
  6. package/out/command-line/command.d.ts.map +1 -1
  7. package/out/command-line/command.js +29 -6
  8. package/out/command-line/controller/deploy-controller.d.ts.map +1 -1
  9. package/out/command-line/controller/deploy-controller.js +4 -7
  10. package/out/command-line/controller/install-controller.d.ts +3 -3
  11. package/out/command-line/controller/install-controller.d.ts.map +1 -1
  12. package/out/command-line/controller/install-controller.js +16 -13
  13. package/out/command-line/controller/version-controller.d.ts +36 -0
  14. package/out/command-line/controller/version-controller.d.ts.map +1 -0
  15. package/out/command-line/controller/version-controller.js +114 -0
  16. package/out/command-line/dependency-injection.d.ts +4 -1
  17. package/out/command-line/dependency-injection.d.ts.map +1 -1
  18. package/out/command-line/dependency-injection.js +14 -6
  19. package/out/command-line/index.d.ts +1 -1
  20. package/out/command-line/index.d.ts.map +1 -1
  21. package/out/command-line/index.js +6 -4
  22. package/out/command-line/register-app-commands.d.ts.map +1 -1
  23. package/out/command-line/register-app-commands.js +9 -1
  24. package/out/command-line/register-installation-commands.d.ts +2 -10
  25. package/out/command-line/register-installation-commands.d.ts.map +1 -1
  26. package/out/command-line/register-installation-commands.js +29 -32
  27. package/out/command-line/register-version-commands.d.ts +4 -0
  28. package/out/command-line/register-version-commands.d.ts.map +1 -0
  29. package/out/command-line/register-version-commands.js +76 -0
  30. package/out/command-line/register-webtrigger-commands.d.ts +1 -1
  31. package/out/command-line/register-webtrigger-commands.d.ts.map +1 -1
  32. package/out/command-line/register-webtrigger-commands.js +13 -5
  33. package/out/command-line/view/deploy-view.d.ts +1 -1
  34. package/out/command-line/view/deploy-view.d.ts.map +1 -1
  35. package/out/command-line/view/deploy-view.js +2 -2
  36. package/out/command-line/view/version-view.d.ts +26 -0
  37. package/out/command-line/view/version-view.d.ts.map +1 -0
  38. package/out/command-line/view/version-view.js +198 -0
  39. package/out/environment/graphql-client.d.ts +1 -0
  40. package/out/environment/graphql-client.d.ts.map +1 -1
  41. package/out/environment/graphql-client.js +3 -1
  42. package/out/environment/list-environment.d.ts +1 -0
  43. package/out/environment/list-environment.d.ts.map +1 -1
  44. package/out/installations/graphql-client.d.ts +6 -5
  45. package/out/installations/graphql-client.d.ts.map +1 -1
  46. package/out/installations/graphql-client.js +44 -7
  47. package/out/installations/installation-helper.d.ts.map +1 -1
  48. package/out/installations/installation-helper.js +1 -1
  49. package/out/installations/site-translation/bitbucket.d.ts +3 -4
  50. package/out/installations/site-translation/bitbucket.d.ts.map +1 -1
  51. package/out/installations/site-translation/bitbucket.js +1 -1
  52. package/out/installations/site-translation/index.d.ts +1 -1
  53. package/out/installations/site-translation/index.d.ts.map +1 -1
  54. package/out/installations/site-translation/index.js +1 -1
  55. package/out/installations/site-translation/site-translation.d.ts +3 -4
  56. package/out/installations/site-translation/site-translation.d.ts.map +1 -1
  57. package/out/installations/site-translation/sited-products.d.ts +29 -0
  58. package/out/installations/site-translation/sited-products.d.ts.map +1 -0
  59. package/out/installations/site-translation/sited-products.js +133 -0
  60. package/out/service/installation-service.d.ts +18 -4
  61. package/out/service/installation-service.d.ts.map +1 -1
  62. package/out/service/installation-service.js +44 -10
  63. package/out/service/tunnel-service.d.ts.map +1 -1
  64. package/out/service/tunnel-service.js +1 -1
  65. package/out/service/version-service.d.ts +77 -0
  66. package/out/service/version-service.d.ts.map +1 -0
  67. package/out/service/version-service.js +163 -0
  68. package/out/version/graphql-client.d.ts +25 -0
  69. package/out/version/graphql-client.d.ts.map +1 -0
  70. package/out/version/graphql-client.js +144 -0
  71. package/package.json +13 -11
  72. package/out/installations/site-translation/cloudid-products.d.ts +0 -25
  73. package/out/installations/site-translation/cloudid-products.d.ts.map +0 -1
  74. package/out/installations/site-translation/cloudid-products.js +0 -103
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SitedProductTranslator = exports.ActivationIdMissingError = exports.InvalidAtlassianSiteError = exports.GRAPH_PRODUCT_ID_IN_TCS = void 0;
4
+ const cli_shared_1 = require("@forge/cli-shared");
5
+ exports.GRAPH_PRODUCT_ID_IN_TCS = 'devops';
6
+ const PRODUCT_RESOURCE_OWNER_TO_TCS_PRODUCT_ID = {
7
+ graph: exports.GRAPH_PRODUCT_ID_IN_TCS
8
+ };
9
+ const NON_SITED_PRODUCTS_USING_WORKSPACE_ARI = [cli_shared_1.TRELLO_RESOURCE_OWNER, cli_shared_1.BITBUCKET_RESOURCE_OWNER];
10
+ class InvalidAtlassianSiteError extends cli_shared_1.UserError {
11
+ constructor(url) {
12
+ super(cli_shared_1.Text.install.error.invalidAtlassianSite(url));
13
+ }
14
+ }
15
+ exports.InvalidAtlassianSiteError = InvalidAtlassianSiteError;
16
+ class ActivationIdMissingError extends Error {
17
+ constructor(url, product) {
18
+ super(cli_shared_1.Text.install.error.activationIdMissing(url, product));
19
+ }
20
+ }
21
+ exports.ActivationIdMissingError = ActivationIdMissingError;
22
+ function removeDuplicatedAris(aris) {
23
+ return Array.from(new Map(aris.map((ari) => [ari.toString(), ari])).values());
24
+ }
25
+ const tenantContextsToCloudIdAndActivationId = (url, contexts, productResourceOwner) => {
26
+ if (!contexts.length) {
27
+ throw new InvalidAtlassianSiteError(url);
28
+ }
29
+ const context = contexts[0];
30
+ if (!context || !context.cloudId) {
31
+ throw new InvalidAtlassianSiteError(url);
32
+ }
33
+ const activationId = context.activationIdByProduct?.active;
34
+ if (!activationId) {
35
+ throw new ActivationIdMissingError(url.toString(), (0, cli_shared_1.productDisplayName)(productResourceOwner));
36
+ }
37
+ return { cloudId: context.cloudId, activationId: activationId };
38
+ };
39
+ function splitArrayToChunks(array, chunkSize) {
40
+ const chunks = [];
41
+ for (let i = 0; i < array.length; i += chunkSize) {
42
+ chunks.push(array.slice(i, i + chunkSize));
43
+ }
44
+ return chunks;
45
+ }
46
+ class SitedProductTranslator {
47
+ graphqlClient;
48
+ constructor(graphqlClient) {
49
+ this.graphqlClient = graphqlClient;
50
+ }
51
+ ariBelongsToProduct(ari) {
52
+ return (ari.resourceType === cli_shared_1.SITE_RESOURCE_TYPE ||
53
+ (ari.resourceType === cli_shared_1.WORKSPACE_RESOURCE_TYPE &&
54
+ !NON_SITED_PRODUCTS_USING_WORKSPACE_ARI.includes(ari.resourceOwner)));
55
+ }
56
+ async buildInstallationContext(product, site) {
57
+ const productResourceOwner = (0, cli_shared_1.ariResourceOwner)(product);
58
+ const { cloudId, activationId } = await this.getCloudIdAndActivationId(site, productResourceOwner);
59
+ const workspaceAriCreator = cli_shared_1.createWorkspaceAriByProduct[productResourceOwner];
60
+ return workspaceAriCreator(cloudId, activationId);
61
+ }
62
+ async getSitesForResourceAris(aris) {
63
+ const uniqueAris = removeDuplicatedAris(aris);
64
+ const arisWithCloudId = uniqueAris.filter((ari) => ari.resourceType == cli_shared_1.SITE_RESOURCE_TYPE || !!ari.cloudId);
65
+ const arisWithOnlyActivationId = uniqueAris.filter((ari) => ari.resourceType == cli_shared_1.WORKSPACE_RESOURCE_TYPE && !ari.cloudId);
66
+ const [cloudIdArisToHostname, activationIdArisToHostname] = await Promise.all([
67
+ this.bulkQuerySiteHostnames(arisWithCloudId, (ari) => ari.cloudId || ari.resourceId, this.queryHostnamesByCloudIds),
68
+ this.bulkQuerySiteHostnames(arisWithOnlyActivationId, (ari) => ari.resourceId, this.queryHostnamesByActivationIds)
69
+ ]);
70
+ return {
71
+ ...cloudIdArisToHostname,
72
+ ...activationIdArisToHostname
73
+ };
74
+ }
75
+ queryHostnamesByCloudIds = async (cloudIds) => {
76
+ const query = `
77
+ query forge_cli_getHostnameForTenantContexts($cloudIds: [ID!]!) {
78
+ tenantContexts(cloudIds: $cloudIds) {
79
+ hostName
80
+ }
81
+ }
82
+ `;
83
+ const response = await this.graphqlClient.query(query, {
84
+ cloudIds: cloudIds
85
+ });
86
+ return Object.fromEntries(cloudIds.map((id, index) => [
87
+ id,
88
+ response?.tenantContexts?.[index]?.hostName || id
89
+ ]));
90
+ };
91
+ queryHostnamesByActivationIds = async (activationIds) => {
92
+ const query = `
93
+ query forge_cli_getHostnameForTenantContexts($activationIds: [ID!]!) {
94
+ tenantContexts(activationIds: $activationIds) {
95
+ hostName
96
+ }
97
+ }
98
+ `;
99
+ const response = await this.graphqlClient.query(query, {
100
+ activationIds: activationIds
101
+ });
102
+ return Object.fromEntries(activationIds.map((id, index) => [id, response?.tenantContexts?.[index]?.hostName]));
103
+ };
104
+ async bulkQuerySiteHostnames(aris, idExtractor, querySiteHostnameFunction) {
105
+ if (aris.length === 0) {
106
+ return {};
107
+ }
108
+ const idsToQuery = [...new Set(aris.map(idExtractor))];
109
+ const idsChunks = splitArrayToChunks(idsToQuery, 20);
110
+ const chunkedMapping = await Promise.all(idsChunks.map(querySiteHostnameFunction));
111
+ const fullMapping = Object.assign({}, ...chunkedMapping);
112
+ return Object.fromEntries(aris.map((ari) => [ari.toString(), fullMapping[idExtractor(ari)]]));
113
+ }
114
+ async getCloudIdAndActivationId(site, productResourceOwner) {
115
+ const query = `
116
+ query getTenantContextDetails($hostNames: [String!], $product: String!) {
117
+ tenantContexts(hostNames: $hostNames) {
118
+ cloudId
119
+ activationIdByProduct(product: $product) {
120
+ active
121
+ }
122
+ }
123
+ }
124
+ `;
125
+ const result = await this.graphqlClient.query(query, {
126
+ hostNames: [site.hostname],
127
+ product: PRODUCT_RESOURCE_OWNER_TO_TCS_PRODUCT_ID[productResourceOwner] || productResourceOwner
128
+ });
129
+ const tenantContexts = result.tenantContexts || [];
130
+ return tenantContextsToCloudIdAndActivationId(site, tenantContexts, productResourceOwner);
131
+ }
132
+ }
133
+ exports.SitedProductTranslator = SitedProductTranslator;
@@ -1,14 +1,16 @@
1
1
  /// <reference types="node" />
2
- import { AppConfigProvider, AppEnvironmentType, AppEnvironmentVersion, Maybe } from '@forge/cli-shared';
2
+ import { AppConfigProvider, AppEnvironmentType, AppEnvironmentVersion, Maybe, SupportedProduct, BaseError } from '@forge/cli-shared';
3
3
  import { URL } from 'url';
4
4
  import { AppInstallSiteDetails } from '../installations/install-app-site';
5
5
  export interface Installation {
6
6
  id: string;
7
7
  product: string;
8
+ secondaryProducts?: string[];
8
9
  site: string;
9
10
  environmentKey: string;
10
11
  environmentType: AppEnvironmentType;
11
12
  context: string;
13
+ secondaryContexts?: string[];
12
14
  version: {
13
15
  isLatest: boolean;
14
16
  version: string;
@@ -20,6 +22,7 @@ export interface AppInstallation {
20
22
  export interface AppEnvironmentVersionPermissions {
21
23
  scopes: string[];
22
24
  egressAddresses: string[];
25
+ primaryProduct?: string;
23
26
  }
24
27
  export interface AppEnvironmentPermissions extends AppEnvironmentVersionPermissions {
25
28
  addedScopes: string[];
@@ -27,8 +30,8 @@ export interface AppEnvironmentPermissions extends AppEnvironmentVersionPermissi
27
30
  hasDeployments: boolean;
28
31
  }
29
32
  interface InstallationFilterOptions {
30
- site?: string;
31
- product?: 'Jira' | 'Confluence';
33
+ site?: URL;
34
+ product?: SupportedProduct;
32
35
  environment?: string;
33
36
  }
34
37
  export interface AppEnvironmentVersionData {
@@ -42,14 +45,25 @@ export interface ListAppInstallationsClient {
42
45
  export interface UpgradeAppInstallationsClient {
43
46
  upgradeInstallation({ site, product, environmentKey, appId }: AppInstallSiteDetails): Promise<void>;
44
47
  }
48
+ export interface HasNoAppInstallationsForEnvClient {
49
+ hasNoAppInstallationsForEnv(appId: string, appEnv: AppEnvironmentType): Promise<boolean>;
50
+ }
51
+ export declare class MultipleMatchingInstallationsError extends BaseError {
52
+ constructor();
53
+ }
45
54
  export declare class InstallationService {
46
55
  private readonly getAppConfig;
47
56
  private readonly listInstallationsClient;
48
57
  private readonly upgradeAppInstallationsClient;
49
- constructor(getAppConfig: AppConfigProvider, listInstallationsClient: ListAppInstallationsClient, upgradeAppInstallationsClient: UpgradeAppInstallationsClient);
58
+ private readonly hasNoAppInstallationsForEnvClient;
59
+ constructor(getAppConfig: AppConfigProvider, listInstallationsClient: ListAppInstallationsClient, upgradeAppInstallationsClient: UpgradeAppInstallationsClient, hasNoAppInstallationsForEnvClient: HasNoAppInstallationsForEnvClient);
60
+ private comparePossibleInstallations;
61
+ private matchSiteForProduct;
50
62
  private filterInstallations;
51
63
  listAppInstallations(filter?: InstallationFilterOptions): Promise<AppInstallation>;
64
+ hasNoAppInstallationsForEnv(appEnv: AppEnvironmentType): Promise<boolean>;
52
65
  listNonTechnicalAppInstallations(filter?: InstallationFilterOptions): Promise<AppInstallation>;
66
+ findOnlyMatchingInstallation(filter: InstallationFilterOptions): Promise<Installation>;
53
67
  hasOutdatedProductInstallation(environment: string): Promise<boolean>;
54
68
  upgradeInstallation(site: URL, product: string, environmentKey: string, appId: string): Promise<boolean>;
55
69
  private getPermissionsFromAppEnvironmentVersion;
@@ -1 +1 @@
1
- {"version":3,"file":"installation-service.d.ts","sourceRoot":"","sources":["../../src/service/installation-service.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EAKrB,KAAK,EAEN,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAG1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE1E,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,kBAAkB,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,gCAAgC;IAC/C,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,yBAA0B,SAAQ,gCAAgC;IACjF,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,kBAAkB,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,UAAU,yBAAyB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,GAAG,IAAI,CAAC;IACnD,eAAe,EAAE,kBAAkB,CAAC;CACrC;AAED,MAAM,WAAW,0BAA0B;IACzC,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC1D,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;CACxG;AAED,MAAM,WAAW,6BAA6B;IAC5C,mBAAmB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrG;AAKD,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,6BAA6B;gBAF7B,YAAY,EAAE,iBAAiB,EAC/B,uBAAuB,EAAE,0BAA0B,EACnD,6BAA6B,EAAE,6BAA6B;IAG/E,OAAO,CAAC,mBAAmB;IAiBd,oBAAoB,CAAC,MAAM,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,eAAe,CAAC;IAOlF,gCAAgC,CAAC,MAAM,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,eAAe,CAAC;IAU9F,8BAA8B,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOrE,mBAAmB,CAC9B,IAAI,EAAE,GAAG,EACT,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC;IAkBnB,OAAO,CAAC,uCAAuC;IAgBlC,4BAA4B,CACvC,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,yBAAyB,GAAG,SAAS,CAAC;CAiClD"}
1
+ {"version":3,"file":"installation-service.d.ts","sourceRoot":"","sources":["../../src/service/installation-service.ts"],"names":[],"mappings":"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"}
@@ -1,29 +1,46 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InstallationService = void 0;
3
+ exports.InstallationService = exports.MultipleMatchingInstallationsError = void 0;
4
4
  const cli_shared_1 = require("@forge/cli-shared");
5
5
  const egress_1 = require("@forge/egress");
6
6
  const lodash_1 = require("lodash");
7
7
  const graphql_client_1 = require("../installations/graphql-client");
8
8
  const IDENTITY_PRODUCT_NAME = 'identity';
9
+ const BITBUCKET_PRODUCT_NAME = 'bitbucket';
9
10
  const JIRA_SERVICE_DESK_PRODUCT_NAME = 'jira-servicedesk';
11
+ class MultipleMatchingInstallationsError extends cli_shared_1.BaseError {
12
+ constructor() {
13
+ super(cli_shared_1.Text.error.multipleMatchingInstallations);
14
+ }
15
+ }
16
+ exports.MultipleMatchingInstallationsError = MultipleMatchingInstallationsError;
10
17
  class InstallationService {
11
18
  getAppConfig;
12
19
  listInstallationsClient;
13
20
  upgradeAppInstallationsClient;
14
- constructor(getAppConfig, listInstallationsClient, upgradeAppInstallationsClient) {
21
+ hasNoAppInstallationsForEnvClient;
22
+ constructor(getAppConfig, listInstallationsClient, upgradeAppInstallationsClient, hasNoAppInstallationsForEnvClient) {
15
23
  this.getAppConfig = getAppConfig;
16
24
  this.listInstallationsClient = listInstallationsClient;
17
25
  this.upgradeAppInstallationsClient = upgradeAppInstallationsClient;
26
+ this.hasNoAppInstallationsForEnvClient = hasNoAppInstallationsForEnvClient;
27
+ }
28
+ comparePossibleInstallations(url1, url2) {
29
+ const trimmedUrl1 = url1.replace(/\/+$/, '');
30
+ const trimmedUrl2 = url2.replace(/\/+$/, '');
31
+ return trimmedUrl1 === trimmedUrl2;
32
+ }
33
+ matchSiteForProduct(filterSite, installationSite, installationProduct) {
34
+ if (installationProduct === BITBUCKET_PRODUCT_NAME) {
35
+ return this.comparePossibleInstallations(filterSite.href, installationSite);
36
+ }
37
+ return this.comparePossibleInstallations(filterSite.host, installationSite);
18
38
  }
19
39
  filterInstallations(installations, { site: filterSite, product: filterProduct, environment: filterEnvironment }) {
20
- const isDefaultEnvironment = (env) => env === (0, cli_shared_1.optionToEnvironment)(cli_shared_1.DEFAULT_ENVIRONMENT_OPTION);
21
40
  return installations.filter(({ product, site, environmentKey }) => {
22
41
  const matchProduct = !filterProduct || filterProduct === (0, cli_shared_1.productDisplayName)(product);
23
- const matchSite = !filterSite || filterSite === site;
24
- const matchEnvironment = filterEnvironment
25
- ? isDefaultEnvironment(filterEnvironment) || filterEnvironment === (0, cli_shared_1.environmentToOption)(environmentKey)
26
- : true;
42
+ const matchSite = !filterSite || this.matchSiteForProduct(filterSite, site, product);
43
+ const matchEnvironment = !filterEnvironment || filterEnvironment === (0, cli_shared_1.optionToEnvironment)(environmentKey);
27
44
  return matchProduct && matchSite && matchEnvironment;
28
45
  });
29
46
  }
@@ -32,12 +49,26 @@ class InstallationService {
32
49
  const installations = await this.listInstallationsClient.listInstallations(appId);
33
50
  return { installations: this.filterInstallations(installations, { ...filter }) };
34
51
  }
52
+ async hasNoAppInstallationsForEnv(appEnv) {
53
+ const { id: appId } = await this.getAppConfig();
54
+ return this.hasNoAppInstallationsForEnvClient.hasNoAppInstallationsForEnv(appId, appEnv);
55
+ }
35
56
  async listNonTechnicalAppInstallations(filter) {
36
57
  const { installations } = await this.listAppInstallations(filter);
37
58
  return {
38
59
  installations: installations.filter(({ product }) => product !== IDENTITY_PRODUCT_NAME && product !== JIRA_SERVICE_DESK_PRODUCT_NAME)
39
60
  };
40
61
  }
62
+ async findOnlyMatchingInstallation(filter) {
63
+ const filterInstalls = await this.listNonTechnicalAppInstallations(filter);
64
+ if (!filterInstalls.installations.length) {
65
+ throw new cli_shared_1.UserError(cli_shared_1.Text.error.invalidInstallationContext);
66
+ }
67
+ if (filterInstalls.installations.length !== 1) {
68
+ throw new MultipleMatchingInstallationsError();
69
+ }
70
+ return filterInstalls.installations[0];
71
+ }
41
72
  async hasOutdatedProductInstallation(environment) {
42
73
  const { installations } = await this.listNonTechnicalAppInstallations({
43
74
  environment
@@ -65,23 +96,25 @@ class InstallationService {
65
96
  }
66
97
  getPermissionsFromAppEnvironmentVersion(appEnvironmentVersion) {
67
98
  const permissions = appEnvironmentVersion?.permissions[0];
99
+ const primaryProduct = appEnvironmentVersion?.primaryProduct ?? undefined;
68
100
  if (!permissions) {
69
- return { scopes: [], egressAddresses: [] };
101
+ return { scopes: [], egressAddresses: [], primaryProduct };
70
102
  }
71
103
  const scopes = permissions.scopes.map((s) => s.key);
72
104
  const egressAddresses = permissions?.egress ? (0, cli_shared_1.flatMap)(permissions.egress, ({ addresses }) => addresses ?? []) : [];
73
- return { scopes, egressAddresses };
105
+ return { scopes, egressAddresses, primaryProduct };
74
106
  }
75
107
  async getAppEnvironmentPermissions(appId, environmentKey) {
76
108
  const versionDetails = await this.listInstallationsClient.getVersions(appId, environmentKey, 2);
77
109
  const versions = versionDetails?.nodes;
78
110
  if (!versions || versions.length === 0)
79
111
  return;
80
- const [{ scopes, egressAddresses }, oldVersion] = versions.map((appEnvironmentVersion) => this.getPermissionsFromAppEnvironmentVersion(appEnvironmentVersion));
112
+ const [{ scopes, egressAddresses, primaryProduct }, oldVersion] = versions.map((appEnvironmentVersion) => this.getPermissionsFromAppEnvironmentVersion(appEnvironmentVersion));
81
113
  const groupedEgressAddresses = (0, egress_1.sortAndGroupEgressPermissionsByDomain)(egressAddresses);
82
114
  if (!oldVersion) {
83
115
  return {
84
116
  scopes,
117
+ primaryProduct,
85
118
  hasDeployments: false,
86
119
  egressAddresses: groupedEgressAddresses,
87
120
  addedScopes: scopes,
@@ -92,6 +125,7 @@ class InstallationService {
92
125
  const addedScopes = (0, lodash_1.difference)(scopes, oldScopes);
93
126
  return {
94
127
  scopes,
128
+ primaryProduct,
95
129
  hasDeployments: true,
96
130
  egressAddresses: groupedEgressAddresses,
97
131
  addedScopes,
@@ -1 +1 @@
1
- {"version":3,"file":"tunnel-service.d.ts","sourceRoot":"","sources":["../../src/service/tunnel-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tunnel-service.d.ts","sourceRoot":"","sources":["../../src/service/tunnel-service.ts"],"names":[],"mappings":"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"}
@@ -240,7 +240,7 @@ class DockerTunnelService extends SandboxTunnelServiceBase {
240
240
  if (process.env.FORGE_DEV_DOCKER_TUNNEL) {
241
241
  const monorepoRoot = (0, path_1.join)(__dirname, '../../../..');
242
242
  options.push(`-v=${monorepoRoot}:/monorepo:cached`);
243
- options.push(`-v=${monorepoRoot}/node_modules/@koterpillar/cloudflared/docker-bin:/monorepo/node_modules/@koterpillar/cloudflared/bin`);
243
+ options.push(`-v=${monorepoRoot}/node_modules/cloudflared/docker-bin:/monorepo/node_modules/cloudflared/bin`);
244
244
  }
245
245
  if (process.env.FORGE_TUNNEL_MOUNT_DIRECTORIES) {
246
246
  const mounts = process.env.FORGE_TUNNEL_MOUNT_DIRECTORIES.split(',');
@@ -0,0 +1,77 @@
1
+ import { AppConfigProvider, AppEnvironmentType } from '@forge/cli-shared';
2
+ import { AppVersionDetailsClient } from '../version/graphql-client';
3
+ export interface VersionDetails {
4
+ appVersion: number;
5
+ deploymentDateTime: Date;
6
+ environmentType: AppEnvironmentType;
7
+ functions: {
8
+ key: string;
9
+ runtimeName: string;
10
+ handler: string;
11
+ }[];
12
+ modules: {
13
+ type: string;
14
+ items: {
15
+ key: string;
16
+ properties: any;
17
+ }[];
18
+ }[];
19
+ requiresLicense: boolean;
20
+ egresses: {
21
+ type: string;
22
+ addresses: string[];
23
+ }[];
24
+ scopes: string[];
25
+ policies: {
26
+ type: string;
27
+ policies: string[];
28
+ }[];
29
+ connectKeys: {
30
+ product: string;
31
+ key: string;
32
+ }[];
33
+ remotes: {
34
+ key: string;
35
+ baseUrl: string;
36
+ operations: string[];
37
+ }[];
38
+ }
39
+ export interface VersionOverview {
40
+ version: number;
41
+ deploymentDateTime: Date;
42
+ environmentType: AppEnvironmentType;
43
+ egresses: {
44
+ type: string;
45
+ count: number;
46
+ }[];
47
+ policies: {
48
+ type: string;
49
+ count: number;
50
+ }[];
51
+ scopes: string;
52
+ connectKeys: string;
53
+ functions: string;
54
+ remotes: string;
55
+ modules: {
56
+ type: string;
57
+ count: number;
58
+ }[];
59
+ requiresLicense: boolean;
60
+ }
61
+ export declare class VersionService {
62
+ private readonly getAppConfig;
63
+ private readonly versionDetailsClient;
64
+ constructor(getAppConfig: AppConfigProvider, versionDetailsClient: AppVersionDetailsClient);
65
+ private filterOutEmpty;
66
+ private getEgresses;
67
+ private getPolicies;
68
+ private getConnectedKeys;
69
+ private getFunctions;
70
+ getAppVersionDetails(environmentKey: string, majorVersion?: number): Promise<VersionDetails>;
71
+ private getTypeFromPermissionType;
72
+ private getModulesGroupedByTypes;
73
+ private removeInternalPropertiesFromObject;
74
+ private getAppVersions;
75
+ getAppVersionOverviewList(environmentKey: string): Promise<VersionOverview[]>;
76
+ }
77
+ //# sourceMappingURL=version-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-service.d.ts","sourceRoot":"","sources":["../../src/service/version-service.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAOnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,IAAI,CAAC;IACzB,eAAe,EAAE,kBAAkB,CAAC;IACpC,SAAS,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACnE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,GAAG,CAAA;SAAE,EAAE,CAAA;KAAE,EAAE,CAAC;IACvE,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IAClD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IACjD,WAAW,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChD,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;CACnE;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,IAAI,CAAC;IACzB,eAAe,EAAE,kBAAkB,CAAC;IACpC,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;IACJ,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;IACJ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;IACJ,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,oBAAoB;gBADpB,YAAY,EAAE,iBAAiB,EAC/B,oBAAoB,EAAE,uBAAuB;IAGhE,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,WAAW;IA4BnB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,YAAY;IAmDP,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA4BzG,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,kCAAkC;YAM5B,cAAc;IAKf,yBAAyB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAsB3F"}
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VersionService = void 0;
4
+ const semver_1 = require("semver");
5
+ const cli_shared_1 = require("@forge/cli-shared");
6
+ const manifest_1 = require("@forge/manifest");
7
+ class VersionService {
8
+ getAppConfig;
9
+ versionDetailsClient;
10
+ constructor(getAppConfig, versionDetailsClient) {
11
+ this.getAppConfig = getAppConfig;
12
+ this.versionDetailsClient = versionDetailsClient;
13
+ }
14
+ filterOutEmpty(array) {
15
+ return array?.filter((entry) => entry !== null) || [];
16
+ }
17
+ getEgresses(egresses, remoteModules) {
18
+ const remoteModuleUrls = this.filterOutEmpty(remoteModules).map((remote) => remote?.extensionData.baseUrl);
19
+ const egressesWithoutRemoteModules = this.filterOutEmpty(egresses).map((entry) => {
20
+ if (entry.type === 'FETCH_BACKEND_SIDE') {
21
+ return {
22
+ ...entry,
23
+ addresses: entry.addresses?.filter((address) => !remoteModuleUrls.includes(address))
24
+ };
25
+ }
26
+ return entry;
27
+ });
28
+ return egressesWithoutRemoteModules
29
+ .filter((entry) => this.filterOutEmpty(entry.addresses).length !== 0)
30
+ .map((entry) => ({
31
+ type: this.getTypeFromPermissionType(entry.type),
32
+ addresses: entry.addresses || []
33
+ }));
34
+ }
35
+ getPolicies(securityPolicies) {
36
+ return this.filterOutEmpty(securityPolicies).map((entry) => ({
37
+ type: this.getTypeFromPermissionType(entry.type),
38
+ policies: entry.policies || []
39
+ }));
40
+ }
41
+ getConnectedKeys(migrationKeys) {
42
+ if (!migrationKeys) {
43
+ return [];
44
+ }
45
+ return Object.keys(migrationKeys).map((key) => ({
46
+ product: key,
47
+ key: migrationKeys[key] || ''
48
+ }));
49
+ }
50
+ getFunctions(functionModules) {
51
+ const isOldFunctionsExtension = (extensionData) => {
52
+ return 'functionName' in extensionData;
53
+ };
54
+ const isNewFunctionsExtension = (extensionData) => {
55
+ return 'functions' in extensionData;
56
+ };
57
+ const getRuntimeName = (identifier) => (identifier || 'sandbox').replace('provided.al2', 'sandbox').replace('provided', 'sandbox');
58
+ return this.filterOutEmpty(functionModules).map((entry) => {
59
+ const { key, extensionData } = entry;
60
+ if (isOldFunctionsExtension(extensionData)) {
61
+ return {
62
+ key,
63
+ runtimeName: getRuntimeName(extensionData.runtime?.identifier),
64
+ handler: extensionData.handler
65
+ };
66
+ }
67
+ else if (isNewFunctionsExtension(extensionData)) {
68
+ const keysOfFunctions = Object.keys(extensionData.functions || {});
69
+ return {
70
+ key,
71
+ runtimeName: getRuntimeName(extensionData.functions[keysOfFunctions[0]].runtime.identifier),
72
+ handler: extensionData.handler
73
+ };
74
+ }
75
+ else {
76
+ throw new Error('Unknown function extension data format');
77
+ }
78
+ });
79
+ }
80
+ async getAppVersionDetails(environmentKey, majorVersion) {
81
+ const { id: appId } = await this.getAppConfig();
82
+ const data = await this.versionDetailsClient.getVersionDetails(appId, environmentKey, majorVersion);
83
+ const functionModules = data.modules?.filter((mod) => mod?.extensionData.type === manifest_1.AllModuleTypes.CoreFunction);
84
+ const remoteModules = data.modules?.filter((mod) => mod?.extensionData.type === manifest_1.AllModuleTypes.CoreRemote);
85
+ const allModules = this.getModulesGroupedByTypes(data.modules);
86
+ return {
87
+ requiresLicense: data.requiresLicense,
88
+ egresses: this.getEgresses(data.permissions?.[0].egress, remoteModules),
89
+ scopes: data.permissions?.[0].scopes.map((scope) => scope.key).sort() || [],
90
+ policies: this.getPolicies(data.permissions?.[0].securityPolicies),
91
+ connectKeys: this.getConnectedKeys(data.migrationKeys),
92
+ appVersion: (0, semver_1.major)(data.appVersion),
93
+ deploymentDateTime: data.deploymentDateTime,
94
+ environmentType: data.environmentType,
95
+ functions: this.getFunctions(functionModules),
96
+ modules: Object.keys(allModules)
97
+ .filter((type) => !['function', 'remote'].includes(type))
98
+ .map((type) => ({ type, items: allModules[type] })),
99
+ remotes: this.filterOutEmpty(remoteModules).map((entry) => ({
100
+ key: entry.key || 'N/A',
101
+ baseUrl: entry.extensionData.baseUrl,
102
+ operations: entry.extensionData.operations || []
103
+ }))
104
+ };
105
+ }
106
+ getTypeFromPermissionType(permissionType) {
107
+ switch (permissionType) {
108
+ case cli_shared_1.AppNetworkPermissionType.FetchBackendSide:
109
+ return 'fetch.backend';
110
+ case cli_shared_1.AppNetworkPermissionType.FetchClientSide:
111
+ return 'fetch.client';
112
+ default:
113
+ return permissionType?.toLowerCase().replaceAll('_', '.') || 'N/A';
114
+ }
115
+ }
116
+ getModulesGroupedByTypes(modules) {
117
+ const rawModules = this.filterOutEmpty(modules)
118
+ .filter((mod) => manifest_1.SUPPORTED_MODULES.includes(mod.extensionData.type))
119
+ .filter((mod) => ![manifest_1.AllModuleTypes.CoreFunction, manifest_1.AllModuleTypes.CoreRemote].includes(mod.extensionData.type))
120
+ .map((entry) => ({
121
+ key: entry.key,
122
+ type: entry.extensionData.type,
123
+ properties: {
124
+ ...this.removeInternalPropertiesFromObject(entry.extensionData)
125
+ }
126
+ }));
127
+ return rawModules.reduce((acc, entry) => {
128
+ const type = (0, manifest_1.cleanKey)(entry.type);
129
+ if (acc[type] === undefined) {
130
+ acc[type] = [];
131
+ }
132
+ acc[type].push(entry);
133
+ return acc;
134
+ }, {});
135
+ }
136
+ removeInternalPropertiesFromObject(obj) {
137
+ const { type, functions, outboundAuthContainerId, resourceUploadId, key, ...rest } = obj;
138
+ return rest;
139
+ }
140
+ async getAppVersions(environmentKey) {
141
+ const { id: appId } = await this.getAppConfig();
142
+ return await this.versionDetailsClient.getVersionList(appId, environmentKey);
143
+ }
144
+ async getAppVersionOverviewList(environmentKey) {
145
+ const versions = await this.getAppVersions(environmentKey);
146
+ const majorVersions = versions.map((version) => (0, semver_1.major)(version)).filter((majorVersion) => majorVersion > 0);
147
+ const versionDetails = await Promise.all(majorVersions.map(async (version) => await this.getAppVersionDetails(environmentKey, version)));
148
+ return versionDetails.map((entry) => ({
149
+ version: entry.appVersion,
150
+ deploymentDateTime: entry.deploymentDateTime,
151
+ environmentType: entry.environmentType,
152
+ egresses: entry.egresses.map((egress) => ({ type: egress.type, count: egress.addresses.length })),
153
+ policies: entry.policies.map((policy) => ({ type: policy.type, count: policy.policies.length })),
154
+ scopes: (entry.scopes.length || 0).toString(),
155
+ connectKeys: (entry.connectKeys.length || 0).toString(),
156
+ functions: (entry.functions.length || 0).toString(),
157
+ remotes: (entry.remotes.length || 0).toString(),
158
+ modules: entry.modules.map((module) => ({ type: module.type, count: module.items.length })),
159
+ requiresLicense: entry.requiresLicense
160
+ }));
161
+ }
162
+ }
163
+ exports.VersionService = VersionService;
@@ -0,0 +1,25 @@
1
+ import { AppEnvironmentType, AppPermission, AppVersionExtension, GraphQLClient, Maybe, MigrationKeys, Storage, UserError } from '@forge/cli-shared';
2
+ export interface AppVersionDetailsData {
3
+ migrationKeys?: Maybe<MigrationKeys> | null;
4
+ permissions?: Array<AppPermission> | null;
5
+ modules: Array<AppVersionExtension | null> | null | undefined;
6
+ environmentType: AppEnvironmentType;
7
+ appVersion: string;
8
+ deploymentDateTime: Date;
9
+ requiresLicense: boolean;
10
+ storage: Storage;
11
+ }
12
+ export declare class MissingAppError extends UserError {
13
+ }
14
+ export declare class EnvironmentNotFoundError extends UserError {
15
+ constructor(environmentKey: string);
16
+ }
17
+ export declare class MissingAppVersionError extends Error {
18
+ }
19
+ export declare class AppVersionDetailsClient {
20
+ private readonly graphqlClient;
21
+ constructor(graphqlClient: GraphQLClient);
22
+ getVersionDetails(appId: string, environmentKey: string, majorVersion?: number): Promise<AppVersionDetailsData>;
23
+ getVersionList(appId: string, environmentKey: string): Promise<string[]>;
24
+ }
25
+ //# sourceMappingURL=graphql-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphql-client.d.ts","sourceRoot":"","sources":["../../src/version/graphql-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,aAAa,EACb,KAAK,EACL,aAAa,EAEb,OAAO,EAEP,SAAS,EACV,MAAM,mBAAmB,CAAC;AAS3B,MAAM,WAAW,qBAAqB;IACpC,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAC5C,WAAW,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9D,eAAe,EAAE,kBAAkB,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,IAAI,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,eAAgB,SAAQ,SAAS;CAAG;AAEjD,qBAAa,wBAAyB,SAAQ,SAAS;gBACzC,cAAc,EAAE,MAAM;CAGnC;AAED,qBAAa,sBAAuB,SAAQ,KAAK;CAAG;AAEpD,qBAAa,uBAAuB;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,aAAa;IAE5C,iBAAiB,CAC5B,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,EACtB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,qBAAqB,CAAC;IAqFpB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAuDtF"}