New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@graphql-tools/executor-http

Package Overview
Dependencies
Maintainers
0
Versions
1072
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@graphql-tools/executor-http - npm Package Compare versions

Comparing version

to
1.3.0-alpha-97aa61c442facee49ab18af23145184fd1cb236c

13

CHANGELOG.md
# @graphql-tools/executor-http
## 1.2.9-rc-fa9af4651df2ba248ee59d3d4b64dfd70b45e988
## 1.3.0-alpha-97aa61c442facee49ab18af23145184fd1cb236c
### Minor Changes
- [#792](https://github.com/graphql-hive/gateway/pull/792) [`9af6aae`](https://github.com/graphql-hive/gateway/commit/9af6aae2beec0dc73952b2972b4ed66f27d9dd78) Thanks [@ardatan](https://github.com/ardatan)! - Ensure subgraph name is present in the upstream error extensions when HTTP Executor throws
### Patch Changes

@@ -19,2 +23,9 @@

- [#791](https://github.com/graphql-hive/gateway/pull/791) [`661b103`](https://github.com/graphql-hive/gateway/commit/661b103a7b9586641e69b78cbaad516e550e7192) Thanks [@ardatan](https://github.com/ardatan)! - dependencies updates:
- Removed dependency [`value-or-promise@^1.0.12` ↗︎](https://www.npmjs.com/package/value-or-promise/v/1.0.12) (from `dependencies`)
- Updated dependencies [[`e393337`](https://github.com/graphql-hive/gateway/commit/e393337ecb40beffb79748b19b5aa8f2fd9197b7)]:
- @graphql-tools/executor-common@0.0.4-alpha-97aa61c442facee49ab18af23145184fd1cb236c
## 1.2.8

@@ -21,0 +32,0 @@

@@ -18,2 +18,6 @@ import { ExecutionRequest, DisposableSyncExecutor, DisposableAsyncExecutor } from '@graphql-tools/utils';

/**
* The name of the service
*/
serviceName?: string;
/**
* The endpoint to use when querying the upstream API

@@ -20,0 +24,0 @@ * @default '/graphql'

317

dist/index.js

@@ -6,3 +6,2 @@ import { defaultPrintFn, serializeExecutionRequest } from '@graphql-tools/executor-common';

import { isPromise, handleMaybePromise } from '@whatwg-node/promise-helpers';
import { ValueOrPromise } from 'value-or-promise';
import { Repeater } from '@repeaterjs/repeater';

@@ -522,2 +521,3 @@ import { GraphQLError } from 'graphql';

const disposeCtrl = new AbortController();
const serviceName = options?.serviceName;
const baseExecutor = (request, excludeQuery) => {

@@ -572,2 +572,3 @@ if (disposeCtrl.signal.aborted) {

const upstreamErrorExtensions = {
serviceName,
request: {

@@ -607,160 +608,176 @@ method

}
function handleError(e) {
if (e.name === "AggregateError") {
return {
errors: e.errors.map(
(e2) => coerceFetchError(e2, {
signal,
endpoint,
upstreamErrorExtensions
})
)
};
}
return {
errors: [
coerceFetchError(e, {
signal,
endpoint,
upstreamErrorExtensions
})
]
};
}
return handleMaybePromise(
() => serializeFn(),
(body) => new ValueOrPromise(() => {
switch (method) {
case "GET": {
const finalUrl = prepareGETUrl({
baseUrl: endpoint,
body
});
const fetchOptions = {
method: "GET",
headers,
signal
};
if (options?.credentials != null) {
fetchOptions.credentials = options.credentials;
(body) => handleMaybePromise(
() => {
switch (method) {
case "GET": {
const finalUrl = prepareGETUrl({
baseUrl: endpoint,
body
});
const fetchOptions = {
method: "GET",
headers,
signal
};
if (options?.credentials != null) {
fetchOptions.credentials = options.credentials;
}
upstreamErrorExtensions.request.url = finalUrl;
return fetchFn(
finalUrl,
fetchOptions,
request.context,
request.info
);
}
upstreamErrorExtensions.request.url = finalUrl;
return fetchFn(
finalUrl,
fetchOptions,
request.context,
request.info
);
case "POST": {
upstreamErrorExtensions.request.body = body;
return handleMaybePromise(
() => createFormDataFromVariables(body, {
File: options?.File,
FormData: options?.FormData
}),
(body2) => {
if (typeof body2 === "string" && !headers["content-type"]) {
upstreamErrorExtensions.request.body = body2;
headers["content-type"] = "application/json";
}
const fetchOptions = {
method: "POST",
body: body2,
headers,
signal
};
if (options?.credentials != null) {
fetchOptions.credentials = options.credentials;
}
return fetchFn(
endpoint,
fetchOptions,
request.context,
request.info
);
},
handleError
);
}
}
case "POST": {
upstreamErrorExtensions.request.body = body;
return handleMaybePromise(
() => createFormDataFromVariables(body, {
File: options?.File,
FormData: options?.FormData
}),
(body2) => {
if (typeof body2 === "string" && !headers["content-type"]) {
upstreamErrorExtensions.request.body = body2;
headers["content-type"] = "application/json";
},
(fetchResult) => handleMaybePromise(
() => {
upstreamErrorExtensions.response ||= {};
upstreamErrorExtensions.response.status = fetchResult.status;
upstreamErrorExtensions.response.statusText = fetchResult.statusText;
Object.defineProperty(
upstreamErrorExtensions.response,
"headers",
{
get() {
return Object.fromEntries(fetchResult.headers.entries());
}
const fetchOptions = {
method: "POST",
body: body2,
headers,
signal
};
if (options?.credentials != null) {
fetchOptions.credentials = options.credentials;
}
return fetchFn(
endpoint,
fetchOptions,
request.context,
request.info
);
}
);
}
}
}).then((fetchResult) => {
upstreamErrorExtensions.response ||= {};
upstreamErrorExtensions.response.status = fetchResult.status;
upstreamErrorExtensions.response.statusText = fetchResult.statusText;
Object.defineProperty(upstreamErrorExtensions.response, "headers", {
get() {
return Object.fromEntries(fetchResult.headers.entries());
}
});
if (options?.retry != null && !fetchResult.status.toString().startsWith("2")) {
throw new Error(
fetchResult.statusText || `Upstream HTTP Error: ${fetchResult.status}`
);
}
const contentType = fetchResult.headers.get("content-type");
if (contentType?.includes("text/event-stream")) {
return handleEventStreamResponse(
fetchResult,
subscriptionCtrl,
signal
);
} else if (contentType?.includes("multipart/mixed")) {
return handleMultipartMixedResponse(fetchResult);
}
return fetchResult.text();
}).then((result) => {
if (typeof result === "string") {
upstreamErrorExtensions.response ||= {};
upstreamErrorExtensions.response.body = result;
if (result) {
try {
const parsedResult = JSON.parse(result);
upstreamErrorExtensions.response.body = parsedResult;
if (parsedResult.data == null && (parsedResult.errors == null || parsedResult.errors.length === 0)) {
return {
errors: [
createGraphQLError(
'Unexpected empty "data" and "errors" fields in result: ' + result,
{
extensions: upstreamErrorExtensions
}
)
]
};
if (options?.retry != null && !fetchResult.status.toString().startsWith("2")) {
throw new Error(
fetchResult.statusText || `Upstream HTTP Error: ${fetchResult.status}`
);
}
const contentType = fetchResult.headers.get("content-type");
if (contentType?.includes("text/event-stream")) {
return handleEventStreamResponse(
fetchResult,
subscriptionCtrl,
signal
);
} else if (contentType?.includes("multipart/mixed")) {
return handleMultipartMixedResponse(fetchResult);
}
return fetchResult.text();
},
(result) => {
if (typeof result === "string") {
upstreamErrorExtensions.response ||= {};
upstreamErrorExtensions.response.body = result;
if (result) {
try {
const parsedResult = JSON.parse(result);
upstreamErrorExtensions.response.body = parsedResult;
if (parsedResult.data == null && (parsedResult.errors == null || parsedResult.errors.length === 0)) {
return {
errors: [
createGraphQLError(
'Unexpected empty "data" and "errors" fields in result: ' + result,
{
extensions: upstreamErrorExtensions
}
)
]
};
}
if (Array.isArray(parsedResult.errors)) {
return {
...parsedResult,
errors: parsedResult.errors.map(
({
message,
...options2
}) => createGraphQLError(message, {
...options2,
extensions: {
code: "DOWNSTREAM_SERVICE_ERROR",
serviceName,
...options2.extensions || {}
}
})
)
};
}
return parsedResult;
} catch (e) {
return {
errors: [
createGraphQLError(
`Unexpected response: ${JSON.stringify(result)}`,
{
extensions: upstreamErrorExtensions,
originalError: e
}
)
]
};
}
}
if (Array.isArray(parsedResult.errors)) {
return {
...parsedResult,
errors: parsedResult.errors.map(
({
message,
...options2
}) => createGraphQLError(message, {
...options2,
extensions: {
code: "DOWNSTREAM_SERVICE_ERROR",
...options2.extensions || {}
}
})
)
};
}
return parsedResult;
} catch (e) {
return {
errors: [
createGraphQLError(
`Unexpected response: ${JSON.stringify(result)}`,
{
extensions: upstreamErrorExtensions,
originalError: e
}
)
]
};
} else {
return result;
}
}
} else {
return result;
}
}).catch((e) => {
if (e.name === "AggregateError") {
return {
errors: e.errors.map(
(e2) => coerceFetchError(e2, {
signal,
endpoint,
upstreamErrorExtensions
})
)
};
}
return {
errors: [
coerceFetchError(e, {
signal,
endpoint,
upstreamErrorExtensions
})
]
};
}).resolve()
},
handleError
),
handleError
),
handleError
);

@@ -767,0 +784,0 @@ };

{
"name": "@graphql-tools/executor-http",
"version": "1.2.9-rc-fa9af4651df2ba248ee59d3d4b64dfd70b45e988",
"version": "1.3.0-alpha-97aa61c442facee49ab18af23145184fd1cb236c",
"type": "module",

@@ -42,3 +42,3 @@ "description": "A set of utils for faster development of GraphQL tools",

"dependencies": {
"@graphql-tools/executor-common": "^0.0.3",
"@graphql-tools/executor-common": "0.0.4-alpha-97aa61c442facee49ab18af23145184fd1cb236c",
"@graphql-tools/utils": "^10.8.1",

@@ -50,4 +50,3 @@ "@repeaterjs/repeater": "^3.0.4",

"meros": "^1.2.1",
"tslib": "^2.8.1",
"value-or-promise": "^1.0.12"
"tslib": "^2.8.1"
},

@@ -60,3 +59,3 @@ "devDependencies": {

"graphql": "^16.9.0",
"graphql-yoga": "^5.12.0",
"graphql-yoga": "^5.13.1",
"pkgroll": "2.11.2"

@@ -63,0 +62,0 @@ },

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet