@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.
- package/CHANGELOG.md +203 -0
- package/LICENSE.txt +7 -0
- package/npm-shrinkwrap.json +142 -130
- package/out/autocomplete/autocomplete-config.json +26 -0
- package/out/command-line/command.d.ts +15 -2
- package/out/command-line/command.d.ts.map +1 -1
- package/out/command-line/command.js +29 -6
- package/out/command-line/controller/deploy-controller.d.ts.map +1 -1
- package/out/command-line/controller/deploy-controller.js +4 -7
- package/out/command-line/controller/install-controller.d.ts +3 -3
- package/out/command-line/controller/install-controller.d.ts.map +1 -1
- package/out/command-line/controller/install-controller.js +16 -13
- package/out/command-line/controller/version-controller.d.ts +36 -0
- package/out/command-line/controller/version-controller.d.ts.map +1 -0
- package/out/command-line/controller/version-controller.js +114 -0
- package/out/command-line/dependency-injection.d.ts +4 -1
- package/out/command-line/dependency-injection.d.ts.map +1 -1
- package/out/command-line/dependency-injection.js +14 -6
- package/out/command-line/index.d.ts +1 -1
- package/out/command-line/index.d.ts.map +1 -1
- package/out/command-line/index.js +6 -4
- package/out/command-line/register-app-commands.d.ts.map +1 -1
- package/out/command-line/register-app-commands.js +9 -1
- package/out/command-line/register-installation-commands.d.ts +2 -10
- package/out/command-line/register-installation-commands.d.ts.map +1 -1
- package/out/command-line/register-installation-commands.js +29 -32
- package/out/command-line/register-version-commands.d.ts +4 -0
- package/out/command-line/register-version-commands.d.ts.map +1 -0
- package/out/command-line/register-version-commands.js +76 -0
- package/out/command-line/register-webtrigger-commands.d.ts +1 -1
- package/out/command-line/register-webtrigger-commands.d.ts.map +1 -1
- package/out/command-line/register-webtrigger-commands.js +13 -5
- package/out/command-line/view/deploy-view.d.ts +1 -1
- package/out/command-line/view/deploy-view.d.ts.map +1 -1
- package/out/command-line/view/deploy-view.js +2 -2
- package/out/command-line/view/version-view.d.ts +26 -0
- package/out/command-line/view/version-view.d.ts.map +1 -0
- package/out/command-line/view/version-view.js +198 -0
- package/out/environment/graphql-client.d.ts +1 -0
- package/out/environment/graphql-client.d.ts.map +1 -1
- package/out/environment/graphql-client.js +3 -1
- package/out/environment/list-environment.d.ts +1 -0
- package/out/environment/list-environment.d.ts.map +1 -1
- package/out/installations/graphql-client.d.ts +6 -5
- package/out/installations/graphql-client.d.ts.map +1 -1
- package/out/installations/graphql-client.js +44 -7
- package/out/installations/installation-helper.d.ts.map +1 -1
- package/out/installations/installation-helper.js +1 -1
- package/out/installations/site-translation/bitbucket.d.ts +3 -4
- package/out/installations/site-translation/bitbucket.d.ts.map +1 -1
- package/out/installations/site-translation/bitbucket.js +1 -1
- package/out/installations/site-translation/index.d.ts +1 -1
- package/out/installations/site-translation/index.d.ts.map +1 -1
- package/out/installations/site-translation/index.js +1 -1
- package/out/installations/site-translation/site-translation.d.ts +3 -4
- package/out/installations/site-translation/site-translation.d.ts.map +1 -1
- package/out/installations/site-translation/sited-products.d.ts +29 -0
- package/out/installations/site-translation/sited-products.d.ts.map +1 -0
- package/out/installations/site-translation/sited-products.js +133 -0
- package/out/service/installation-service.d.ts +18 -4
- package/out/service/installation-service.d.ts.map +1 -1
- package/out/service/installation-service.js +44 -10
- package/out/service/tunnel-service.d.ts.map +1 -1
- package/out/service/tunnel-service.js +1 -1
- package/out/service/version-service.d.ts +77 -0
- package/out/service/version-service.d.ts.map +1 -0
- package/out/service/version-service.js +163 -0
- package/out/version/graphql-client.d.ts +25 -0
- package/out/version/graphql-client.d.ts.map +1 -0
- package/out/version/graphql-client.js +144 -0
- package/package.json +13 -11
- package/out/installations/site-translation/cloudid-products.d.ts +0 -25
- package/out/installations/site-translation/cloudid-products.d.ts.map +0 -1
- 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?:
|
|
31
|
-
product?:
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
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"}
|