@forge/api 2.15.0 → 2.15.1-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
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @forge/api
|
|
2
2
|
|
|
3
|
+
## 2.15.1-next.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e91cabc: Route HTTPS calls from the new runtime through @forge/api
|
|
8
|
+
|
|
9
|
+
## 2.15.1-next.0
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 55f66d2: Support fetch through proxy on the Node Runtime
|
|
14
|
+
|
|
3
15
|
## 2.15.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/out/api/fetch.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { RequestInfo, RequestInit, Response } from 'node-fetch';
|
|
3
|
-
import { Url } from 'url';
|
|
4
2
|
import { FetchAPI } from '..';
|
|
5
|
-
declare type FetchFunction = (url: RequestInfo
|
|
3
|
+
declare type FetchFunction = (url: RequestInfo, options?: RequestInit) => Promise<Response>;
|
|
6
4
|
declare type ProxyUrlProvider = 'app' | 'user' | 'none';
|
|
7
5
|
declare type ProxyUrlRemote = 'jira' | 'confluence' | 'stargate' | 'bitbucket';
|
|
8
|
-
|
|
6
|
+
declare type ProxyFetchArgs = {
|
|
7
|
+
type: 'fpp';
|
|
8
|
+
provider: ProxyUrlProvider;
|
|
9
|
+
remote: ProxyUrlRemote;
|
|
10
|
+
} | {
|
|
11
|
+
type: 'egress';
|
|
12
|
+
};
|
|
13
|
+
export declare const createProxyFetch: (args: ProxyFetchArgs) => FetchFunction;
|
|
9
14
|
export declare function getNodeRuntimeAPI(): FetchAPI;
|
|
10
15
|
export declare function getSandboxRuntimeAPI(api: any): FetchAPI;
|
|
11
16
|
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":"AAAA,OAAc,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAW,MAAM,YAAY,CAAC;AAEhF,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAQ9B,aAAK,aAAa,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AACpF,aAAK,gBAAgB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAChD,aAAK,cAAc,GAAG,MAAM,GAAG,YAAY,GAAG,UAAU,GAAG,WAAW,CAAC;AA4BvE,aAAK,cAAc,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAyB/G,eAAO,MAAM,gBAAgB,SAAU,cAAc,KAAG,aAoCrD,CAAC;AAOJ,wBAAgB,iBAAiB,IAAI,QAAQ,CAoB5C;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ,CAEvD"}
|
package/out/api/fetch.js
CHANGED
|
@@ -6,7 +6,6 @@ const node_fetch_1 = tslib_1.__importStar(require("node-fetch"));
|
|
|
6
6
|
const _1 = require(".");
|
|
7
7
|
const runtime_1 = require("./runtime");
|
|
8
8
|
const polyfill_response_1 = require("./polyfill-response");
|
|
9
|
-
const egress_1 = require("@forge/egress");
|
|
10
9
|
const errors_1 = require("./errors");
|
|
11
10
|
const perf_hooks_1 = require("perf_hooks");
|
|
12
11
|
const FORGE_PROXY_UPSTREAM_LATENCY_HEADER = 'forge-proxy-upstream-latency';
|
|
@@ -21,18 +20,38 @@ const remoteToMetric = {
|
|
|
21
20
|
bitbucket: 'requestBitbucket',
|
|
22
21
|
stargate: 'requestAtlassian'
|
|
23
22
|
};
|
|
24
|
-
const metricName = (
|
|
25
|
-
|
|
26
|
-
|
|
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]}`;
|
|
27
32
|
}
|
|
28
|
-
return `api.${providerToMetric[provider]}.${remoteToMetric[remote]}`;
|
|
29
33
|
};
|
|
30
|
-
const
|
|
34
|
+
const createProxyRequest = ({ url: proxyUrl, token }, args, originalRequest) => {
|
|
35
|
+
let proxyRequest;
|
|
36
|
+
switch (args.type) {
|
|
37
|
+
case 'egress':
|
|
38
|
+
proxyRequest = new node_fetch_1.Request(`${proxyUrl}/egress`, originalRequest);
|
|
39
|
+
const url = new URL(originalRequest.url);
|
|
40
|
+
proxyRequest.headers.set('Forge-Proxy-Target-Relative', `${url.pathname}${url.search}`);
|
|
41
|
+
proxyRequest.headers.set('Forge-Proxy-Target-Host', url.hostname);
|
|
42
|
+
break;
|
|
43
|
+
case 'fpp':
|
|
44
|
+
proxyRequest = new node_fetch_1.Request(`${proxyUrl}/fpp/provider/${args.provider}/remote/${args.remote}`, originalRequest);
|
|
45
|
+
proxyRequest.headers.set('Forge-Proxy-Target-Relative', originalRequest.url);
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
proxyRequest.headers.set('Forge-Proxy-Authorization', `Bearer ${token}`);
|
|
49
|
+
return proxyRequest;
|
|
50
|
+
};
|
|
51
|
+
const createProxyFetch = (args) => (0, runtime_1.wrapInMetrics)(metricName(args), async (url, options) => {
|
|
31
52
|
const { proxy, metrics } = (0, runtime_1.getRuntime)();
|
|
32
53
|
const request = new node_fetch_1.Request(url, options);
|
|
33
|
-
const proxyRequest =
|
|
34
|
-
proxyRequest.headers.set('Forge-Proxy-Target-Relative', request.url);
|
|
35
|
-
proxyRequest.headers.set('Forge-Proxy-Authorization', `Bearer ${proxy.token}`);
|
|
54
|
+
const proxyRequest = createProxyRequest(proxy, args, request);
|
|
36
55
|
const requestStart = perf_hooks_1.performance.now();
|
|
37
56
|
const response = await (0, node_fetch_1.default)(proxyRequest);
|
|
38
57
|
const requestEnd = perf_hooks_1.performance.now();
|
|
@@ -41,9 +60,13 @@ const createProxyFetch = (provider, remote) => (0, runtime_1.wrapInMetrics)(metr
|
|
|
41
60
|
metrics.timing('proxy-success-overhead').set(requestEnd - requestStart - proxyUpstreamLatency);
|
|
42
61
|
}
|
|
43
62
|
if (response.headers.has('forge-proxy-error')) {
|
|
44
|
-
|
|
63
|
+
const errorReason = response.headers.get('forge-proxy-error');
|
|
64
|
+
if (errorReason === 'NEEDS_AUTHENTICATION_ERR') {
|
|
45
65
|
throw new errors_1.NeedsAuthenticationError('Authentication Required', ATLASSIAN_TOKEN_SERVICE_KEY);
|
|
46
66
|
}
|
|
67
|
+
if (errorReason === 'BLOCKED_EGRESS') {
|
|
68
|
+
throw new errors_1.ExternalEndpointNotAllowedError(request.url);
|
|
69
|
+
}
|
|
47
70
|
throw new errors_1.ProxyRequestError(response.status, response.headers.get('forge-proxy-error'));
|
|
48
71
|
}
|
|
49
72
|
return response;
|
|
@@ -52,32 +75,24 @@ exports.createProxyFetch = createProxyFetch;
|
|
|
52
75
|
const throwNotImplementedError = () => {
|
|
53
76
|
throw new Error('not implemented');
|
|
54
77
|
};
|
|
55
|
-
const wrapExternalEgress = (url, options) => {
|
|
56
|
-
const { allowedEgress } = (0, runtime_1.getRuntime)();
|
|
57
|
-
const egressFilteringService = new egress_1.EgressFilteringService(allowedEgress);
|
|
58
|
-
if (!egressFilteringService.isValidUrl(url)) {
|
|
59
|
-
throw new Error(`URL not included in the external fetch backend permissions: ${url}. Visit go.atlassian.com/forge-egress for more information.`);
|
|
60
|
-
}
|
|
61
|
-
return (0, node_fetch_1.default)(url, options);
|
|
62
|
-
};
|
|
63
78
|
function getNodeRuntimeAPI() {
|
|
64
79
|
return {
|
|
65
|
-
fetch: (0, _1.wrapWithRouteUnwrapper)(
|
|
66
|
-
requestJira: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)('none', 'jira')),
|
|
67
|
-
requestConfluence: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)('none', 'confluence')),
|
|
68
|
-
requestBitbucket: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)('none', 'bitbucket')),
|
|
80
|
+
fetch: (0, _1.wrapWithRouteUnwrapper)((0, exports.createProxyFetch)({ type: 'egress' })),
|
|
81
|
+
requestJira: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)({ type: 'fpp', provider: 'none', remote: 'jira' })),
|
|
82
|
+
requestConfluence: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)({ type: 'fpp', provider: 'none', remote: 'confluence' })),
|
|
83
|
+
requestBitbucket: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)({ type: 'fpp', provider: 'none', remote: 'bitbucket' })),
|
|
69
84
|
asUser: () => ({
|
|
70
|
-
requestJira: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)('user', 'jira')),
|
|
71
|
-
requestConfluence: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)('user', 'confluence')),
|
|
72
|
-
requestBitbucket: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)('user', 'bitbucket')),
|
|
73
|
-
requestGraph: (0, _1.wrapRequestGraph)((0, exports.createProxyFetch)('user', 'stargate')),
|
|
85
|
+
requestJira: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)({ type: 'fpp', provider: 'user', remote: 'jira' })),
|
|
86
|
+
requestConfluence: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)({ type: 'fpp', provider: 'user', remote: 'confluence' })),
|
|
87
|
+
requestBitbucket: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)({ type: 'fpp', provider: 'user', remote: 'bitbucket' })),
|
|
88
|
+
requestGraph: (0, _1.wrapRequestGraph)((0, exports.createProxyFetch)({ type: 'fpp', provider: 'user', remote: 'stargate' })),
|
|
74
89
|
withProvider: throwNotImplementedError
|
|
75
90
|
}),
|
|
76
91
|
asApp: () => ({
|
|
77
|
-
requestJira: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)('app', 'jira')),
|
|
78
|
-
requestConfluence: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)('app', 'confluence')),
|
|
79
|
-
requestBitbucket: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)('app', 'bitbucket')),
|
|
80
|
-
requestGraph: (0, _1.wrapRequestGraph)((0, exports.createProxyFetch)('app', 'stargate'))
|
|
92
|
+
requestJira: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)({ type: 'fpp', provider: 'app', remote: 'jira' })),
|
|
93
|
+
requestConfluence: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)({ type: 'fpp', provider: 'app', remote: 'confluence' })),
|
|
94
|
+
requestBitbucket: (0, _1.wrapRequestProduct)((0, exports.createProxyFetch)({ type: 'fpp', provider: 'app', remote: 'bitbucket' })),
|
|
95
|
+
requestGraph: (0, _1.wrapRequestGraph)((0, exports.createProxyFetch)({ type: 'fpp', provider: 'app', remote: 'stargate' }))
|
|
81
96
|
})
|
|
82
97
|
};
|
|
83
98
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-and-storage.d.ts","sourceRoot":"","sources":["../../src/runtime/fetch-and-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA2C,MAAM,cAAc,CAAC;AAGzF,eAAO,MAAM,0BAA0B,EAAE,MAAM,UAAU,CAAC,OAAO,gBAAgB,
|
|
1
|
+
{"version":3,"file":"fetch-and-storage.d.ts","sourceRoot":"","sources":["../../src/runtime/fetch-and-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA2C,MAAM,cAAc,CAAC;AAGzF,eAAO,MAAM,0BAA0B,EAAE,MAAM,UAAU,CAAC,OAAO,gBAAgB,CAET,CAAC;AAEzE,eAAO,MAAM,aAAa,WAQzB,CAAC;AAEF,eAAO,MAAM,WAAW,6BAOvB,CAAC"}
|
|
@@ -3,7 +3,10 @@ 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 = () => {
|
|
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
|
+
};
|
|
7
10
|
exports.createRequestStargateAsApp = createRequestStargateAsApp;
|
|
8
11
|
const getContextAri = () => {
|
|
9
12
|
var _a;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge/api",
|
|
3
|
-
"version": "2.15.
|
|
3
|
+
"version": "2.15.1-next.1",
|
|
4
4
|
"description": "Forge API methods",
|
|
5
5
|
"author": "Atlassian",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@forge/runtime": "4.3.1",
|
|
16
16
|
"@forge/util": "1.2.2",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
17
|
+
"@types/node": "14.18.42",
|
|
18
|
+
"jest-matcher-specific-error": "^1.0.0",
|
|
19
|
+
"nock": "^10.0.6"
|
|
19
20
|
},
|
|
20
21
|
"dependencies": {
|
|
21
22
|
"@forge/auth": "0.0.1",
|