@forge/cli 10.13.6 → 11.0.0

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 +251 -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,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"}
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppVersionDetailsClient = exports.MissingAppVersionError = exports.EnvironmentNotFoundError = exports.MissingAppError = void 0;
4
+ const cli_shared_1 = require("@forge/cli-shared");
5
+ class MissingAppError extends cli_shared_1.UserError {
6
+ }
7
+ exports.MissingAppError = MissingAppError;
8
+ class EnvironmentNotFoundError extends cli_shared_1.UserError {
9
+ constructor(environmentKey) {
10
+ super(cli_shared_1.Text.env.error.envNotExist(environmentKey));
11
+ }
12
+ }
13
+ exports.EnvironmentNotFoundError = EnvironmentNotFoundError;
14
+ class MissingAppVersionError extends Error {
15
+ }
16
+ exports.MissingAppVersionError = MissingAppVersionError;
17
+ class AppVersionDetailsClient {
18
+ graphqlClient;
19
+ constructor(graphqlClient) {
20
+ this.graphqlClient = graphqlClient;
21
+ }
22
+ async getVersionDetails(appId, environmentKey, majorVersion) {
23
+ const query = `
24
+ query forge_cli_getApplicationVersionDetails($appId: ID!, $environmentKey: String!, $firstN: Int!, $majorVersion: Int) {
25
+ app(id: $appId) {
26
+ environmentByKey(key: $environmentKey) {
27
+ type
28
+ versions(first: $firstN, majorVersion: $majorVersion) {
29
+ nodes {
30
+ version
31
+ createdAt
32
+ isLatest
33
+ requiresLicense
34
+ permissions {
35
+ scopes {
36
+ key
37
+ }
38
+ egress {
39
+ type
40
+ addresses
41
+ }
42
+ securityPolicies {
43
+ type
44
+ policies
45
+ }
46
+ }
47
+ extensions {
48
+ nodes {
49
+ id
50
+ key
51
+ extensionData
52
+ }
53
+ }
54
+ storage {
55
+ hosted {
56
+ classifications
57
+ locations
58
+ }
59
+ remotes {
60
+ key
61
+ baseUrl
62
+ classifications
63
+ locations
64
+ }
65
+ }
66
+ migrationKeys {
67
+ jira
68
+ confluence
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
75
+ `;
76
+ const result = await this.graphqlClient.query(query, {
77
+ appId,
78
+ environmentKey,
79
+ firstN: 1,
80
+ majorVersion
81
+ });
82
+ if (!result.app) {
83
+ throw new MissingAppError();
84
+ }
85
+ if (!result.app.environmentByKey) {
86
+ throw new EnvironmentNotFoundError(environmentKey);
87
+ }
88
+ if (!result.app.environmentByKey.versions?.nodes?.length || !result.app.environmentByKey.versions?.nodes?.[0]) {
89
+ throw new MissingAppVersionError();
90
+ }
91
+ return {
92
+ migrationKeys: result.app.environmentByKey.versions?.nodes?.[0]?.migrationKeys,
93
+ environmentType: result.app.environmentByKey.type,
94
+ appVersion: result.app.environmentByKey.versions?.nodes?.[0]?.version,
95
+ deploymentDateTime: new Date(Number.parseInt(result.app.environmentByKey.versions?.nodes?.[0]?.createdAt)),
96
+ storage: result.app.environmentByKey.versions?.nodes?.[0]?.storage,
97
+ requiresLicense: result.app.environmentByKey.versions?.nodes?.[0]?.requiresLicense,
98
+ permissions: result.app.environmentByKey.versions?.nodes?.[0]?.permissions,
99
+ modules: result.app.environmentByKey.versions?.nodes?.[0]?.extensions?.nodes
100
+ };
101
+ }
102
+ async getVersionList(appId, environmentKey) {
103
+ const query = `
104
+ query forge_cli_getApplicationVersionList($appId: ID!, $first: Int, $after: String) {
105
+ app(id: $appId) {
106
+ environments {
107
+ key
108
+ versions(first: $first, after: $after) {
109
+ nodes {
110
+ version
111
+ }
112
+ pageInfo {
113
+ hasNextPage
114
+ endCursor
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
120
+ `;
121
+ const output = [];
122
+ let cursor = undefined;
123
+ let hasNext = undefined;
124
+ do {
125
+ const result = await this.graphqlClient.query(query, {
126
+ appId,
127
+ first: 20,
128
+ after: cursor
129
+ });
130
+ if (!result.app) {
131
+ throw new MissingAppError();
132
+ }
133
+ if (!result.app.environments) {
134
+ throw new MissingAppVersionError();
135
+ }
136
+ const environment = result.app.environments.filter((env) => env.key === environmentKey)[0];
137
+ cursor = environment?.versions?.pageInfo.endCursor;
138
+ hasNext = environment?.versions?.pageInfo.hasNextPage;
139
+ output.push(...(environment?.versions?.nodes?.map((node) => node?.version) || []).filter((item) => Boolean(item)));
140
+ } while (hasNext && cursor);
141
+ return output;
142
+ }
143
+ }
144
+ exports.AppVersionDetailsClient = AppVersionDetailsClient;
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@forge/cli",
3
- "version": "10.13.6",
3
+ "version": "11.0.0",
4
4
  "description": "A command line interface for managing Atlassian-hosted apps",
5
5
  "author": "Atlassian",
6
- "license": "UNLICENSED",
6
+ "license": "SEE LICENSE IN LICENSE.txt",
7
7
  "bin": {
8
8
  "forge": "out/bin/cli.js"
9
9
  },
@@ -18,16 +18,16 @@
18
18
  "postinstall": "node -e \"fs.existsSync('./out/bin/postinstall.js') && require('./out/bin/postinstall.js')\""
19
19
  },
20
20
  "dependencies": {
21
- "@forge/bundler": "4.20.7",
22
- "@forge/cli-shared": "6.5.4",
23
- "@forge/egress": "1.3.0",
24
- "@forge/lint": "5.6.7",
25
- "@forge/manifest": "8.6.0",
26
- "@forge/runtime": "5.10.4",
27
- "@forge/tunnel": "5.9.1",
28
- "@forge/util": "1.4.6",
21
+ "@forge/bundler": "4.20.8",
22
+ "@forge/cli-shared": "6.6.0",
23
+ "@forge/egress": "1.3.1",
24
+ "@forge/lint": "5.7.0",
25
+ "@forge/manifest": "8.6.1",
26
+ "@forge/runtime": "5.10.5",
27
+ "@forge/tunnel": "5.9.2",
28
+ "@forge/util": "1.4.7",
29
29
  "@sentry/node": "7.106.0",
30
- "@forge/i18n": "0.0.2",
30
+ "@forge/i18n": "0.0.3",
31
31
  "ajv": "^8.12.0",
32
32
  "archiver": "^6.0.2",
33
33
  "case": "^1.6.3",
@@ -39,6 +39,7 @@
39
39
  "cross-spawn": "^7.0.3",
40
40
  "dayjs": "^1.11.10",
41
41
  "didyoumean": "^1.2.2",
42
+ "diff": "^7.0.0",
42
43
  "env-paths": "^2.2.1",
43
44
  "exponential-backoff": "^3.1.1",
44
45
  "form-data": "^4.0.0",
@@ -63,6 +64,7 @@
63
64
  "@types/command-exists": "^1.2.3",
64
65
  "@types/cross-spawn": "^6.0.6",
65
66
  "@types/didyoumean": "^1.2.2",
67
+ "@types/diff": "^6.0.0",
66
68
  "@types/fs-extra": "^11.0.4",
67
69
  "@types/hidefile": "^3.0.3",
68
70
  "@types/inquirer": "^8.2.10",
@@ -1,25 +0,0 @@
1
- /// <reference types="node" />
2
- import { SiteTranslator } from './site-translation';
3
- import { URL } from 'url';
4
- import { Ari } from '@forge/util/packages/ari';
5
- import { GraphQLClient, UserError, EnrichedAri } from '@forge/cli-shared';
6
- export declare class InvalidAtlassianSiteError extends UserError {
7
- constructor(url: URL);
8
- }
9
- declare type CloudIdAndActivationId = {
10
- cloudId: string;
11
- activationId: string;
12
- };
13
- export declare class ActivationIdMissingError extends Error {
14
- constructor(url: string, product: string);
15
- }
16
- export declare class CloudIdTranslator implements SiteTranslator {
17
- private graphqlClient;
18
- constructor(graphqlClient: GraphQLClient);
19
- ariBelongsToProduct(ari: EnrichedAri): boolean;
20
- buildInstallationContext(product: string, site: URL): Promise<Ari>;
21
- getSitesForResourceAris(aris: EnrichedAri[]): Promise<Record<string, string>>;
22
- getCloudIdAndActivationId(site: URL, product: string): Promise<CloudIdAndActivationId>;
23
- }
24
- export {};
25
- //# sourceMappingURL=cloudid-products.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloudid-products.d.ts","sourceRoot":"","sources":["../../../src/installations/site-translation/cloudid-products.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAC/C,OAAO,EACL,aAAa,EAOb,SAAS,EAET,WAAW,EAEZ,MAAM,mBAAmB,CAAC;AAE3B,qBAAa,yBAA0B,SAAQ,SAAS;gBAC1C,GAAG,EAAE,GAAG;CAGrB;AAED,aAAK,sBAAsB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AACxE,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAGzC;AA+BD,qBAAa,iBAAkB,YAAW,cAAc;IAC1C,OAAO,CAAC,aAAa;gBAAb,aAAa,EAAE,aAAa;IAEzC,mBAAmB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO;IAQxC,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IASlE,uBAAuB,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IA2C7E,yBAAyB,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;CAsBpG"}
@@ -1,103 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CloudIdTranslator = exports.ActivationIdMissingError = exports.InvalidAtlassianSiteError = void 0;
4
- const cli_shared_1 = require("@forge/cli-shared");
5
- class InvalidAtlassianSiteError extends cli_shared_1.UserError {
6
- constructor(url) {
7
- super(cli_shared_1.Text.install.error.invalidAtlassianSite(url));
8
- }
9
- }
10
- exports.InvalidAtlassianSiteError = InvalidAtlassianSiteError;
11
- class ActivationIdMissingError extends Error {
12
- constructor(url, product) {
13
- super(cli_shared_1.Text.install.error.activationIdMissing(url, product));
14
- }
15
- }
16
- exports.ActivationIdMissingError = ActivationIdMissingError;
17
- const tenantContextsToCloudIdAndActivationId = (url, contexts, product) => {
18
- if (!contexts.length) {
19
- throw new InvalidAtlassianSiteError(url);
20
- }
21
- const context = contexts[0];
22
- if (!context || !context.cloudId) {
23
- throw new InvalidAtlassianSiteError(url);
24
- }
25
- const activationId = context.activationIdByProduct?.active;
26
- if (!activationId) {
27
- throw new ActivationIdMissingError(url.toString(), product);
28
- }
29
- return { cloudId: context.cloudId, activationId: activationId };
30
- };
31
- const tenantToHostname = (tenantInfo) => {
32
- if (!tenantInfo) {
33
- return null;
34
- }
35
- return tenantInfo.hostName || null;
36
- };
37
- class CloudIdTranslator {
38
- graphqlClient;
39
- constructor(graphqlClient) {
40
- this.graphqlClient = graphqlClient;
41
- }
42
- ariBelongsToProduct(ari) {
43
- return (ari.resourceType === cli_shared_1.SITE_RESOURCE_TYPE ||
44
- (ari.resourceType === cli_shared_1.WORKSPACE_RESOURCE_TYPE &&
45
- ![cli_shared_1.TRELLO_RESOURCE_OWNER, cli_shared_1.BITBUCKET_RESOURCE_OWNER].includes(ari.resourceOwner)));
46
- }
47
- async buildInstallationContext(product, site) {
48
- const lowerCaseProduct = product.toLowerCase();
49
- const { cloudId, activationId } = await this.getCloudIdAndActivationId(site, lowerCaseProduct);
50
- const workspaceAriCreator = cli_shared_1.createWorkspaceAriByProduct[lowerCaseProduct];
51
- const workspaceAri = workspaceAriCreator(cloudId, activationId);
52
- return workspaceAri;
53
- }
54
- async getSitesForResourceAris(aris) {
55
- const MAX_CLOUD_IDS_AT_ONCE = 20;
56
- const cloudIds = [...new Set(aris.map((ari) => ari.derivedCloudId))];
57
- const cloudIdsChunks = [];
58
- for (let i = 0; i < cloudIds.length; i += MAX_CLOUD_IDS_AT_ONCE) {
59
- cloudIdsChunks.push(cloudIds.slice(i, i + MAX_CLOUD_IDS_AT_ONCE));
60
- }
61
- const query = `
62
- query forge_cli_getHostnameForTenantContexts($cloudIds: [ID!]!) {
63
- tenantContexts(cloudIds: $cloudIds) {
64
- hostName
65
- }
66
- }
67
- `;
68
- const results = await Promise.all(cloudIdsChunks.map((cloudIdsChunk) => this.graphqlClient.query(query, {
69
- cloudIds: cloudIdsChunk
70
- })));
71
- const tenantContexts = [].concat(...results.map((result) => result.tenantContexts || []));
72
- const cloudIdToHostname = {};
73
- const ariToHostname = {};
74
- cloudIds.forEach((cloudId, index) => {
75
- const maybeHostname = tenantToHostname(tenantContexts[index]);
76
- cloudIdToHostname[cloudId] = maybeHostname || cloudId;
77
- });
78
- aris.forEach((ari) => {
79
- ariToHostname[ari.toString()] = cloudIdToHostname[ari.derivedCloudId];
80
- });
81
- return ariToHostname;
82
- }
83
- async getCloudIdAndActivationId(site, product) {
84
- const query = `
85
- query getTenantContextDetails($hostNames: [String!], $product: String!) {
86
- tenantContexts(hostNames: $hostNames) {
87
- cloudId
88
- activationIdByProduct(product: $product) {
89
- product
90
- active
91
- }
92
- }
93
- }
94
- `;
95
- const result = await this.graphqlClient.query(query, {
96
- hostNames: [site.hostname],
97
- product
98
- });
99
- const tenantContexts = result.tenantContexts || [];
100
- return tenantContextsToCloudIdAndActivationId(site, tenantContexts, product);
101
- }
102
- }
103
- exports.CloudIdTranslator = CloudIdTranslator;