graphile-settings 2.3.1 → 2.5.0

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/esm/index.js CHANGED
@@ -4,7 +4,7 @@ import PgPostgis from '@pyramation/postgis';
4
4
  // @ts-ignore
5
5
  import FulltextFilterPlugin from '@pyramation/postgraphile-plugin-fulltext-filter';
6
6
  import { NodePlugin } from 'graphile-build';
7
- import { additionalGraphQLContextFromRequest as langAdditional, LangPlugin
7
+ import { additionalGraphQLContextFromRequest as langAdditional, LangPlugin,
8
8
  // @ts-ignore
9
9
  } from 'graphile-i18n';
10
10
  // @ts-ignore
@@ -13,12 +13,11 @@ import PgMetaschema from 'graphile-meta-schema';
13
13
  import PgSearch from 'graphile-search-plugin';
14
14
  // @ts-ignore
15
15
  import PgSimpleInflector from 'graphile-simple-inflector';
16
- // @ts-ignore
17
- import PostGraphileUploadFieldPlugin from 'postgraphile-derived-upload-field';
18
16
  import ConnectionFilterPlugin from 'postgraphile-plugin-connection-filter';
19
17
  // @ts-ignore
20
18
  import PgPostgisFilter from 'postgraphile-plugin-connection-filter-postgis';
21
19
  import LqlTypesPlugin from './plugins/types';
20
+ import UploadPostGraphilePlugin from './plugins/upload-postgraphile-plugin';
22
21
  import { Uploader } from './resolvers/upload';
23
22
  export const getGraphileSettings = (rawOpts) => {
24
23
  const opts = getEnvOptions(rawOpts);
@@ -29,17 +28,17 @@ export const getGraphileSettings = (rawOpts) => {
29
28
  awsRegion: cdn.awsRegion,
30
29
  awsAccessKey: cdn.awsAccessKey,
31
30
  awsSecretKey: cdn.awsSecretKey,
32
- minioEndpoint: cdn.minioEndpoint
31
+ minioEndpoint: cdn.minioEndpoint,
33
32
  });
34
33
  const resolveUpload = uploader.resolveUpload.bind(uploader);
35
34
  const plugins = [
36
35
  ConnectionFilterPlugin,
37
36
  FulltextFilterPlugin,
38
37
  LqlTypesPlugin,
39
- PostGraphileUploadFieldPlugin,
38
+ UploadPostGraphilePlugin,
40
39
  PgMetaschema,
41
40
  PgManyToMany,
42
- PgSearch
41
+ PgSearch,
43
42
  ];
44
43
  if (features?.postgis) {
45
44
  plugins.push(PgPostgis, PgPostgisFilter);
@@ -55,27 +54,27 @@ export const getGraphileSettings = (rawOpts) => {
55
54
  name: 'upload',
56
55
  namespaceName: 'public',
57
56
  type: 'JSON',
58
- resolve: resolveUpload
57
+ resolve: resolveUpload,
59
58
  },
60
59
  {
61
60
  name: 'attachment',
62
61
  namespaceName: 'public',
63
62
  type: 'String',
64
- resolve: resolveUpload
63
+ resolve: resolveUpload,
65
64
  },
66
65
  {
67
66
  name: 'image',
68
67
  namespaceName: 'public',
69
68
  type: 'JSON',
70
- resolve: resolveUpload
69
+ resolve: resolveUpload,
71
70
  },
72
71
  {
73
72
  tag: 'upload',
74
- resolve: resolveUpload
75
- }
73
+ resolve: resolveUpload,
74
+ },
76
75
  ],
77
76
  pgSimplifyOppositeBaseNames: features?.oppositeBaseNames,
78
- connectionFilterComputedColumns: false
77
+ connectionFilterComputedColumns: false,
79
78
  },
80
79
  appendPlugins: plugins,
81
80
  skipPlugins: [NodePlugin],
@@ -102,7 +101,7 @@ export const getGraphileSettings = (rawOpts) => {
102
101
  additionalGraphQLContextFromRequest: (req, res) => ({
103
102
  ...langAdditional(req, res),
104
103
  req,
105
- res
106
- })
104
+ res,
105
+ }),
107
106
  };
108
107
  };
