Skip to content

Commit 6a6b835

Browse files
committed
chore(dependencies): migrate apollo-server 3->4
1 parent c58662b commit 6a6b835

File tree

7 files changed

+216
-323
lines changed

7 files changed

+216
-323
lines changed

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
"url": "https://github.com/ar-io/ar-io-node"
99
},
1010
"dependencies": {
11+
"@apollo/server": "^4.11.3",
12+
"@apollo/server-plugin-landing-page-graphql-playground": "^4.0.1",
1113
"@ar.io/sdk": "^3.4.0-alpha.3",
1214
"@aws-lite/client": "^0.22.4",
1315
"@aws-lite/s3": "^0.2.6",
1416
"@clickhouse/client": "^1.10.1",
1517
"@dha-team/arbundles": "^1.0.1",
1618
"@permaweb/aoconnect": "^0.0.63",
17-
"apollo-server-express": "^3.13.0",
1819
"arweave": "^1.15.5",
1920
"axios": "^1.7.9",
2021
"better-sqlite3": "^9.4.5",
@@ -28,6 +29,7 @@
2829
"fastq": "^1.18.0",
2930
"fs-extra": "^11.3.0",
3031
"graphql": "^16.10.0",
32+
"graphql-tag": "^2.12.6",
3133
"ioredis": "^5.4.2",
3234
"json-canonicalize": "^1.0.6",
3335
"lmdb": "^3.2.2",
@@ -62,6 +64,7 @@
6264
"@testcontainers/localstack": "^10.17.2",
6365
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
6466
"@types/better-sqlite3": "7.6.3",
67+
"@types/cors": "^2.8.17",
6568
"@types/express": "^5.0.0",
6669
"@types/express-prometheus-middleware": "^1.2.3",
6770
"@types/express-serve-static-core": "^5.0.6",
@@ -98,7 +101,8 @@
98101
},
99102
"resolutions": {
100103
"gc-stats/nan": "2.18.0",
101-
"express-prometheus-middleware/prometheus-gc-stats/gc-stats": "1.4.1"
104+
"express-prometheus-middleware/prometheus-gc-stats/gc-stats": "1.4.1",
105+
"lru-cache": "8.x"
102106
},
103107
"scripts": {
104108
"build": "yarn clean && npx tsc --project ./tsconfig.prod.json && yarn copy-files",

src/app.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* You should have received a copy of the GNU Affero General Public License
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
18-
import { default as cors } from 'cors';
18+
import cors from 'cors';
1919
import express from 'express';
2020
import { Server } from 'node:http';
2121

@@ -26,7 +26,7 @@ import { arIoRouter } from './routes/ar-io.js';
2626
import { arnsRouter } from './routes/arns.js';
2727
import { dataRouter } from './routes/data/index.js';
2828
import { arweaveRouter } from './routes/arweave.js';
29-
import { apolloServer } from './routes/graphql/index.js';
29+
import { makeApolloServerMiddleware } from './routes/graphql/index.js';
3030
import { openApiRouter } from './routes/openapi.js';
3131
import * as system from './system.js';
3232

@@ -66,20 +66,12 @@ app.use(dataRouter);
6666
app.use(arweaveRouter);
6767

6868
// GraphQL
69-
const apolloServerInstanceGql = apolloServer(system.gqlQueryable, {
70-
introspection: true,
71-
persistedQueries: false,
69+
const apolloServerMiddleware = await makeApolloServerMiddleware({
70+
db: system.gqlQueryable,
7271
});
7372

74-
let server: Server;
75-
apolloServerInstanceGql.start().then(() => {
76-
apolloServerInstanceGql.applyMiddleware({
77-
app: app as any,
78-
path: '/graphql',
79-
});
80-
server = app.listen(config.PORT, () => {
81-
log.info(`Listening on port ${config.PORT}`);
82-
});
83-
});
73+
app.use(apolloServerMiddleware);
8474

85-
export { server };
75+
export const server: Server = app.listen(config.PORT, () => {
76+
log.info(`Listening on port ${config.PORT}`);
77+
});

src/database/composite-clickhouse.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
import * as winston from 'winston';
1919
import sql from 'sql-bricks';
2020
import { ClickHouseClient, createClient } from '@clickhouse/client';
21-
import { ValidationError } from 'apollo-server-express';
21+
import { ApolloServerErrorCode } from '@apollo/server/errors';
22+
import { GraphQLError } from 'graphql';
2223

2324
import {
2425
b64UrlToHex,
@@ -69,7 +70,11 @@ export function decodeTransactionGqlCursor(cursor: string | undefined) {
6970

7071
return { height, blockTransactionIndex, isDataItem, id, indexedAt };
7172
} catch (error) {
72-
throw new ValidationError('Invalid transaction cursor');
73+
throw new GraphQLError('Invalid transaction cursor', {
74+
extensions: {
75+
code: ApolloServerErrorCode.GRAPHQL_VALIDATION_FAILED,
76+
},
77+
});
7378
}
7479
}
7580

@@ -87,7 +92,11 @@ export function decodeBlockGqlCursor(cursor: string | undefined) {
8792

8893
return { height };
8994
} catch (error) {
90-
throw new ValidationError('Invalid block cursor');
95+
throw new GraphQLError('Invalid block cursor', {
96+
extensions: {
97+
code: ApolloServerErrorCode.GRAPHQL_VALIDATION_FAILED,
98+
},
99+
});
91100
}
92101
}
93102

src/database/standalone-sqlite.test.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
*/
1818
import { strict as assert } from 'node:assert';
1919
import { after, before, beforeEach, describe, it } from 'node:test';
20-
import { ValidationError } from 'apollo-server-express';
2120
import crypto from 'node:crypto';
2221
import fs from 'node:fs';
2322

@@ -108,7 +107,7 @@ describe('SQLite GraphQL cursor functions', () => {
108107
decodeTransactionGqlCursor('123');
109108
},
110109
{
111-
name: ValidationError.name,
110+
name: 'GraphQLError',
112111
message: 'Invalid transaction cursor',
113112
},
114113
);
@@ -140,7 +139,7 @@ describe('SQLite GraphQL cursor functions', () => {
140139
decodeBlockGqlCursor('123');
141140
},
142141
{
143-
name: ValidationError.name,
142+
name: 'GraphQLError',
144143
message: 'Invalid block cursor',
145144
},
146145
);

src/database/standalone-sqlite.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
* You should have received a copy of the GNU Affero General Public License
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
18-
import { ValidationError } from 'apollo-server-express';
18+
import { ApolloServerErrorCode } from '@apollo/server/errors';
19+
import { GraphQLError } from 'graphql';
1920
import Sqlite from 'better-sqlite3';
2021
import crypto from 'node:crypto';
2122
import os from 'node:os';
@@ -122,7 +123,11 @@ export function decodeTransactionGqlCursor(cursor: string | undefined) {
122123

123124
return { height, blockTransactionIndex, dataItemId, indexedAt, id };
124125
} catch (error) {
125-
throw new ValidationError('Invalid transaction cursor');
126+
throw new GraphQLError('Invalid transaction cursor', {
127+
extensions: {
128+
code: ApolloServerErrorCode.GRAPHQL_VALIDATION_FAILED,
129+
},
130+
});
126131
}
127132
}
128133

@@ -140,7 +145,11 @@ export function decodeBlockGqlCursor(cursor: string | undefined) {
140145

141146
return { height };
142147
} catch (error) {
143-
throw new ValidationError('Invalid block cursor');
148+
throw new GraphQLError('Invalid block cursor', {
149+
extensions: {
150+
code: ApolloServerErrorCode.GRAPHQL_VALIDATION_FAILED,
151+
},
152+
});
144153
}
145154
}
146155

