Repository: apollographql/apollo-server
Pull request #7900 (2024-07-11 16:55:46)

Inline `@josephg/resolvable` dependency
Issue https://github.com/apollographql/apollo-server/issues/7895 reports that AS4 fails to build for ESM due to the resolvable dependency.

I'm actually unsure _why_ this is happening though, since the shipped JS appears to be ESM compatible:
https://unpkg.com/@josephg/resolvable@1.0.1/index.js

@macrozone would you mind testing the builds from this PR (see Codesandbox CI comment) and letting me know if this resolves the issue in your project?


netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *apollo-server-docs* processing.


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 9395e64f9d0221ae9097ee6e4cc9dc8893e4c690 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/apollo-server-docs/deploys/66900e956450b300087d1b46 |
codesandbox-ci[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/apollographql/apollo-server/pr/7900/builds/522055) or the icon next to each commit SHA.
macrozone: @trevor-scheer I can confirm that this resolves the issue!
davidhasek1: @trevor-scheer Thank you for this fix.

Patch:
diff --git a/.changeset/ninety-clouds-smile.md b/.changeset/ninety-clouds-smile.md
new file mode 100644
index 000000000..77e953d1b
--- /dev/null
+++ b/.changeset/ninety-clouds-smile.md
@@ -0,0 +1,6 @@
+---
+"@apollo/server-integration-testsuite": patch
+"@apollo/server": patch
+---
+
+Inline a small dependency that was causing build issues for ESM projects
diff --git a/cspell-dict.txt b/cspell-dict.txt
index 2515e3a41..71fe67c72 100644
--- a/cspell-dict.txt
+++ b/cspell-dict.txt
@@ -98,7 +98,6 @@ instanceof
 iosapp
 isnodelike
 iteratees
-josephg
 jsdelivr
 keyv
 keyvadapter
diff --git a/package-lock.json b/package-lock.json
index a28a9cb44..e33b5a81c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,7 +20,6 @@
         "@graphql-codegen/typescript-operations": "3.0.4",
         "@graphql-tools/mock": "8.7.20",
         "@graphql-tools/schema": "9.0.19",
-        "@josephg/resolvable": "1.0.1",
         "@rollup/plugin-commonjs": "25.0.7",
         "@types/async-retry": "1.4.8",
         "@types/compression": "1.7.5",
