buro26-strapi-graphql 0.0.26 → 0.1.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.
Files changed (36) hide show
  1. package/README.md +353 -446
  2. package/dist/server/index.d.ts +13 -7
  3. package/dist/server/index.js +1 -0
  4. package/dist/server/nexus/index.d.ts +1 -0
  5. package/dist/server/nexus/index.js +17 -0
  6. package/dist/server/nexus/plugins/field-authorize.plugin.d.ts +15 -0
  7. package/dist/server/nexus/plugins/field-authorize.plugin.js +89 -0
  8. package/dist/server/nexus/plugins/index.d.ts +2 -0
  9. package/dist/server/nexus/plugins/index.js +18 -0
  10. package/dist/server/nexus/plugins/middleware.plugin.d.ts +17 -0
  11. package/dist/server/{utils/middleware.js → nexus/plugins/middleware.plugin.js} +2 -3
  12. package/dist/server/register.js +6 -7
  13. package/dist/server/services/file-service.js +7 -1
  14. package/dist/server/types.d.ts +10 -10
  15. package/dist/server/utils/field-builder/builder.d.ts +24 -0
  16. package/dist/server/utils/field-builder/builder.js +510 -0
  17. package/dist/server/utils/field-builder/helpers.d.ts +19 -0
  18. package/dist/server/utils/field-builder/helpers.js +56 -0
  19. package/dist/server/utils/field-builder/index.d.ts +3 -0
  20. package/dist/server/utils/field-builder/index.js +19 -0
  21. package/dist/server/utils/field-builder/types.d.ts +160 -0
  22. package/dist/server/utils/field-builder/types.js +2 -0
  23. package/dist/server/utils/graphql-extension.d.ts +5 -0
  24. package/dist/server/utils/graphql-extension.js +26 -24
  25. package/dist/server/utils/index.d.ts +1 -1
  26. package/dist/server/utils/index.js +1 -1
  27. package/dist/server/utils/override.d.ts +2 -1
  28. package/dist/server/utils/registry/global-registry.d.ts +19 -0
  29. package/dist/server/utils/registry/global-registry.js +21 -0
  30. package/dist/server/utils/registry/index.d.ts +1 -0
  31. package/dist/server/utils/registry/index.js +17 -0
  32. package/dist/tsconfig.server.tsbuildinfo +1 -1
  33. package/package.json +5 -3
  34. package/dist/server/utils/field-builder.d.ts +0 -31
  35. package/dist/server/utils/field-builder.js +0 -113
  36. package/dist/server/utils/middleware.d.ts +0 -17
@@ -1,5 +1,6 @@
1
1
  import type { GraphQLExtension } from './types';
2
- import type { Middleware, ResolveContext } from './utils';
2
+ import type { ResolveContext } from './utils';
3
+ import type { Middleware } from './nexus';
3
4
  import type { GraphQLResolveInfo } from 'graphql';
4
5
  import type { GraphQLFieldConfig } from 'graphql/type';