@@ -0,0 +1,158 @@
1
+ // PostGraphile plugin
2
+ const UploadPostGraphilePlugin = (builder, opts = {}) => {
3
+ const { uploadFieldDefinitions = [] } = opts;
4
+ // Determine whether a table attribute should be treated as an Upload according to configuration
5
+ const relevantUploadType = (attr) => {
6
+ const types = uploadFieldDefinitions.filter(({ name, namespaceName, tag }) => (name &&
7
+ namespaceName &&
8
+ attr.type?.name === name &&
9
+ attr.type?.namespaceName === namespaceName) ||
10
+ (tag && attr.tags?.[tag]));
11
+ if (types.length === 1) {
12
+ return types[0];
13
+ }
14
+ else if (types.length > 1) {
15
+ throw new Error('Upload field definitions are ambiguous');
16
+ }
17
+ return undefined;
18
+ };
19
+ builder.hook('build', (input, build) => {
20
+ const { addType, graphql: { GraphQLScalarType, GraphQLError }, } = build;
21
+ const GraphQLUpload = new GraphQLScalarType({
22
+ name: 'Upload',
23
+ description: 'The `Upload` scalar type represents a file upload.',
24
+ parseValue(value) {
25
+ // The value should be an object with a `.promise` that resolves to the file upload
26
+ const maybe = value;
27
+ if (maybe &&
28
+ maybe.promise &&
29
+ typeof maybe.promise.then === 'function') {
30
+ return maybe.promise;
31
+ }
32
+ throw new GraphQLError('Upload value invalid.');
33
+ },
34
+ parseLiteral(ast) {
35
+ throw new GraphQLError('Upload literal unsupported.', ast);
36
+ },
37
+ serialize() {
38
+ throw new GraphQLError('Upload serialization unsupported.');
39
+ },
40
+ });
41
+ addType(GraphQLUpload);
42
+ // Override the internal types for configured upload-backed columns
43
+ uploadFieldDefinitions.forEach(({ name, namespaceName, type }) => {
44
+ if (!name || !type || !namespaceName)
45
+ return; // tag-based or incomplete definitions
46
+ const theType = build.pgIntrospectionResultsByKind.type.find((typ) => typ.name === name && typ.namespaceName === namespaceName);
47
+ if (theType) {
48
+ build.pgRegisterGqlTypeByTypeId(theType.id, () => build.getTypeByName(type));
49
+ }
50
+ });
51
+ return input;
52
+ });
53
+ builder.hook('inflection', (inflection, build) => {
54
+ return build.extend(inflection, {
55
+ // NO ARROW FUNCTIONS HERE (this)
56
+ uploadColumn(attr) {
57
+ return this.column(attr) + 'Upload';
58
+ },
59
+ });
60
+ });
61
+ // Add Upload input fields alongside matching columns
62
+ builder.hook('GraphQLInputObjectType:fields', (fields, build, context) => {
63
+ const { scope: { isPgRowType, pgIntrospection: table }, } = context;
64
+ if (!isPgRowType || !table || table.kind !== 'class') {
65
+ return fields;
66
+ }
67
+ return build.extend(fields, table.attributes.reduce((memo, attr) => {
68
+ if (!build.pgColumnFilter(attr, build, context))
69
+ return memo;
70
+ const action = context.scope.isPgBaseInput
71
+ ? 'base'
72
+ : context.scope.isPgPatch
73
+ ? 'update'
74
+ : 'create';
75
+ if (build.pgOmit(attr, action))
76
+ return memo;
77
+ if (attr.identity === 'a')
78
+ return memo;
79
+ if (!relevantUploadType(attr)) {
80
+ return memo;
81
+ }
82
+ const fieldName = build.inflection.uploadColumn(attr);
83
+ if (memo[fieldName]) {
84
+ throw new Error(`Two columns produce the same GraphQL field name '${fieldName}' on class '${table.namespaceName}.${table.name}'; one of them is '${attr.name}'`);
85
+ }
86
+ memo = build.extend(memo, {
87
+ [fieldName]: context.fieldWithHooks(fieldName, {
88
+ description: attr.description,
89
+ type: build.getTypeByName('Upload'),
90
+ }, { pgFieldIntrospection: attr, isPgUploadField: true }),
91
+ }, `Adding field for ${build.describePgEntity(attr)}. You can rename this field with a 'Smart Comment':\n\n ${build.sqlCommentByAddingTags(attr, {
92
+ name: 'newNameHere',
93
+ })}`);
94
+ return memo;
95
+ }, {}), `Adding columns to '${build.describePgEntity(table)}'`);
96
+ });
97
+ builder.hook('GraphQLObjectType:fields:field', (field, build, context) => {
98
+ const { pgIntrospectionResultsByKind: introspectionResultsByKind, inflection, } = build;
99
+ const { scope: { isRootMutation, fieldName, pgFieldIntrospection: table }, } = context;
100
+ if (!isRootMutation || !table) {
101
+ return field;
102
+ }
103
+ // It's possible that `resolve` isn't specified on a field, so in that case
104
+ // we fall back to a default resolver.
105
+ const defaultResolver = (obj) => obj[fieldName];
106
+ // Extract the old resolver from `field`
107
+ const { resolve: oldResolve = defaultResolver, ...rest } = field; // GraphQLFieldConfig
108
+ const tags = {};
109
+ const types = {};
110
+ const originals = {};
111
+ const uploadResolversByFieldName = introspectionResultsByKind.attribute
112
+ .filter((attr) => attr.classId === table.id)
113
+ .reduce((memo, attr) => {
114
+ // first, try to directly match the types here
115
+ const typeMatched = relevantUploadType(attr);
116
+ if (typeMatched) {
117
+ const fieldName = inflection.column(attr);
118
+ const uploadFieldName = inflection.uploadColumn(attr);
119
+ memo[uploadFieldName] = typeMatched.resolve;
120
+ tags[uploadFieldName] = attr.tags;
121
+ types[uploadFieldName] = attr.type.name;
122
+ originals[uploadFieldName] = fieldName;
123
+ }
124
+ return memo;
125
+ }, {});
126
+ return {
127
+ // Copy over everything except 'resolve'
128
+ ...rest,
129
+ // Add our new resolver which wraps the old resolver
130
+ async resolve(source, args, context, info) {
131
+ // Recursively check for Upload promises to resolve
132
+ async function resolvePromises(obj) {
133
+ for (const key of Object.keys(obj)) {
134
+ if (obj[key] instanceof Promise) {
135
+ if (uploadResolversByFieldName[key]) {
136
+ const upload = await obj[key];
137
+ // eslint-disable-next-line require-atomic-updates
138
+ obj[originals[key]] = await uploadResolversByFieldName[key](upload, args, context, {
139
+ ...info,
140
+ uploadPlugin: { tags: tags[key], type: types[key] },
141
+ });
142
+ }
143
+ }
144
+ else if (obj[key] !== null && typeof obj[key] === 'object') {
145
+ await resolvePromises(obj[key]);
146
+ }
147
+ }
148
+ }
149
+ await resolvePromises(args);
150
+ // Call the old resolver
151
+ const oldResolveResult = await oldResolve(source, args, context, info);
152
+ // Finally return the result.
153
+ return oldResolveResult;
154
+ },
155
+ };
156
+ });
157
+ };
158
+ export default UploadPostGraphilePlugin;
package/index.js CHANGED
@@ -17,12 +17,11 @@ const graphile_meta_schema_1 = __importDefault(require("graphile-meta-schema"));
17
17
  const graphile_search_plugin_1 = __importDefault(require("graphile-search-plugin"));