@@ -4114,6 +4113,7 @@
     },
     "node_modules/@josephg/resolvable": {
       "version": "1.0.1",
+      "dev": true,
       "license": "ISC"
     },
     "node_modules/@jridgewell/gen-mapping": {
@@ -14647,7 +14647,6 @@
         "@apollo/usage-reporting-protobuf": "^4.1.1",
         "@apollo/utils.createhash": "^2.0.0",
         "@apollo/utils.keyvaluecache": "^2.1.0",
-        "@josephg/resolvable": "^1.0.1",
         "express": "^4.18.1",
         "graphql-http": "1.22.0",
         "graphql-tag": "^2.12.6",
@@ -14741,7 +14740,6 @@
         "@apollo/utils.usagereporting": "^2.1.0",
         "@apollo/utils.withrequired": "^2.0.0",
         "@graphql-tools/schema": "^9.0.0",
-        "@josephg/resolvable": "^1.0.0",
         "@types/express": "^4.17.13",
         "@types/express-serve-static-core": "^4.17.30",
         "@types/node-fetch": "^2.6.1",
@@ -14975,7 +14973,6 @@
         "@apollo/utils.usagereporting": "^2.1.0",
         "@apollo/utils.withrequired": "^2.0.0",
         "@graphql-tools/schema": "^9.0.0",
-        "@josephg/resolvable": "^1.0.0",
         "@types/express": "^4.17.13",
         "@types/express-serve-static-core": "^4.17.30",
         "@types/node-fetch": "^2.6.1",
@@ -15021,7 +15018,6 @@
         "@apollo/usage-reporting-protobuf": "^4.1.1",
         "@apollo/utils.createhash": "^2.0.0",
         "@apollo/utils.keyvaluecache": "^2.1.0",
-        "@josephg/resolvable": "^1.0.1",
         "express": "^4.18.1",
         "graphql-http": "1.22.0",
         "graphql-tag": "^2.12.6",
@@ -18127,7 +18123,8 @@
       }
     },
     "@josephg/resolvable": {
-      "version": "1.0.1"
+      "version": "1.0.1",
+      "dev": true
     },
     "@jridgewell/gen-mapping": {
       "version": "0.3.2",
diff --git a/package.json b/package.json
index dfa6f813b..b016373fa 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,6 @@
     "@graphql-codegen/typescript-operations": "3.0.4",
     "@graphql-tools/mock": "8.7.20",
     "@graphql-tools/schema": "9.0.19",
-    "@josephg/resolvable": "1.0.1",
     "@rollup/plugin-commonjs": "25.0.7",
     "@types/async-retry": "1.4.8",
     "@types/compression": "1.7.5",
diff --git a/packages/server/package.json b/packages/server/package.json
index 8b274f10b..d2d33cb25 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -136,7 +136,6 @@
     "@apollo/utils.usagereporting": "^2.1.0",
     "@apollo/utils.withrequired": "^2.0.0",
     "@graphql-tools/schema": "^9.0.0",
-    "@josephg/resolvable": "^1.0.0",
     "@types/express": "^4.17.13",
     "@types/express-serve-static-core": "^4.17.30",
     "@types/node-fetch": "^2.6.1",
diff --git a/packages/server/src/ApolloServer.ts b/packages/server/src/ApolloServer.ts
index a78dceee4..b851b2955 100644
--- a/packages/server/src/ApolloServer.ts
+++ b/packages/server/src/ApolloServer.ts
@@ -8,7 +8,7 @@ import {
 import type { Logger } from '@apollo/utils.logger';
 import type { WithRequired } from '@apollo/utils.withrequired';
 import { makeExecutableSchema } from '@graphql-tools/schema';
-import resolvable, { type Resolvable } from '@josephg/resolvable';
+import resolvable, { type Resolvable } from './utils/resolvable.js';
 import {
   GraphQLError,
   assertValidSchema,
diff --git a/packages/server/src/utils/resolvable.ts b/packages/server/src/utils/resolvable.ts
new file mode 100644
index 000000000..f279ed448
--- /dev/null
+++ b/packages/server/src/utils/resolvable.ts
@@ -0,0 +1,30 @@
+// Copyright 2019 Joseph Gentle
+
+// Permission to use, copy, modify, and / or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+// FITNESS.IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+//   INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+export type Resolvable<T> = Promise<T> & {
+  resolve: (t: T) => void;
+  reject: (e: any) => void;
+};
+
+export default <T = void>(): Resolvable<T> => {
+  let resolve: (val: T) => void;
+  let reject: (err: any) => void;
+  const promise = new Promise<T>((_resolve, _reject) => {
+    resolve = _resolve;
+    reject = _reject;
+  }) as Resolvable<T>;
+  promise.resolve = resolve!;
+  promise.reject = reject!;
+  return promise;
+};


Test patch:
diff --git a/packages/integration-testsuite/package.json b/packages/integration-testsuite/package.json
index a65453fa8..37abe995c 100644
--- a/packages/integration-testsuite/package.json
+++ b/packages/integration-testsuite/package.json
@@ -32,7 +32,6 @@
     "@apollo/usage-reporting-protobuf": "^4.1.1",
     "@apollo/utils.createhash": "^2.0.0",
     "@apollo/utils.keyvaluecache": "^2.1.0",
-    "@josephg/resolvable": "^1.0.1",
     "express": "^4.18.1",
     "graphql-http": "1.22.0",
     "graphql-tag": "^2.12.6",
diff --git a/packages/integration-testsuite/src/apolloServerTests.ts b/packages/integration-testsuite/src/apolloServerTests.ts
index 102db81bb..e57c41e11 100644
--- a/packages/integration-testsuite/src/apolloServerTests.ts
+++ b/packages/integration-testsuite/src/apolloServerTests.ts
@@ -37,7 +37,7 @@ import {
 } from '@apollo/server';
 import fetch, { type Headers } from 'node-fetch';
 
-import resolvable, { type Resolvable } from '@josephg/resolvable';
+import resolvable, { type Resolvable } from './resolvable.js';
 import type { AddressInfo } from 'net';
 import request, { type Response } from 'supertest';
 import { InMemoryLRUCache } from '@apollo/utils.keyvaluecache';
diff --git a/packages/integration-testsuite/src/httpServerTests.ts b/packages/integration-testsuite/src/httpServerTests.ts
index a431901c6..9a1977e78 100644
--- a/packages/integration-testsuite/src/httpServerTests.ts
+++ b/packages/integration-testsuite/src/httpServerTests.ts
@@ -4,7 +4,7 @@
 // function. Newer tests have generally been added to the apolloServerTests.ts
 // file.
 import { createHash } from '@apollo/utils.createhash';
-import resolvable, { type Resolvable } from '@josephg/resolvable';
+import resolvable, { type Resolvable } from './resolvable.js';
 import {
   BREAK,
   type DocumentNode,
diff --git a/packages/integration-testsuite/src/resolvable.ts b/packages/integration-testsuite/src/resolvable.ts
new file mode 100644
index 000000000..f279ed448
--- /dev/null
+++ b/packages/integration-testsuite/src/resolvable.ts
@@ -0,0 +1,30 @@
+// Copyright 2019 Joseph Gentle
+
+// Permission to use, copy, modify, and / or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+// FITNESS.IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+//   INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+export type Resolvable<T> = Promise<T> & {
+  resolve: (t: T) => void;
+  reject: (e: any) => void;
+};
+
+export default <T = void>(): Resolvable<T> => {
+  let resolve: (val: T) => void;
+  let reject: (err: any) => void;
+  const promise = new Promise<T>((_resolve, _reject) => {
+    resolve = _resolve;
+    reject = _reject;
+  }) as Resolvable<T>;
+  promise.resolve = resolve!;
+  promise.reject = reject!;
+  return promise;
+};
diff --git a/packages/server/src/__tests__/express4/expressSpecific.test.ts b/packages/server/src/__tests__/express4/expressSpecific.test.ts
index 70eddeaad..f175744c0 100644
--- a/packages/server/src/__tests__/express4/expressSpecific.test.ts
+++ b/packages/server/src/__tests__/express4/expressSpecific.test.ts
@@ -4,7 +4,7 @@ import compression, { filter as defaultFilter } from 'compression';
 import { ApolloServer, BaseContext } from '../../index.js';
 import { expressMiddleware } from '../../express4/index.js';
 import { it, expect } from '@jest/globals';
-import resolvable from '@josephg/resolvable';
+import resolvable from '../../utils/resolvable.js';
 import cors from 'cors';
 
 it('gives helpful error if json middleware is not installed', async () => {
diff --git a/packages/server/src/__tests__/plugin/drainHttpServer/stoppable.test.ts b/packages/server/src/__tests__/plugin/drainHttpServer/stoppable.test.ts
index e3face7cd..fa444f531 100644
--- a/packages/server/src/__tests__/plugin/drainHttpServer/stoppable.test.ts
+++ b/packages/server/src/__tests__/plugin/drainHttpServer/stoppable.test.ts
@@ -36,7 +36,7 @@ import path from 'path';
 import type { AddressInfo } from 'net';
 import { describe, it, expect, afterEach, beforeEach } from '@jest/globals';
 import { AbortController } from 'node-abort-controller';
-import resolvable, { Resolvable } from '@josephg/resolvable';
+import resolvable, { Resolvable } from '../../../utils/resolvable.js';
 
 function port(s: http.Server) {
   return (s.address() as AddressInfo).port;