@forge/api 2.18.3-next.0 → 2.18.3-next.1
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 +6 -0
- package/out/api/fetch.d.ts +9 -13
- package/out/api/fetch.d.ts.map +1 -1
- package/out/api/fetch.js +34 -144
- package/out/api/index.d.ts.map +1 -1
- package/out/api/polyfill-response.d.ts.map +1 -1
- package/out/runtime/fetch-and-storage.d.ts +2 -2
- package/out/runtime/fetch-and-storage.d.ts.map +1 -1
- package/out/runtime/fetch-and-storage.js +1 -4
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
package/out/api/fetch.d.ts
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { FetchAPI } from '..';
|
|
3
|
-
type
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
provider: ProxyUrlProvider;
|
|
9
|
-
remote: ProxyUrlRemote;
|
|
10
|
-
} | {
|
|
11
|
-
type: 'egress';
|
|
1
|
+
import { RequestInit } from 'node-fetch';
|
|
2
|
+
import { FetchAPI, FetchMethod } from '..';
|
|
3
|
+
type AuthProvider = 'app' | 'user' | 'none';
|
|
4
|
+
type RemoteAPI = 'jira' | 'confluence' | 'stargate' | 'bitbucket';
|
|
5
|
+
type FetchArgs = {
|
|
6
|
+
provider: AuthProvider;
|
|
7
|
+
remote: RemoteAPI;
|
|
12
8
|
};
|
|
13
|
-
export declare
|
|
14
|
-
export declare const
|
|
9
|
+
export declare function fetchProduct(args: FetchArgs): FetchMethod;
|
|
10
|
+
export declare const addMagicAgent: (init?: RequestInit) => RequestInit;
|
|
15
11
|
export declare function getNodeRuntimeAPI(): FetchAPI;
|
|
16
12
|
export declare function getSandboxRuntimeAPI(api: any): FetchAPI;
|
|
17
13
|
export {};
|
package/out/api/fetch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/api/fetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/api/fetch.ts"],"names":[],"mappings":"AAEA,OAAc,EAAE,WAAW,EAAY,MAAM,YAAY,CAAC;AAG1D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAI3C,KAAK,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAC5C,KAAK,SAAS,GAAG,MAAM,GAAG,YAAY,GAAG,UAAU,GAAG,WAAW,CAAC;AAElE,KAAK,SAAS,GAAG;IAAE,QAAQ,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,SAAS,CAAA;CAAE,CAAC;AAS/D,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW,CAkBzD;AAgCD,eAAO,MAAM,aAAa,EAAE,CAAC,IAAI,CAAC,EAAE,WAAW,KAAK,WAGlD,CAAC;AAOH,wBAAgB,iBAAiB,IAAI,QAAQ,CAoB5C;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ,CAEvD"}
|
package/out/api/fetch.js
CHANGED
|
@@ -1,171 +1,61 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getSandboxRuntimeAPI = exports.getNodeRuntimeAPI = exports.
|
|
3
|
+
exports.getSandboxRuntimeAPI = exports.getNodeRuntimeAPI = exports.addMagicAgent = exports.fetchProduct = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const node_fetch_1 = tslib_1.
|
|
5
|
+
const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
|
6
6
|
const _1 = require(".");
|
|
7
|
-
const runtime_1 = require("./runtime");
|
|
8
7
|
const polyfill_response_1 = require("./polyfill-response");
|
|
9
8
|
const errors_1 = require("./errors");
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
function fetchProduct(args) {
|
|
10
|
+
return async (path, init) => {
|
|
11
|
+
const url = productURL(args.remote, path);
|
|
12
|
+
init = (0, exports.addMagicAgent)(init);
|
|
13
|
+
init.headers = Object.assign(Object.assign({}, init.headers), { authorization: `Forge ${args.provider}` });
|
|
14
|
+
const response = await (0, node_fetch_1.default)(url, init);
|
|
15
|
+
handleProxyResponseErrors(response);
|
|
16
|
+
return response;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
exports.fetchProduct = fetchProduct;
|
|
12
20
|
const ATLASSIAN_TOKEN_SERVICE_KEY = 'atlassian-token-service-key';
|
|
13
|
-
const
|
|
14
|
-
app: 'asApp',
|
|
15
|
-
user: 'asUser'
|
|
16
|
-
};
|
|
17
|
-
const remoteToMetric = {
|
|
18
|
-
jira: 'requestJira',
|
|
19
|
-
confluence: 'requestConfluence',
|
|
20
|
-
bitbucket: 'requestBitbucket',
|
|
21
|
-
stargate: 'requestAtlassian'
|
|
22
|
-
};
|
|
23
|
-
const metricName = (args) => {
|
|
24
|
-
switch (args.type) {
|
|
25
|
-
case 'egress':
|
|
26
|
-
return 'api.fetch';
|
|
27
|
-
case 'fpp':
|
|
28
|
-
if (args.provider === 'none') {
|
|
29
|
-
return `api.${remoteToMetric[args.remote]}`;
|
|
30
|
-
}
|
|
31
|
-
return `api.${providerToMetric[args.provider]}.${remoteToMetric[args.remote]}`;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
const createProxyRequest = ({ url: proxyUrl, token, host }, args, originalRequest) => {
|
|
35
|
-
let proxyEndpoint;
|
|
36
|
-
switch (args.type) {
|
|
37
|
-
case 'egress':
|
|
38
|
-
proxyEndpoint = `${proxyUrl}/egress`;
|
|
39
|
-
break;
|
|
40
|
-
case 'fpp':
|
|
41
|
-
proxyEndpoint = `${proxyUrl}/fpp/provider/${args.provider}/remote/${args.remote}`;
|
|
42
|
-
break;
|
|
43
|
-
}
|
|
44
|
-
const tempRequest = new node_fetch_1.Request(proxyEndpoint, originalRequest);
|
|
45
|
-
const proxyRequest = new node_fetch_1.Request(tempRequest, { redirect: 'manual' });
|
|
46
|
-
proxyRequest.headers.set('Forge-Proxy-Target', originalRequest.url);
|
|
47
|
-
proxyRequest.headers.set('Forge-Proxy-Authorization', `Bearer ${token}`);
|
|
48
|
-
if (host) {
|
|
49
|
-
proxyRequest.headers.set('Host', host);
|
|
50
|
-
}
|
|
51
|
-
return proxyRequest;
|
|
52
|
-
};
|
|
53
|
-
const wrapWithOverheadMetric = async (fetch, metrics) => {
|
|
54
|
-
const requestStart = perf_hooks_1.performance.now();
|
|
55
|
-
const response = await fetch;
|
|
56
|
-
const requestEnd = perf_hooks_1.performance.now();
|
|
57
|
-
const proxyUpstreamLatency = parseInt(response.headers.get(FORGE_PROXY_UPSTREAM_LATENCY_HEADER) || '');
|
|
58
|
-
if (proxyUpstreamLatency) {
|
|
59
|
-
metrics.timing('proxy-success-overhead').set(requestEnd - requestStart - proxyUpstreamLatency);
|
|
60
|
-
}
|
|
61
|
-
return response;
|
|
62
|
-
};
|
|
63
|
-
const getRedirectArgs = (args, response) => {
|
|
64
|
-
const proxyRelativeLocation = response.headers.get('forge-proxy-relative-location');
|
|
65
|
-
if (!proxyRelativeLocation) {
|
|
66
|
-
return { type: 'egress' };
|
|
67
|
-
}
|
|
68
|
-
return args;
|
|
69
|
-
};
|
|
70
|
-
const buildGetRequest = (url, originalRequest) => {
|
|
71
|
-
const request = new node_fetch_1.Request(url, { method: 'GET' });
|
|
72
|
-
for (const [name, values] of Array.from(originalRequest.headers.entries())) {
|
|
73
|
-
if (!name.toLowerCase().startsWith('content-')) {
|
|
74
|
-
request.headers.set(name, values);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return request;
|
|
78
|
-
};
|
|
79
|
-
const getLocation = (responseHeaders) => {
|
|
80
|
-
const location = responseHeaders.get('location');
|
|
81
|
-
if (!location) {
|
|
82
|
-
throw new errors_1.FetchError('Redirect location is empty');
|
|
83
|
-
}
|
|
84
|
-
return location;
|
|
85
|
-
};
|
|
86
|
-
const getRedirectUrl = (responseHeaders, original, isFromEgress) => {
|
|
87
|
-
if (!isFromEgress) {
|
|
88
|
-
return responseHeaders.get('forge-proxy-relative-location') || getLocation(responseHeaders);
|
|
89
|
-
}
|
|
90
|
-
return new URL(getLocation(responseHeaders), original).toString();
|
|
91
|
-
};
|
|
92
|
-
exports.getRedirectUrl = getRedirectUrl;
|
|
93
|
-
const buildRedirectedRequest = (response, originalRequest, isFromEgress) => {
|
|
94
|
-
const url = (0, exports.getRedirectUrl)(response.headers, originalRequest.url, isFromEgress);
|
|
95
|
-
if (response.status === 303) {
|
|
96
|
-
return buildGetRequest(url, originalRequest);
|
|
97
|
-
}
|
|
98
|
-
return new node_fetch_1.Request(url, originalRequest);
|
|
99
|
-
};
|
|
100
|
-
const fetchViaProxy = async ({ proxy, proxyFetchArgs, request, metrics, count = 0 }) => {
|
|
101
|
-
const REDIRECT_STATUS = [300, 301, 302, 303, 307, 308];
|
|
102
|
-
const MAX_REDIRECTS = 20;
|
|
103
|
-
if (count >= MAX_REDIRECTS) {
|
|
104
|
-
throw new errors_1.FetchError('Max redirects exceeded');
|
|
105
|
-
}
|
|
106
|
-
const proxyRequest = createProxyRequest(proxy, proxyFetchArgs, request);
|
|
107
|
-
if (request.redirect === 'manual' && count === 0) {
|
|
108
|
-
return wrapWithOverheadMetric((0, node_fetch_1.default)(proxyRequest), metrics);
|
|
109
|
-
}
|
|
110
|
-
const response = await wrapWithOverheadMetric((0, node_fetch_1.default)(proxyRequest), metrics);
|
|
111
|
-
if (REDIRECT_STATUS.includes(response.status)) {
|
|
112
|
-
const redirectedRequest = buildRedirectedRequest(response, request, proxyFetchArgs.type === 'egress');
|
|
113
|
-
const redirectedArgs = getRedirectArgs(proxyFetchArgs, response);
|
|
114
|
-
return fetchViaProxy({
|
|
115
|
-
proxy,
|
|
116
|
-
proxyFetchArgs: redirectedArgs,
|
|
117
|
-
request: redirectedRequest,
|
|
118
|
-
metrics,
|
|
119
|
-
count: count + 1
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
return response;
|
|
123
|
-
};
|
|
124
|
-
const handleProxyResponseErrors = (response, requestUrl) => {
|
|
21
|
+
const handleProxyResponseErrors = (response) => {
|
|
125
22
|
if (response.headers.has('forge-proxy-error')) {
|
|
126
23
|
const errorReason = response.headers.get('forge-proxy-error');
|
|
127
24
|
if (errorReason === 'NEEDS_AUTHENTICATION_ERR') {
|
|
128
25
|
throw new errors_1.NeedsAuthenticationError('Authentication Required', ATLASSIAN_TOKEN_SERVICE_KEY);
|
|
129
26
|
}
|
|
130
|
-
if (errorReason === 'BLOCKED_EGRESS') {
|
|
131
|
-
throw new errors_1.ExternalEndpointNotAllowedError(requestUrl);
|
|
132
|
-
}
|
|
133
27
|
throw new errors_1.ProxyRequestError(response.status, response.headers.get('forge-proxy-error'));
|
|
134
28
|
}
|
|
135
29
|
};
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
handleProxyResponseErrors(response, url.toString());
|
|
145
|
-
return response;
|
|
146
|
-
}, { tags: { proxy: 'true' } });
|
|
147
|
-
exports.createProxyFetch = createProxyFetch;
|
|
30
|
+
function productURL(remote, path) {
|
|
31
|
+
if (!path.startsWith('/')) {
|
|
32
|
+
path = '/' + path;
|
|
33
|
+
}
|
|
34
|
+
return `https://${remote}${path}`;
|
|
35
|
+
}
|
|
36
|
+
const addMagicAgent = (init) => (Object.assign(Object.assign({}, init), { agent: 'FORGE_PRODUCT_REQUEST' }));
|
|
37
|
+
exports.addMagicAgent = addMagicAgent;
|
|
148
38
|
const throwNotImplementedError = () => {
|
|
149
39
|
throw new Error('not implemented');
|
|
150
40
|
};
|
|
151
41
|
function getNodeRuntimeAPI() {
|
|
152
42
|
return {
|
|
153
|
-
fetch: (0, _1.wrapWithRouteUnwrapper)(
|
|
154
|
-
requestJira: (0, _1.wrapRequestProduct)((
|
|
155
|
-
requestConfluence: (0, _1.wrapRequestProduct)((
|
|
156
|
-
requestBitbucket: (0, _1.wrapRequestProduct)((
|
|
43
|
+
fetch: (0, _1.wrapWithRouteUnwrapper)(node_fetch_1.default),
|
|
44
|
+
requestJira: (0, _1.wrapRequestProduct)(fetchProduct({ provider: 'none', remote: 'jira' })),
|
|
45
|
+
requestConfluence: (0, _1.wrapRequestProduct)(fetchProduct({ provider: 'none', remote: 'confluence' })),
|
|
46
|
+
requestBitbucket: (0, _1.wrapRequestProduct)(fetchProduct({ provider: 'none', remote: 'bitbucket' })),
|
|
157
47
|
asUser: () => ({
|
|
158
|
-
requestJira: (0, _1.wrapRequestProduct)((
|
|
159
|
-
requestConfluence: (0, _1.wrapRequestProduct)((
|
|
160
|
-
requestBitbucket: (0, _1.wrapRequestProduct)((
|
|
161
|
-
requestGraph: (0, _1.wrapRequestGraph)((
|
|
48
|
+
requestJira: (0, _1.wrapRequestProduct)(fetchProduct({ provider: 'user', remote: 'jira' })),
|
|
49
|
+
requestConfluence: (0, _1.wrapRequestProduct)(fetchProduct({ provider: 'user', remote: 'confluence' })),
|
|
50
|
+
requestBitbucket: (0, _1.wrapRequestProduct)(fetchProduct({ provider: 'user', remote: 'bitbucket' })),
|
|
51
|
+
requestGraph: (0, _1.wrapRequestGraph)(fetchProduct({ provider: 'user', remote: 'stargate' })),
|
|
162
52
|
withProvider: throwNotImplementedError
|
|
163
53
|
}),
|
|
164
54
|
asApp: () => ({
|
|
165
|
-
requestJira: (0, _1.wrapRequestProduct)((
|
|
166
|
-
requestConfluence: (0, _1.wrapRequestProduct)((
|
|
167
|
-
requestBitbucket: (0, _1.wrapRequestProduct)((
|
|
168
|
-
requestGraph: (0, _1.wrapRequestGraph)((
|
|
55
|
+
requestJira: (0, _1.wrapRequestProduct)(fetchProduct({ provider: 'app', remote: 'jira' })),
|
|
56
|
+
requestConfluence: (0, _1.wrapRequestProduct)(fetchProduct({ provider: 'app', remote: 'confluence' })),
|
|
57
|
+
requestBitbucket: (0, _1.wrapRequestProduct)(fetchProduct({ provider: 'app', remote: 'bitbucket' })),
|
|
58
|
+
requestGraph: (0, _1.wrapRequestGraph)(fetchProduct({ provider: 'app', remote: 'stargate' }))
|
|
169
59
|
})
|
|
170
60
|
};
|
|
171
61
|
}
|
package/out/api/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EACL,QAAQ,EAER,WAAW,EAEX,oBAAoB,EACpB,wBAAwB,EAGxB,WAAW,EACZ,MAAM,IAAI,CAAC;AAIZ,MAAM,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AAElH,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EACL,QAAQ,EAER,WAAW,EAEX,oBAAoB,EACpB,wBAAwB,EAGxB,WAAW,EACZ,MAAM,IAAI,CAAC;AAIZ,MAAM,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AAElH,eAAO,MAAM,gBAAgB,oBACT,WAAW,aACrB,MAAM,cAAc,GAAG,uCAQ3B,CAAC;AAEP,eAAO,MAAM,kBAAkB,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,oBAGpD,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,wBAGxD,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAS,GAAG,aAAa,YAAY,KAAG,QAkCvE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"polyfill-response.d.ts","sourceRoot":"","sources":["../../src/api/polyfill-response.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,CAAC;AAGjC,eAAO,MAAM,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"polyfill-response.d.ts","sourceRoot":"","sources":["../../src/api/polyfill-response.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,CAAC;AAGjC,eAAO,MAAM,iBAAiB,EAAE,YAQ7B,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const createRequestStargateAsApp: () =>
|
|
1
|
+
import { FetchMethod } from '..';
|
|
2
|
+
export declare const createRequestStargateAsApp: () => FetchMethod;
|
|
3
3
|
export declare const getContextAri: () => any;
|
|
4
4
|
export declare const getFetchAPI: () => import("..").FetchAPI;
|
|
5
5
|
//# sourceMappingURL=fetch-and-storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-and-storage.d.ts","sourceRoot":"","sources":["../../src/runtime/fetch-and-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"fetch-and-storage.d.ts","sourceRoot":"","sources":["../../src/runtime/fetch-and-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAIjC,eAAO,MAAM,0BAA0B,EAAE,MAAM,WAC2D,CAAC;AAE3G,eAAO,MAAM,aAAa,WAQzB,CAAC;AAEF,eAAO,MAAM,WAAW,6BAOvB,CAAC"}
|
|
@@ -3,10 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getFetchAPI = exports.getContextAri = exports.createRequestStargateAsApp = void 0;
|
|
4
4
|
const fetch_1 = require("../api/fetch");
|
|
5
5
|
const runtime_1 = require("../api/runtime");
|
|
6
|
-
const createRequestStargateAsApp = () => {
|
|
7
|
-
var _a, _b;
|
|
8
|
-
return (_b = (_a = global.api) === null || _a === void 0 ? void 0 : _a.asApp().__requestAtlassian) !== null && _b !== void 0 ? _b : (0, fetch_1.createProxyFetch)({ type: 'fpp', provider: 'app', remote: 'stargate' });
|
|
9
|
-
};
|
|
6
|
+
const createRequestStargateAsApp = () => { var _a, _b; return (_b = (_a = global.api) === null || _a === void 0 ? void 0 : _a.asApp().__requestAtlassian) !== null && _b !== void 0 ? _b : (0, fetch_1.fetchProduct)({ provider: 'app', remote: 'stargate' }); };
|
|
10
7
|
exports.createRequestStargateAsApp = createRequestStargateAsApp;
|
|
11
8
|
const getContextAri = () => {
|
|
12
9
|
var _a;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge/api",
|
|
3
|
-
"version": "2.18.3-next.
|
|
3
|
+
"version": "2.18.3-next.1",
|
|
4
4
|
"description": "Forge API methods",
|
|
5
5
|
"author": "Atlassian",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"compile": "tsc -b -v"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@forge/runtime": "4.4.5-next.
|
|
15
|
+
"@forge/runtime": "4.4.5-next.1",
|
|
16
16
|
"@types/node": "14.18.53",
|
|
17
17
|
"jest-matcher-specific-error": "^1.0.0",
|
|
18
18
|
"nock": "^10.0.6"
|