18
18
  // @ts-ignore
19
19
  const graphile_simple_inflector_1 = __importDefault(require("graphile-simple-inflector"));
20
- // @ts-ignore
21
- const postgraphile_derived_upload_field_1 = __importDefault(require("postgraphile-derived-upload-field"));
22
20
  const postgraphile_plugin_connection_filter_1 = __importDefault(require("postgraphile-plugin-connection-filter"));
23
21
  // @ts-ignore
24
22
  const postgraphile_plugin_connection_filter_postgis_1 = __importDefault(require("postgraphile-plugin-connection-filter-postgis"));
25
23
  const types_1 = __importDefault(require("./plugins/types"));
24
+ const upload_postgraphile_plugin_1 = __importDefault(require("./plugins/upload-postgraphile-plugin"));
26
25
  const upload_1 = require("./resolvers/upload");
27
26
  const getGraphileSettings = (rawOpts) => {
28
27
  const opts = (0, env_1.getEnvOptions)(rawOpts);
@@ -33,17 +32,17 @@ const getGraphileSettings = (rawOpts) => {
33
32
  awsRegion: cdn.awsRegion,
34
33
  awsAccessKey: cdn.awsAccessKey,
35
34
  awsSecretKey: cdn.awsSecretKey,
36
- minioEndpoint: cdn.minioEndpoint
35
+ minioEndpoint: cdn.minioEndpoint,
37
36
  });
38
37
  const resolveUpload = uploader.resolveUpload.bind(uploader);