5
6
  declare const _default: {
@@ -39,6 +40,7 @@ declare const _default: {
39
40
  export default _default;
40
41
  export * from './types';
41
42
  export * from './utils';
43
+ export * from './nexus';
42
44
  declare module '@strapi/strapi' {
43
45
  interface Strapi {
44
46
  createGraphQLExtension: (factory: (strapi: Strapi) => GraphQLExtension) => GraphQLExtension;
@@ -59,14 +61,18 @@ declare module 'nexus/dist/core' {
59
61
  interface NexusOutputFieldConfig<TypeName extends string, FieldName extends string> {
60
62
  extensions?: {
61
63
  middlewares?: Middleware[];
64
+ /**
65
+ * A function that determines if the current user is authorized to access this field.
66
+ *
67
+ * @param parent The parent object.
68
+ * @param args The arguments passed to the field.
69
+ * @param context The context object.
70
+ * @param info The GraphQLResolveInfo object.
71
+ */
72
+ authorize?: <Parent extends Object, Args extends Object, Context = ResolveContext>(parent: Parent, args: Args, context: Context, info: GraphQLResolveInfo) => boolean | Promise<boolean>;
62
73
  } & GraphQLFieldConfig<any, any>['extensions'];
63
74
  /**
64
- * A function that determines if the current user is authorized to access this field.
65
- *
66
- * @param parent The parent object.
67
- * @param args The arguments passed to the field.
68
- * @param context The context object.
69
- * @param info The GraphQLResolveInfo object.
75
+ * @deprecated Use `authorize` in the extensions config instead.
70
76
  */
71
77
  authorize?: <Parent extends Object, Args extends Object, Context = ResolveContext>(parent: Parent, args: Args, context: Context, info: GraphQLResolveInfo) => boolean | Promise<boolean>;
72
78
  }
@@ -41,3 +41,4 @@ exports.default = {
41
41
  };
42
42
  __exportStar(require("./types"), exports);
43
43
  __exportStar(require("./utils"), exports);
44
+ __exportStar(require("./nexus"), exports);
@@ -0,0 +1 @@
1
+ export * from './plugins';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./plugins"), exports);
@@ -0,0 +1,15 @@
1
+ import { ArgsValue, GetGen, MaybePromise, SourceValue } from 'nexus/dist/typegenTypeHelpers';
2
+ import type { GraphQLResolveInfo } from 'graphql';
3
+ export type FieldAuthorizeResolver<TypeName extends string, FieldName extends string> = (root: SourceValue<TypeName>, args: ArgsValue<TypeName, FieldName>, context: GetGen<'context'>, info: GraphQLResolveInfo) => MaybePromise<boolean | Error>;
4
+ export interface FieldAuthorizePluginErrorConfig {
5
+ error: Error;
6
+ root: any;
7
+ args: any;
8
+ ctx: GetGen<'context'>;
9
+ info: GraphQLResolveInfo;
10
+ }
11
+ export interface FieldAuthorizePluginConfig {
12
+ formatError?: (authConfig: FieldAuthorizePluginErrorConfig) => Error;
13
+ }
14
+ export declare const defaultFormatError: ({ error, root, args, ctx, info }: FieldAuthorizePluginErrorConfig) => Error;
15
+ export declare const nexusFieldAuthorizePlugin: (authConfig?: FieldAuthorizePluginConfig) => import("nexus/dist/plugin").NexusPlugin;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.nexusFieldAuthorizePlugin = exports.defaultFormatError = void 0;
4
+ const nexus_1 = require("nexus");
5
+ const utils_1 = require("nexus/dist/utils");
6
+ const utils_2 = require("@strapi/utils");
7
+ const fieldDefTypes = (0, utils_1.printedGenTyping)({
8
+ optional: true,
9
+ name: 'authorize',
10
+ description: `
11
+ Authorization for an individual field. Returning "true"
12
+ or "Promise<true>" means the field can be accessed.
13
+ Returning "false" or "Promise<false>" will respond
14
+ with a "Not Authorized" error for the field.
15
+ Returning or throwing an error will also prevent the
16
+ resolver from executing.
17
+ `,
18
+ type: 'FieldAuthorizeResolver<TypeName, FieldName>',
19
+ });
20
+ const defaultFormatError = ({ error, root, args, ctx, info }) => {
21
+ var _a, _b;
22
+ // Add rich tracing info
23
+ const trace = {
24
+ type: info.parentType.name,
25
+ field: info.fieldName,
26
+ user: (_b = (_a = ctx === null || ctx === void 0 ? void 0 : ctx.state) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.id,
27
+ args,
28
+ timestamp: new Date().toISOString(),
29
+ originalError: error
30
+ };
31
+ // Use Strapi's ForbiddenError and attach trace info
32
+ return new utils_2.errors.ForbiddenError((error === null || error === void 0 ? void 0 : error.message) || 'Not authorized', { trace });
33
+ };
34
+ exports.defaultFormatError = defaultFormatError;
35
+ const nexusFieldAuthorizePlugin = (authConfig = {}) => {
36
+ const { formatError = exports.defaultFormatError } = authConfig;
37
+ const ensureError = (root, args, ctx, info) => (error) => {
38
+ const finalErr = formatError({ error, root, args, ctx, info });
39
+ if (finalErr instanceof Error) {
40
+ throw finalErr;
41
+ }
42
+ console.error(`Non-Error value ${finalErr} returned from custom formatError in authorize plugin`);
43
+ throw new utils_2.errors.ForbiddenError('Not authorized');
44
+ };
45
+ return (0, nexus_1.plugin)({
46
+ name: 'CustomFieldAuthorize',
47
+ description: 'Custom field-level authorization for Strapi GraphQL, with tracing.',
48
+ fieldDefTypes: fieldDefTypes,
49
+ onCreateFieldResolver(config) {
50
+ var _a;
51
+ // @ts-ignore
52
+ const authorize = (_a = config.fieldConfig.extensions) === null || _a === void 0 ? void 0 : _a.authorize;
53
+ if (authorize == null) {
54
+ return;
55
+ }
56
+ if (typeof authorize !== 'function') {
57
+ console.error(new Error(`The authorize property provided to ${config.fieldConfig.name} with type ${config.fieldConfig.type} should be a function, saw ${typeof authorize}`));
58
+ return;
59
+ }
60
+ return function (root, args, ctx, info, next) {
61
+ console.log(`Running authorize for ${info.parentType.name}.${info.fieldName}`);
62
+ let toComplete;
63
+ try {
64
+ toComplete = authorize(root, args, ctx, info);
65
+ }
66
+ catch (e) {
67
+ toComplete = Promise.reject(e);
68
+ }
69
+ return nexus_1.plugin.completeValue(toComplete, (authResult) => {
70
+ if (authResult === true) {
71
+ return next(root, args, ctx, info);
72
+ }
73
+ const finalFormatError = ensureError(root, args, ctx, info);
74
+ if (authResult instanceof Error) {
75
+ finalFormatError(authResult);
76
+ }
77
+ if (authResult === false) {
78
+ finalFormatError(new utils_2.errors.ForbiddenError('Not authorized'));
79
+ }
80
+ const { fieldName, parentType: { name: parentTypeName } } = info;
81
+ finalFormatError(new utils_2.errors.ForbiddenError(`Authorize for ${parentTypeName}.${fieldName} Expected a boolean or Error, saw ${authResult}`));
82
+ }, (err) => {
83
+ ensureError(root, args, ctx, info)(err);
84
+ });
85
+ };
86
+ }
87
+ });
88
+ };
89
+ exports.nexusFieldAuthorizePlugin = nexusFieldAuthorizePlugin;
@@ -0,0 +1,2 @@
1
+ export * from './field-authorize.plugin';
2
+ export * from './middleware.plugin';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./field-authorize.plugin"), exports);
18
+ __exportStar(require("./middleware.plugin"), exports);
@@ -0,0 +1,17 @@
1
+ import type { GraphQLResolveInfo } from 'graphql';
2
+ import type { ResolverFunction } from '../../types';
3
+ import type { ResolveContext } from '../../utils';
4
+ /**
5
+ * The Resolver type represents a GraphQL resolver function.
6
+ */
7
+ export type Resolver = <Parent extends any, Args extends any, Context = ResolveContext>(parent: Parent, args: Args, context: Context, info: GraphQLResolveInfo) => any | Promise<any>;
8
+ /**
9
+ * Middleware is a function that takes a resolver and returns a new resolver.
10
+ */
11
+ export type Middleware<TParent = any, TArgs = any> = (resolver: ResolverFunction<TParent, TArgs>) => ResolverFunction<TParent, TArgs>;
12
+ export declare const nexusMiddlewarePlugin: () => import("nexus/dist/plugin").NexusPlugin;
13
+ /**
14
+ * Logging Middleware
15
+ * Logs the execution of the resolver.
16
+ */
17
+ export declare const loggingMiddleware: Middleware;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loggingMiddleware = exports.nexusMiddlewarePlugin = void 0;
4
- require("nexus");
5
4
  const nexus_1 = require("nexus");
6
5
  const utils_1 = require("nexus/dist/utils");
7
6
  const fieldDefTypes = (0, utils_1.printedGenTyping)({
@@ -15,7 +14,7 @@ const fieldDefTypes = (0, utils_1.printedGenTyping)({
15
14
  Returning or throwing an error will also prevent the
16
15
  resolver from executing.
17
16
  `,
18
- type: 'any',
17
+ type: 'any'
19
18
  });
20
19
  const nexusMiddlewarePlugin = () => (0, nexus_1.plugin)({
21
20
  name: 'NexusMiddlewarePlugin',
@@ -59,7 +58,7 @@ const nexusMiddlewarePlugin = () => (0, nexus_1.plugin)({
59
58
  };
60
59
  return dispatch(0);
61
60
  };
62
- },
61
+ }
63
62
  });
64
63
  exports.nexusMiddlewarePlugin = nexusMiddlewarePlugin;
65
64
  /**
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const nexus_1 = require("nexus");
4
- const utils_1 = require("./utils");
3
+ const nexus_1 = require("./nexus");
5
4
  exports.default = async ({ strapi }) => {
6
5
  const fileService = strapi
7
6
  .plugin('burotwosix-graphql-plugin')
@@ -14,8 +13,8 @@ exports.default = async ({ strapi }) => {
14
13
  ];
15
14
  graphQlExtensionService.use(() => ({
16
15
  plugins: [
17
- (0, nexus_1.fieldAuthorizePlugin)(),
18
- (0, utils_1.nexusMiddlewarePlugin)(),
16
+ (0, nexus_1.nexusFieldAuthorizePlugin)(),
17
+ (0, nexus_1.nexusMiddlewarePlugin)()
19
18
  ]
20
19
  }));
21
20
  for (const extension of extensions) {
@@ -26,14 +25,14 @@ exports.default = async ({ strapi }) => {
26
25
  typeDefs: (_b = (_a = extension === null || extension === void 0 ? void 0 : extension.typeDefs) === null || _a === void 0 ? void 0 : _a.call(extension)) !== null && _b !== void 0 ? _b : '',
27
26
  types: [
28
27
  ...((_d = (_c = extension === null || extension === void 0 ? void 0 : extension.getTypes) === null || _c === void 0 ? void 0 : _c.call(extension)) !== null && _d !== void 0 ? _d : []),
29
- ...((_f = (_e = extension === null || extension === void 0 ? void 0 : extension.types) === null || _e === void 0 ? void 0 : _e.call(extension)) !== null && _f !== void 0 ? _f : []),
28
+ ...((_f = (_e = extension === null || extension === void 0 ? void 0 : extension.types) === null || _e === void 0 ? void 0 : _e.call(extension)) !== null && _f !== void 0 ? _f : [])
30
29
  ],
31
30
  plugins: (_h = (_g = extension === null || extension === void 0 ? void 0 : extension.plugins) === null || _g === void 0 ? void 0 : _g.call(extension)) !== null && _h !== void 0 ? _h : [],
32
31
  resolvers: (_k = (_j = extension === null || extension === void 0 ? void 0 : extension.resolvers) === null || _j === void 0 ? void 0 : _j.call(extension)) !== null && _k !== void 0 ? _k : { Query: {}, Mutation: {} },
33
32
  resolversConfig: {
34
33
  ...(_m = (_l = extension === null || extension === void 0 ? void 0 : extension.getResolverConfig) === null || _l === void 0 ? void 0 : _l.call(extension)) !== null && _m !== void 0 ? _m : {},
35
- ...(_p = (_o = extension === null || extension === void 0 ? void 0 : extension.resolversConfig) === null || _o === void 0 ? void 0 : _o.call(extension)) !== null && _p !== void 0 ? _p : {},
36
- },
34
+ ...(_p = (_o = extension === null || extension === void 0 ? void 0 : extension.resolversConfig) === null || _o === void 0 ? void 0 : _o.call(extension)) !== null && _p !== void 0 ? _p : {}
35
+ }
37
36
  });
38
37
  });
39
38
  }
@@ -59,7 +59,13 @@ exports.default = ({ strapi }) => ({
59
59
  if (extension && typeof extension.build === 'function') {
60
60
  extension = extension.build();
61
61
  }
62
- collectedExtensions.push(extension);
62
+ // If it's an array, flatten and push all
63
+ if (Array.isArray(extension)) {
64
+ collectedExtensions.push(...extension.map(ext => ext.build ? ext.build() : ext));
65
+ }
66
+ else if (extension) {
67
+ collectedExtensions.push(extension);
68
+ }
63
69
  });
64
70
  // Wait for all the promises to resolve
65
71
  await Promise.all(filePromises);
@@ -53,14 +53,14 @@ export interface GraphQLExtension {
53
53
  */
54
54
  resolversConfig?: () => Record<string, ResolverConfigOption>;
55
55
  }
56
- export type ResolverConfigOption = {
56
+ export type ResolverConfigOption<TParent = any, TArgs = any, TOutput = any> = {
57
57
  auth?: boolean | undefined;
58
- policies?: (string | PolicyFunction)[];
59
- middlewares?: MiddlewareFunction[];
58
+ policies?: (string | PolicyFunction<TParent, TArgs>)[];
59
+ middlewares?: MiddlewareFunction<TParent, TArgs, TOutput>[];
60
60
  };
61
- export type PolicyFunctionContext = {
62
- parent: any;
63
- args: any;
61
+ export type PolicyFunctionContext<TParent = any, TArgs = any> = {
62
+ parent: TParent;
63
+ args: TArgs;
64
64
  context: ResolveContext;
65
65
  info: GraphQLResolveInfo;
66
66
  state: ResolveContext['state'];
@@ -69,7 +69,7 @@ export type PolicyFunctionContext = {
69
69
  export type PolicyFunctionOptions = {
70
70
  strapi: Strapi;
71
71
  };
72
- export type PolicyFunction = (context: PolicyFunctionContext, config: any, opts: PolicyFunctionOptions) => boolean | Promise<boolean>;
73
- export type MiddlewareFunction = (next: MiddlewareNextFunction, parent: any, args: any, context: ResolveContext, info: GraphQLResolveInfo) => any | Promise<any>;
74
- export type MiddlewareNextFunction = (parent: any, args: any, context: ResolveContext, info: GraphQLResolveInfo) => Promise<any>;
75
- export type ResolverFunction = (parent: any, args: any, context: ResolveContext, info: GraphQLResolveInfo) => any | Promise<any>;
72
+ export type PolicyFunction<TParent = any, TArgs = any> = (context: PolicyFunctionContext<TParent, TArgs>, config: any, opts: PolicyFunctionOptions) => boolean | Promise<boolean>;
73
+ export type MiddlewareFunction<TParent = any, TArgs = any, TOutput = any> = (next: MiddlewareNextFunction<TParent, TArgs, TOutput>, parent: TParent, args: TArgs, context: ResolveContext, info: GraphQLResolveInfo) => TOutput | Promise<TOutput>;
74
+ export type MiddlewareNextFunction<TParent = any, TArgs = any, TOutput = any> = (parent: TParent, args: TArgs, context: ResolveContext, info: GraphQLResolveInfo) => Promise<TOutput>;
75
+ export type ResolverFunction<TParent = any, TArgs = any, TOutput = any> = (parent: TParent, args: TArgs, context: ResolveContext, info: GraphQLResolveInfo) => TOutput | Promise<TOutput>;
@@ -0,0 +1,24 @@
1
+ import type { FieldExtensionBuilder, FieldExtensionOptions, GraphQLFieldHook } from './types';
2
+ import type { ResolverFunction } from '../../types';
3
+ import type { Middleware } from '../../nexus';
4
+ /**
5
+ * Internal state for the builder.
6
+ */
7
+ type BuilderState<Type = any, TArgs = any, TOutput = any> = {
8
+ options: FieldExtensionOptions<Type, TArgs, TOutput>;
9
+ initFunctions: Array<() => void>;
10
+ typeFunctions: Array<() => unknown[]>;
11
+ middlewareFunctions: Middleware[];
12
+ authorizeFunctions: ResolverFunction<Partial<Type> | null, TArgs, boolean>[];
13
+ hooks: GraphQLFieldHook[];
14
+ built: boolean;
15
+ };
16
+ /**
17
+ * Creates a fluent, deeply immutable builder to extend a root field in the GraphQL schema.
18
+ * Each method returns a new builder instance with its own state.
19
+ *
20
+ * @param rootType - Either 'Query' or 'Mutation' or any other Type to extend.
21
+ * @param _state
22
+ */
23
+ export declare const createGraphQLFieldBuilder: <Type = any, TArgs = any, TOutput = Type>(rootType?: string, _state?: BuilderState<Type, TArgs, TOutput>) => FieldExtensionBuilder<Type, TArgs, TOutput>;
24
+ export {};