Skip to content

Commit c1a008a

Browse files
authored
Merge pull request #3303 from SeedCompany/graphql/yoga
2 parents 7de7189 + c15347f commit c1a008a

24 files changed

+1821
-1363
lines changed

.github/workflows/api-schema.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ jobs:
5050
name: head-gql-schema
5151
path: head
5252

53+
- name: Check with Hive
54+
run: |
55+
curl -sSL https://graphql-hive.com/install.sh | sh
56+
hive schema:check head/schema.graphql \
57+
--registry.accessToken '${{ secrets.HIVE_TOKEN }}' \
58+
--github
59+
5360
- name: Show diff in PR comment
5461
uses: agu-z/gql-diff-action@v2
5562
with:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
diff --git a/dist/index.d.ts b/dist/index.d.ts
2+
index d16ddf2f4e30e75c5b04044af34e8286b2e8b0a5..9f56feb61efa75a40c815fd56f11642719d41737 100644
3+
--- a/dist/index.d.ts
4+
+++ b/dist/index.d.ts
5+
@@ -1,5 +1,3 @@
6+
-/// <reference lib="dom" />
7+
-/// <reference lib="dom.iterable" />
8+
/// <reference types="urlpattern-polyfill" />
9+
10+
declare type _URLPattern = typeof URLPattern