39
38
  const plugins = [
40
39
  postgraphile_plugin_connection_filter_1.default,
41
40
  postgraphile_plugin_fulltext_filter_1.default,
42
41
  types_1.default,
43
- postgraphile_derived_upload_field_1.default,
42
+ upload_postgraphile_plugin_1.default,
44
43
  graphile_meta_schema_1.default,
45
44
  pg_many_to_many_1.default,
46
- graphile_search_plugin_1.default
45
+ graphile_search_plugin_1.default,
47
46
  ];
48
47
  if (features?.postgis) {
49
48
  plugins.push(postgis_1.default, postgraphile_plugin_connection_filter_postgis_1.default);
@@ -59,27 +58,27 @@ const getGraphileSettings = (rawOpts) => {
59
58
  name: 'upload',
60
59
  namespaceName: 'public',
61
60
  type: 'JSON',
62
- resolve: resolveUpload
61
+ resolve: resolveUpload,
63
62
  },
64
63
  {
65
64
  name: 'attachment',
66
65
  namespaceName: 'public',
67
66
  type: 'String',
68
- resolve: resolveUpload
67
+ resolve: resolveUpload,
69
68
  },
70
69
  {
71
70
  name: 'image',
72
71
  namespaceName: 'public',
73
72
  type: 'JSON',
74
- resolve: resolveUpload
73
+ resolve: resolveUpload,
75
74
  },
76
75
  {
77
76
  tag: 'upload',
78
- resolve: resolveUpload
79
- }
77
+ resolve: resolveUpload,
78
+ },
80
79
  ],
81
80
  pgSimplifyOppositeBaseNames: features?.oppositeBaseNames,
82
- connectionFilterComputedColumns: false
81
+ connectionFilterComputedColumns: false,
83
82
  },
84
83
  appendPlugins: plugins,
85
84
  skipPlugins: [graphile_build_1.NodePlugin],
@@ -106,8 +105,8 @@ const getGraphileSettings = (rawOpts) => {
106
105
  additionalGraphQLContextFromRequest: (req, res) => ({
107
106
  ...(0, graphile_i18n_1.additionalGraphQLContextFromRequest)(req, res),
108
107
  req,
109
- res
110
- })
108
+ res,
109
+ }),
111
110
  };
112
111
  };
113
112
  exports.getGraphileSettings = getGraphileSettings;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphile-settings",
3
- "version": "2.3.1",
3
+ "version": "2.5.0",
4
4
  "author": "Dan Lynch <pyramation@gmail.com>",
5
5
  "description": "graphile settings",
6
6
  "main": "index.js",
@@ -31,9 +31,9 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@graphile-contrib/pg-many-to-many": "^1.0.2",
34
- "@launchql/env": "^2.2.1",
35
- "@launchql/s3-streamer": "^2.3.1",
36
- "@launchql/types": "^2.3.0",
34
+ "@launchql/env": "^2.4.0",
35
+ "@launchql/s3-streamer": "^2.5.0",
36
+ "@launchql/types": "^2.5.0",
37
37
  "@launchql/upload-names": "^2.2.0",
38
38
  "@pyramation/postgis": "^0.1.1",
39
39
  "@pyramation/postgraphile-plugin-fulltext-filter": "^2.0.0",
@@ -42,11 +42,12 @@
42
42
  "graphile-build": "^4.14.1",
43
43
  "graphile-i18n": "^0.0.3",
44
44
  "graphile-meta-schema": "^0.2.5",
45
- "graphile-query": "^2.2.0",
45
+ "graphile-query": "^2.3.0",
46
46
  "graphile-search-plugin": "^0.1.2",
47
- "graphile-settings": "^2.3.1",
47
+ "graphile-settings": "^2.5.0",
48
48
  "graphile-simple-inflector": "^0.1.1",
49
49
  "graphql-tag": "2.12.6",
50
+ "graphql-upload": "^13.0.0",
50
51
  "lru-cache": "^11.1.0",
51
52
  "pg": "^8.16.0",
52
53
  "postgraphile": "^4.14.1",
@@ -65,7 +66,7 @@
65
66
  "ts-node": "^10.9.2"
66
67
  },
67
68
  "resolutions": {
68
- "graphql": "15.5.2"
69
+ "graphql": "15.10.1"
69
70
  },
70
71
  "keywords": [
71
72
  "graphile",
@@ -74,5 +75,5 @@
74
75
  "launchql",
75
76
  "graphql"
76
77
  ],