src/routes/graphql/index.ts

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,40 +15,45 @@
1515
* You should have received a copy of the GNU Affero General Public License
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
18-
import {
19-
ApolloServerPluginLandingPageDisabled,
20-
ApolloServerPluginLandingPageGraphQLPlayground,
21-
} from 'apollo-server-core';
22-
import {
23-
ApolloServer,
24-
ApolloServerExpressConfig,
25-
gql,
26-
} from 'apollo-server-express';
18+
19+
import { ApolloServer } from '@apollo/server';
20+
import { ApolloServerPluginLandingPageGraphQLPlayground } from '@apollo/server-plugin-landing-page-graphql-playground';
21+
import { expressMiddleware } from '@apollo/server/express4';
22+
import { DocumentNode } from 'graphql';
23+
import gql from 'graphql-tag';
24+
2725
import { readFileSync } from 'node:fs';
2826

2927
import { GqlQueryable } from '../../types.js';
3028
import { resolvers } from './resolvers.js';
3129

3230
const typeDefsUrl = new URL('./schema/types.graphql', import.meta.url);
33-
const typeDefs = gql(readFileSync(typeDefsUrl, 'utf8'));
31+
const typeDefs: DocumentNode | undefined = gql(
32+
readFileSync(typeDefsUrl, 'utf8'),
33+
);
3434

35-
const apolloServer = (
36-
db: GqlQueryable,
37-
opts: ApolloServerExpressConfig = {},
38-
) => {
39-
return new ApolloServer({
35+
interface ApolloServerContext {
36+
db: GqlQueryable;
37+
}
38+
39+
export const makeApolloServerMiddleware = async (
40+
context: ApolloServerContext,
41+
): Promise<any> => {
42+
const apolloServer = new ApolloServer<ApolloServerContext>({
4043
typeDefs,
4144
resolvers,
42-
debug: false,
43-
plugins: [
44-
ApolloServerPluginLandingPageDisabled(),
45-
ApolloServerPluginLandingPageGraphQLPlayground(),
46-
],
47-
context: () => {
48-
return { db };
45+
plugins: [ApolloServerPluginLandingPageGraphQLPlayground()],
46+
introspection: true,
47+
persistedQueries: {
48+
ttl: 300, // 5 minutes
4949
},
50-
...opts,
5150
});
52-
};
5351

54-
export { apolloServer };
52+
await apolloServer.start();
53+
54+
return expressMiddleware<ApolloServerContext>(apolloServer, {
55+
context: async (): Promise<ApolloServerContext> => {
56+
return { ...context };
57+
},
58+
});
59+
};

0 commit comments

Comments
 (0)