package.json

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@
3131
"type-check": "tsc -p tsconfig.check.json"
3232
},
3333
"dependencies": {
34-
"@apollo/server": "^4.9.5",
35-
"@apollo/subgraph": "^2.5.6",
36-
"@as-integrations/fastify": "^2.1.1",
3734
"@aws-sdk/client-s3": "^3.440.0",
3835
"@aws-sdk/s3-request-presigner": "^3.440.0",
3936
"@faker-js/faker": "^8.2.0",
@@ -42,8 +39,11 @@
4239
"@fastify/cors": "^9.0.1",
4340
"@ffprobe-installer/ffprobe": "^2.1.2",
4441
"@golevelup/nestjs-discovery": "^4.0.0",
42+
"@graphql-hive/yoga": "^0.38.2",
43+
"@graphql-tools/utils": "^10.5.4",
44+
"@graphql-yoga/nestjs": "^3.7.0",
45+
"@graphql-yoga/plugin-apq": "^3.7.0",
4546
"@leeoniya/ufuzzy": "^1.0.11",
46-
"@nestjs/apollo": "^12.0.9",
4747
"@nestjs/common": "^10.2.7",
4848
"@nestjs/core": "^10.2.7",
4949
"@nestjs/graphql": "^12.0.9",
@@ -76,10 +76,10 @@
7676
"file-type": "^18.6.0",
7777
"glob": "^10.3.10",
7878
"got": "^14.3.0",
79-
"graphql": "^16.8.1",
79+
"graphql": "^16.9.0",
8080
"graphql-parse-resolve-info": "^4.14.0",
8181
"graphql-scalars": "^1.22.4",
82-
"graphql-upload": "^16.0.2",
82+
"graphql-yoga": "^5.7.0",
8383
"human-format": "^1.2.0",
8484
"image-size": "^1.0.2",
8585
"indent-string": "^5.0.0",
@@ -106,6 +106,7 @@
106106
"sanitize-filename": "^1.6.3",
107107
"title-case": "^4.3.1",
108108
"ts-essentials": "^9.4.1",
109+
"urlpattern-polyfill": "^10.0.0",
109110
"uuid": "^10.0.0",
110111
"winston": "^3.11.0",
111112
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.0/xlsx-0.20.0.tgz",
@@ -114,19 +115,19 @@
114115
},
115116
"devDependencies": {
116117
"@edgedb/generate": "github:CarsonF/edgedb-js#workspace=@edgedb/generate&head=temp-host",
118+
"@graphql-hive/cli": "^0.44.2",
117119
"@nestjs/cli": "^10.2.1",
118120
"@nestjs/schematics": "^10.0.3",
119121
"@nestjs/testing": "^10.2.7",
120122
"@seedcompany/eslint-plugin": "^3.4.1",
121123
"@tsconfig/strictest": "^2.0.2",
122124
"@types/common-tags": "^1.8.3",
123125
"@types/ffprobe": "^1.1.7",
124-
"@types/graphql-upload": "^16.0.4",
125126
"@types/jest": "^29.5.7",
126127
"@types/jsonwebtoken": "^9.0.4",
127128
"@types/lodash": "^4.14.200",
128129
"@types/luxon": "^3.4.2",
129-
"@types/node": "^20.12.5",
130+
"@types/node": "^22.7.8",
130131
"@types/prismjs": "^1.26.2",
131132
"@types/react": "^18.2.33",
132133
"@types/stack-trace": "^0.0.32",
@@ -154,20 +155,14 @@
154155
"cypher-query-builder/neo4j-driver": "^5.9.0",
155156
"neo4j-driver-bolt-connection@npm:5.20.0": "patch:neo4j-driver-bolt-connection@npm%3A5.20.0#~/.yarn/patches/neo4j-driver-bolt-connection-npm-5.20.0-1f7809f435.patch",
156157
"neo4j-driver-core@npm:5.20.0": "patch:neo4j-driver-core@npm%3A5.20.0#~/.yarn/patches/neo4j-driver-core-npm-5.20.0-99216f6938.patch",
157-
"@apollo/server-plugin-landing-page-graphql-playground": "npm:empty-npm-package@*",
158-
"@apollo/server/express": "npm:empty-npm-package@*",
159158
"@nestjs/cli/fork-ts-checker-webpack-plugin": "npm:empty-npm-package@*",
160159
"@nestjs/cli/webpack": "npm:empty-npm-package@*",
161160
"@nestjs/cli/typescript": "^5.1.6",
162-
"@types/express": "npm:@types/stack-trace@*",
163-
"@types/express-serve-static-core": "npm:@types/stack-trace@*",
164-
"@types/koa": "npm:@types/stack-trace@*",
161+
"@nestjs/graphql/graphql-ws": "^5",
162+
"@whatwg-node/fetch": "patch:@whatwg-node/fetch@npm%3A0.9.22#~/.yarn/patches/@whatwg-node-fetch-npm-0.9.22-a60314fb39.patch",
165163
"subscriptions-transport-ws": "npm:empty-npm-package@*"
166164
},
167165
"dependenciesMeta": {
168-
"@apollo/protobufjs": {
169-
"built": false
170-
},
171166
"@nestjs/core": {
172167
"built": false
173168
},

src/common/file-upload.scalar.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { GraphQLError, GraphQLScalarType } from 'graphql';
2+
3+
export const FileUploadScalar = new GraphQLScalarType({
4+
name: 'Upload',
5+
description: 'The `Upload` scalar type represents a file upload.',
6+
parseValue(value) {
7+
if (value instanceof File) {
8+
return value;
9+
}
10+
throw new GraphQLError('Upload value invalid.');
11+
},
12+
parseLiteral(node) {
13+
throw new GraphQLError('Upload literal unsupported.', { nodes: node });
14+
},
15+
serialize() {
16+
throw new GraphQLError('Upload serialization unsupported.');
17+
},
18+
});
19+
20+
export type FileUpload = File;

src/common/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export * from './db-unique.decorator';
1515
export * from './disabled.decorator';
1616
export * from './mutation-placeholder.output';
1717
export * from './exceptions';
18+
export * from './file-upload.scalar';
1819
export * from './field-selection';
1920
export * from './fields.pipe';
2021
export * from './filter-field';

src/common/scalars.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Type } from '@nestjs/common';
22
import { CustomScalar } from '@nestjs/graphql';
33
import { GraphQLScalarType } from 'graphql';
4-
import UploadScalar from 'graphql-upload/GraphQLUpload.mjs';
4+
import { FileUploadScalar } from './file-upload.scalar';
55
import { DateScalar, DateTimeScalar } from './luxon.graphql';
66
import { InlineMarkdownScalar, MarkdownScalar } from './markdown.scalar';
77
import { RichTextScalar } from './rich-text.scalar';
@@ -14,7 +14,7 @@ export const getRegisteredScalars = (): Scalar[] => [
1414
DateScalar,
1515
DateTimeScalar,
1616
RichTextScalar,
17-
UploadScalar,
17+
FileUploadScalar,
1818
UrlScalar,
1919
MarkdownScalar,
2020
InlineMarkdownScalar,

src/components/authentication/current-user.provider.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { Plugin } from '@nestjs/apollo';
21
import {
32
CallHandler,
43
ExecutionContext,
@@ -13,7 +12,6 @@ import { EdgeDB, OptionsFn } from '~/core/edgedb';
1312
import { HttpMiddleware } from '~/core/http';
1413

1514
@Injectable()
16-
@Plugin()
1715
export class EdgeDBCurrentUserProvider
1816
implements HttpMiddleware, NestInterceptor
1917
{

src/components/file/dto/upload.dto.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { Field, InputType, ObjectType } from '@nestjs/graphql';
22
import { stripIndent } from 'common-tags';
3-
import UploadScalar from 'graphql-upload/GraphQLUpload.mjs';
4-
import type { FileUpload } from 'graphql-upload/Upload.mjs';
5-
import { ID, IdField } from '~/common';
3+
import { FileUpload, FileUploadScalar, ID, IdField } from '~/common';
64
import { MediaUserMetadata } from '../media/media.dto';
75

86
@ObjectType()
@@ -31,15 +29,15 @@ export abstract class CreateDefinedFileVersionInput {
3129
})
3230
readonly uploadId?: ID;
3331

34-
@Field(() => UploadScalar, {
32+
@Field(() => FileUploadScalar, {
3533
description: stripIndent`
3634
A file directly uploaded.
3735
This is mainly here to allow usage with Apollo Studio/Sandbox.
38-
For production, prefer the \`url\` from the \`RequestUploadOutput\`.
36+
For production, prefer a PUT request to the \`url\` from the \`RequestUploadOutput\`.
3937
`,
4038
nullable: true,
4139
})
42-
readonly file?: Promise<FileUpload>;
40+
readonly file?: FileUpload;
4341

4442
@Field({
4543
description: stripIndent`

src/components/file/file.service.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
} from '@aws-sdk/client-s3';
55
import { Injectable } from '@nestjs/common';
66
import { bufferFromStream, cleanJoin, Nil } from '@seedcompany/common';
7-
import { fileTypeFromStream } from 'file-type';
7+
import { fileTypeFromBuffer } from 'file-type';
88
import { intersection } from 'lodash';
99
import { Duration } from 'luxon';
1010
import mime from 'mime';
@@ -297,19 +297,19 @@ export class FileService {
297297
'A file with this ID already exists. Request an new upload ID.',
298298
);
299299
}
300-
const file = await uploadingFile;
301300

302-
let type: string | Nil = file.mimetype;
301+
const body = await uploadingFile.arrayBuffer();
302+
303+
let type: string | Nil = uploadingFile.type;
303304
type = type === 'application/octet-stream' ? null : type;
304-
type ??= (await fileTypeFromStream(file.createReadStream()))?.mime;
305+
type ??= (await fileTypeFromBuffer(body))?.mime;
305306
type ??= mime.getType(name);
306307
type ??= 'application/octet-stream';
307308

308309
await this.bucket.putObject({
309310
Key: `temp/${uploadId}`,
310311
ContentType: type,
311-
ContentEncoding: file.encoding,
312-
Body: file.createReadStream(),
312+
Body: Buffer.from(body),
313313
});
314314
}
315315

@@ -441,8 +441,7 @@ export class FileService {
441441
return sanitizeFilename(input.name);
442442
}
443443
if (input?.file) {
444-
const file = await input.file;
445-
const sanitized = sanitizeFilename(file.filename);
444+
const sanitized = sanitizeFilename(input.file.name);
446445
if (sanitized) {
447446
return sanitized;
448447
}

src/core/config/config.service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ export const makeConfig = (env: EnvironmentService) =>
4545
ttl: env.duration('GRAPHQL_PERSISTED_QUERIES_TTL').optional('1w'),
4646
},
4747
};
48+
hive = {
49+
token: env.string('HIVE_TOKEN').optional(),
50+
};
4851

4952
lruCache = {
5053
ttl: env.duration('LRU_CACHE_TTL').optional()?.as('milliseconds'),

0 commit comments

Comments
 (0)