77
- "gitHead": "245029576886f5ac650aa5e8fa8cd8d5f47c258f"
78
+ "gitHead": "f7d2375e14a9f45ebb00d58ab87c0efd6bd50618"
78
79
  }
@@ -0,0 +1,31 @@
1
+ import type { ReadStream } from 'fs';
2
+ import type { Plugin } from 'graphile-build';
3
+ import type { GraphQLResolveInfo } from 'graphql';
4
+ export interface FileUpload {
5
+ filename: string;
6
+ mimetype?: string;
7
+ encoding?: string;
8
+ createReadStream: () => ReadStream;
9
+ }
10
+ export interface UploadPluginInfo {
11
+ tags: Record<string, any>;
12
+ type?: string;
13
+ }
14
+ export type UploadResolver = (upload: FileUpload, args: any, context: any, info: GraphQLResolveInfo & {
15
+ uploadPlugin: UploadPluginInfo;
16
+ }) => Promise<any>;
17
+ export type UploadFieldDefinition = {
18
+ name: string;
19
+ namespaceName: string;
20
+ type: string;
21
+ resolve: UploadResolver;
22
+ tag?: never;
23
+ } | {
24
+ tag: string;
25
+ resolve: UploadResolver;
26
+ name?: never;
27
+ namespaceName?: never;
28
+ type?: string;
29
+ };
30
+ declare const UploadPostGraphilePlugin: Plugin;
31
+ export default UploadPostGraphilePlugin;
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // PostGraphile plugin
4
+ const UploadPostGraphilePlugin = (builder, opts = {}) => {
5
+ const { uploadFieldDefinitions = [] } = opts;
6
+ // Determine whether a table attribute should be treated as an Upload according to configuration
7
+ const relevantUploadType = (attr) => {
8
+ const types = uploadFieldDefinitions.filter(({ name, namespaceName, tag }) => (name &&
9
+ namespaceName &&
10
+ attr.type?.name === name &&
11
+ attr.type?.namespaceName === namespaceName) ||
12
+ (tag && attr.tags?.[tag]));
13
+ if (types.length === 1) {
14
+ return types[0];
15
+ }
16
+ else if (types.length > 1) {
17
+ throw new Error('Upload field definitions are ambiguous');
18
+ }
19
+ return undefined;
20
+ };
21
+ builder.hook('build', (input, build) => {
22
+ const { addType, graphql: { GraphQLScalarType, GraphQLError }, } = build;
23
+ const GraphQLUpload = new GraphQLScalarType({
24
+ name: 'Upload',
25
+ description: 'The `Upload` scalar type represents a file upload.',
26
+ parseValue(value) {
27
+ // The value should be an object with a `.promise` that resolves to the file upload
28
+ const maybe = value;
29
+ if (maybe &&
30
+ maybe.promise &&
31
+ typeof maybe.promise.then === 'function') {
32
+ return maybe.promise;
33
+ }
34
+ throw new GraphQLError('Upload value invalid.');
35
+ },
36
+ parseLiteral(ast) {
37
+ throw new GraphQLError('Upload literal unsupported.', ast);
38
+ },
39
+ serialize() {
40
+ throw new GraphQLError('Upload serialization unsupported.');
41
+ },
42
+ });
43
+ addType(GraphQLUpload);
44
+ // Override the internal types for configured upload-backed columns
45
+ uploadFieldDefinitions.forEach(({ name, namespaceName, type }) => {
46
+ if (!name || !type || !namespaceName)
47
+ return; // tag-based or incomplete definitions
48
+ const theType = build.pgIntrospectionResultsByKind.type.find((typ) => typ.name === name && typ.namespaceName === namespaceName);
49
+ if (theType) {
50
+ build.pgRegisterGqlTypeByTypeId(theType.id, () => build.getTypeByName(type));
51
+ }
52
+ });
53
+ return input;
54
+ });
55
+ builder.hook('inflection', (inflection, build) => {
56
+ return build.extend(inflection, {
57
+ // NO ARROW FUNCTIONS HERE (this)
58
+ uploadColumn(attr) {
59
+ return this.column(attr) + 'Upload';
60
+ },
61
+ });
62
+ });
63
+ // Add Upload input fields alongside matching columns
64
+ builder.hook('GraphQLInputObjectType:fields', (fields, build, context) => {
65
+ const { scope: { isPgRowType, pgIntrospection: table }, } = context;
66
+ if (!isPgRowType || !table || table.kind !== 'class') {
67
+ return fields;
68
+ }
69
+ return build.extend(fields, table.attributes.reduce((memo, attr) => {
70
+ if (!build.pgColumnFilter(attr, build, context))
71
+ return memo;
72
+ const action = context.scope.isPgBaseInput
73
+ ? 'base'
74
+ : context.scope.isPgPatch
75
+ ? 'update'
76
+ : 'create';
77
+ if (build.pgOmit(attr, action))
78
+ return memo;
79
+ if (attr.identity === 'a')
80
+ return memo;
81
+ if (!relevantUploadType(attr)) {
82
+ return memo;
83
+ }
84
+ const fieldName = build.inflection.uploadColumn(attr);
85
+ if (memo[fieldName]) {
86
+ throw new Error(`Two columns produce the same GraphQL field name '${fieldName}' on class '${table.namespaceName}.${table.name}'; one of them is '${attr.name}'`);
87
+ }
88
+ memo = build.extend(memo, {
89
+ [fieldName]: context.fieldWithHooks(fieldName, {
90
+ description: attr.description,
91
+ type: build.getTypeByName('Upload'),
92
+ }, { pgFieldIntrospection: attr, isPgUploadField: true }),
93
+ }, `Adding field for ${build.describePgEntity(attr)}. You can rename this field with a 'Smart Comment':\n\n ${build.sqlCommentByAddingTags(attr, {
94
+ name: 'newNameHere',
95
+ })}`);
96
+ return memo;
97
+ }, {}), `Adding columns to '${build.describePgEntity(table)}'`);
98
+ });
99
+ builder.hook('GraphQLObjectType:fields:field', (field, build, context) => {
100
+ const { pgIntrospectionResultsByKind: introspectionResultsByKind, inflection, } = build;
101
+ const { scope: { isRootMutation, fieldName, pgFieldIntrospection: table }, } = context;
102
+ if (!isRootMutation || !table) {
103
+ return field;
104
+ }
105
+ // It's possible that `resolve` isn't specified on a field, so in that case
106
+ // we fall back to a default resolver.
107
+ const defaultResolver = (obj) => obj[fieldName];
108
+ // Extract the old resolver from `field`
109
+ const { resolve: oldResolve = defaultResolver, ...rest } = field; // GraphQLFieldConfig
110
+ const tags = {};
111
+ const types = {};
112
+ const originals = {};
113
+ const uploadResolversByFieldName = introspectionResultsByKind.attribute
114
+ .filter((attr) => attr.classId === table.id)
115
+ .reduce((memo, attr) => {
116
+ // first, try to directly match the types here
117
+ const typeMatched = relevantUploadType(attr);
118
+ if (typeMatched) {
119
+ const fieldName = inflection.column(attr);
120
+ const uploadFieldName = inflection.uploadColumn(attr);
121
+ memo[uploadFieldName] = typeMatched.resolve;
122
+ tags[uploadFieldName] = attr.tags;
123
+ types[uploadFieldName] = attr.type.name;
124
+ originals[uploadFieldName] = fieldName;
125
+ }
126
+ return memo;
127
+ }, {});
128
+ return {
129
+ // Copy over everything except 'resolve'
130
+ ...rest,
131
+ // Add our new resolver which wraps the old resolver
132
+ async resolve(source, args, context, info) {
133
+ // Recursively check for Upload promises to resolve
134
+ async function resolvePromises(obj) {
135
+ for (const key of Object.keys(obj)) {
136
+ if (obj[key] instanceof Promise) {
137
+ if (uploadResolversByFieldName[key]) {
138
+ const upload = await obj[key];
139
+ // eslint-disable-next-line require-atomic-updates
140
+ obj[originals[key]] = await uploadResolversByFieldName[key](upload, args, context, {
141
+ ...info,
142
+ uploadPlugin: { tags: tags[key], type: types[key] },
143
+ });
144
+ }
145
+ }
146
+ else if (obj[key] !== null && typeof obj[key] === 'object') {
147
+ await resolvePromises(obj[key]);
148
+ }
149
+ }
150
+ }
151
+ await resolvePromises(args);
152
+ // Call the old resolver
153
+ const oldResolveResult = await oldResolve(source, args, context, info);
154
+ // Finally return the result.
155
+ return oldResolveResult;
156
+ },
157
+ };
158
+ });
159
+ };
160
+ exports.default = UploadPostGraphilePlugin;