buro26-strapi-graphql 0.0.24 → 0.0.26
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/README.md +72 -1
- package/dist/server/bootstrap.d.ts +1 -1
- package/dist/server/controllers/index.d.ts +1 -1
- package/dist/server/controllers/my-controller.d.ts +1 -1
- package/dist/server/destroy.d.ts +1 -1
- package/dist/server/index.d.ts +11 -8
- package/dist/server/index.js +0 -3
- package/dist/server/services/file-service.d.ts +1 -2
- package/dist/server/services/file-service.js +7 -4
- package/dist/server/services/graphql-service.d.ts +1 -1
- package/dist/server/services/index.d.ts +2 -2
- package/dist/server/types.d.ts +8 -9
- package/dist/server/utils/field-builder.d.ts +31 -0
- package/dist/server/utils/field-builder.js +113 -0
- package/dist/server/utils/graphql-extension.d.ts +25 -0
- package/dist/server/utils/graphql-extension.js +55 -0
- package/dist/server/utils/index.d.ts +3 -0
- package/dist/server/utils/index.js +3 -0
- package/dist/server/utils/shadow-crud.d.ts +30 -0
- package/dist/server/utils/shadow-crud.js +8 -0
- package/dist/tsconfig.server.tsbuildinfo +1 -1
- package/package.json +28 -34
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@ as co-location of GraphQL schema and resolvers, field overriding, and field auth
|
|
|
6
6
|
This let's you define your GraphQL schema and resolvers in the content-type directory, making it easier to manage and
|
|
7
7
|
maintain your GraphQL API.
|
|
8
8
|
|
|
9
|
+
This plugin is compatible with both Strapi v4 and Strapi v5.
|
|
10
|
+
|
|
9
11
|
## Getting started
|
|
10
12
|
|
|
11
13
|
```bash
|
|
@@ -21,7 +23,7 @@ the [Strapi GraphQL plugin](https://docs.strapi.io/dev-docs/plugins/graphql).
|
|
|
21
23
|
|
|
22
24
|
### Enable plugin
|
|
23
25
|
|
|
24
|
-
Add plugin in `./config/plugins.js/ts` in your Strapi project.
|
|
26
|
+
Add plugin in `./config/plugins.[js/ts]` in your Strapi project.
|
|
25
27
|
|
|
26
28
|
```typescript
|
|
27
29
|
export default () => ({
|
|
@@ -156,6 +158,54 @@ export default createGraphQLExtension(strapi => ({
|
|
|
156
158
|
}));
|
|
157
159
|
```
|
|
158
160
|
|
|
161
|
+
### Fluent Builder Pattern
|
|
162
|
+
The plugin also supports a builder pattern so that you can configure your extension using a fluent API. This is achieved by calling createGraphQLExtension() with no arguments. For example, you can write:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
export default createGraphQLExtension()
|
|
166
|
+
.init(() => {
|
|
167
|
+
// Initialization logic here...
|
|
168
|
+
})
|
|
169
|
+
.typeDefs(`
|
|
170
|
+
extend type Query {
|
|
171
|
+
hello: String
|
|
172
|
+
}
|
|
173
|
+
`)
|
|
174
|
+
.resolvers({
|
|
175
|
+
Query: {
|
|
176
|
+
hello: () => 'Hello from builder!'
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
In this pattern, `createGraphQLExtension()` detects that no argument was passed and returns a builder. The builder exposes methods like `.init()`, `.typeDefs()`, `.types()`, `.plugins()`, `.resolvers()`, and `.resolversConfig()` so you can chain calls and define your extension inline.
|
|
182
|
+
|
|
183
|
+
### Shorter way to define a new field
|
|
184
|
+
|
|
185
|
+
The `createGraphQLFieldBuilder()` function provides a fluent builder API to create a single GraphQL field extension using Nexus. It simplifies the process of extending the GraphQL schema by letting you define the field's name, arguments, output type, resolver, and resolver configuration in a chainable way.
|
|
186
|
+
|
|
187
|
+
The builder pattern ensures that you only need to specify the necessary parts, and the extension is automatically registered using the provided settings. This approach minimizes boilerplate code while ensuring consistency across your GraphQL extensions.
|
|
188
|
+
|
|
189
|
+
Below is an example of how to define a new field using the builder pattern. This example creates a new query field called `helloWorld` that takes a non-null `name` argument and returns a non-null `String`.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { createGraphQLFieldBuilder } from "buro26-strapi-graphql";
|
|
193
|
+
import { nonNull, stringArg } from 'nexus';
|
|
194
|
+
|
|
195
|
+
export default createGraphQLFieldBuilder('Query')
|
|
196
|
+
.fieldName('helloWorld')
|
|
197
|
+
.args({
|
|
198
|
+
name: nonNull(stringArg()),
|
|
199
|
+
})
|
|
200
|
+
.outputType(nonNull('String'))
|
|
201
|
+
.resolver(async (parent, args, ctx) => {
|
|
202
|
+
return `Hello World ${args.name}`;
|
|
203
|
+
})
|
|
204
|
+
.resolverConfig({
|
|
205
|
+
auth: false,
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
159
209
|
### Overriding a field
|
|
160
210
|
|
|
161
211
|
Sometimes you will need to override a field in an existing type. You can do this by extending the type and adding the
|
|
@@ -487,6 +537,27 @@ args into args that can be passed to the entityManager.
|
|
|
487
537
|
|
|
488
538
|
This function is re-exported from the Strapi GraphQL plugin.
|
|
489
539
|
|
|
540
|
+
#### shadowCRUD
|
|
541
|
+
|
|
542
|
+
This function is a typesafe utility function to create shadow CRUD operations for a content type. It will create the CRUD operations for the content type and return the shadow CRUD object.
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
import { createGraphQLExtension, shadowCRUD } from 'buro26-strapi-graphql';
|
|
546
|
+
|
|
547
|
+
export default createGraphQLExtension((strapi) => ({
|
|
548
|
+
|
|
549
|
+
init() {
|
|
550
|
+
shadowCRUD('api::article.article')
|
|
551
|
+
.disableActions(['create', 'update', 'delete']);
|
|
552
|
+
|
|
553
|
+
shadowCRUD('api::category.category')
|
|
554
|
+
.field('title')
|
|
555
|
+
.disable();
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
}));
|
|
559
|
+
```
|
|
560
|
+
|
|
490
561
|
## Test and Deploy
|
|
491
562
|
|
|
492
563
|
### Running tests
|
package/dist/server/destroy.d.ts
CHANGED
package/dist/server/index.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import type { Strapi } from '@strapi/strapi';
|
|
2
1
|
import type { GraphQLExtension } from './types';
|
|
3
2
|
import type { Middleware, ResolveContext } from './utils';
|
|
4
3
|
import type { GraphQLResolveInfo } from 'graphql';
|
|
5
4
|
import type { GraphQLFieldConfig } from 'graphql/type';
|
|
6
5
|
declare const _default: {
|
|
7
6
|
register: ({ strapi }: {
|
|
8
|
-
strapi: Strapi;
|
|
7
|
+
strapi: import("@strapi/types").Strapi;
|
|
9
8
|
}) => Promise<void>;
|
|
10
9
|
bootstrap: ({ strapi }: {
|
|
11
|
-
strapi: Strapi
|
|
10
|
+
strapi: Required<import("@strapi/types").Strapi>;
|
|
12
11
|
}) => void;
|
|
13
12
|
destroy: ({ strapi }: {
|
|
14
|
-
strapi: Strapi
|
|
13
|
+
strapi: Required<import("@strapi/types").Strapi>;
|
|
15
14
|
}) => void;
|
|
16
15
|
config: {
|
|
17
16
|
default: {};
|
|
@@ -19,18 +18,18 @@ declare const _default: {
|
|
|
19
18
|
};
|
|
20
19
|
controllers: {
|
|
21
20
|
myController: ({ strapi }: {
|
|
22
|
-
strapi: Strapi
|
|
21
|
+
strapi: Required<import("@strapi/types").Strapi>;
|
|
23
22
|
}) => {};
|
|
24
23
|
};
|
|
25
24
|
routes: any[];
|
|
26
25
|
services: {
|
|
27
26
|
fileService: ({ strapi }: {
|
|
28
|
-
strapi: Strapi
|
|
27
|
+
strapi: Required<import("@strapi/types").Strapi>;
|
|
29
28
|
}) => {
|
|
30
29
|
getAllFilesInGraphQlDirectory(directoryPath: string, collectedExtensions?: GraphQLExtension[]): Promise<GraphQLExtension[]>;
|
|
31
30
|
};
|
|
32
31
|
graphQlService: ({ strapi }: {
|
|
33
|
-
strapi: Strapi
|
|
32
|
+
strapi: Required<import("@strapi/types").Strapi>;
|
|
34
33
|
}) => {};
|
|
35
34
|
};
|
|
36
35
|
contentTypes: {};
|
|
@@ -40,12 +39,16 @@ declare const _default: {
|
|
|
40
39
|
export default _default;
|
|
41
40
|
export * from './types';
|
|
42
41
|
export * from './utils';
|
|
43
|
-
export declare const createGraphQLExtension: (factory: (strapi: Strapi) => GraphQLExtension) => GraphQLExtension;
|
|
44
42
|
declare module '@strapi/strapi' {
|
|
45
43
|
interface Strapi {
|
|
46
44
|
createGraphQLExtension: (factory: (strapi: Strapi) => GraphQLExtension) => GraphQLExtension;
|
|
47
45
|
}
|
|
48
46
|
}
|
|
47
|
+
declare module '@strapi/types' {
|
|
48
|
+
interface Strapi {
|
|
49
|
+
createGraphQLExtension: (factory: (strapi: Strapi) => GraphQLExtension) => GraphQLExtension;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
49
52
|
/**
|
|
50
53
|
* Extend Nexus's field definition to include a middleware array.
|
|
51
54
|
*/
|
package/dist/server/index.js
CHANGED
|
@@ -17,7 +17,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.createGraphQLExtension = void 0;
|
|
21
20
|
const register_1 = __importDefault(require("./register"));
|
|
22
21
|
const bootstrap_1 = __importDefault(require("./bootstrap"));
|
|
23
22
|
const destroy_1 = __importDefault(require("./destroy"));
|
|
@@ -42,5 +41,3 @@ exports.default = {
|
|
|
42
41
|
};
|
|
43
42
|
__exportStar(require("./types"), exports);
|
|
44
43
|
__exportStar(require("./utils"), exports);
|
|
45
|
-
const createGraphQLExtension = (factory) => factory(strapi);
|
|
46
|
-
exports.createGraphQLExtension = createGraphQLExtension;
|
|
@@ -53,10 +53,13 @@ exports.default = ({ strapi }) => ({
|
|
|
53
53
|
if (!graphqlModule) {
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
// Support both ES module default export and CommonJS exports
|
|
57
|
+
let extension = graphqlModule.default || graphqlModule;
|
|
58
|
+
// If the extension is a builder (has a build function), call build() automatically
|
|
59
|
+
if (extension && typeof extension.build === 'function') {
|
|
60
|
+
extension = extension.build();
|
|
61
|
+
}
|
|
62
|
+
collectedExtensions.push(extension);
|
|
60
63
|
});
|
|
61
64
|
// Wait for all the promises to resolve
|
|
62
65
|
await Promise.all(filePromises);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
2
|
fileService: ({ strapi }: {
|
|
3
|
-
strapi: import("@strapi/types").Strapi
|
|
3
|
+
strapi: Required<import("@strapi/types").Strapi>;
|
|
4
4
|
}) => {
|
|
5
5
|
getAllFilesInGraphQlDirectory(directoryPath: string, collectedExtensions?: import("..").GraphQLExtension[]): Promise<import("..").GraphQLExtension[]>;
|
|
6
6
|
};
|
|
7
7
|
graphQlService: ({ strapi }: {
|
|
8
|
-
strapi: import("@strapi/types").Strapi
|
|
8
|
+
strapi: Required<import("@strapi/types").Strapi>;
|
|
9
9
|
}) => {};
|
|
10
10
|
};
|
|
11
11
|
export default _default;
|
package/dist/server/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ResolveContext } from './utils';
|
|
2
2
|
import type { GraphQLResolveInfo } from 'graphql';
|
|
3
|
-
|
|
3
|
+
export type Strapi = typeof strapi;
|
|
4
4
|
export interface GraphQLExtension {
|
|
5
5
|
/**
|
|
6
6
|
* Called when the extension is initialized, use this to perform any initialization logic
|
|
@@ -53,12 +53,12 @@ export interface GraphQLExtension {
|
|
|
53
53
|
*/
|
|
54
54
|
resolversConfig?: () => Record<string, ResolverConfigOption>;
|
|
55
55
|
}
|
|
56
|
-
type ResolverConfigOption = {
|
|
56
|
+
export type ResolverConfigOption = {
|
|
57
57
|
auth?: boolean | undefined;
|
|
58
58
|
policies?: (string | PolicyFunction)[];
|
|
59
59
|
middlewares?: MiddlewareFunction[];
|
|
60
60
|
};
|
|
61
|
-
type PolicyFunctionContext = {
|
|
61
|
+
export type PolicyFunctionContext = {
|
|
62
62
|
parent: any;
|
|
63
63
|
args: any;
|
|
64
64
|
context: ResolveContext;
|
|
@@ -66,11 +66,10 @@ type PolicyFunctionContext = {
|
|
|
66
66
|
state: ResolveContext['state'];
|
|
67
67
|
http: any;
|
|
68
68
|
};
|
|
69
|
-
type PolicyFunctionOptions = {
|
|
69
|
+
export type PolicyFunctionOptions = {
|
|
70
70
|
strapi: Strapi;
|
|
71
71
|
};
|
|
72
|
-
type PolicyFunction = (context: PolicyFunctionContext, config: any, opts: PolicyFunctionOptions) => boolean | Promise<boolean>;
|
|
73
|
-
type MiddlewareFunction = (next: MiddlewareNextFunction, parent: any, args: any, context: ResolveContext, info: GraphQLResolveInfo) => any | Promise<any>;
|
|
74
|
-
type MiddlewareNextFunction = (parent: any, args: any, context: ResolveContext, info: GraphQLResolveInfo) => Promise<any>;
|
|
75
|
-
type ResolverFunction = (parent: any, args: any, context: ResolveContext, info: GraphQLResolveInfo) => any | Promise<any>;
|
|
76
|
-
export {};
|
|
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>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { GraphQLExtension, ResolverConfigOption, ResolverFunction } from '../types';
|
|
2
|
+
export type FieldExtensionOptions = {
|
|
3
|
+
rootType: string;
|
|
4
|
+
fieldName?: string;
|
|
5
|
+
resolver: ResolverFunction;
|
|
6
|
+
resolverConfig?: ResolverConfigOption;
|
|
7
|
+
typeDefs?: string;
|
|
8
|
+
types?: () => any[];
|
|
9
|
+
plugins?: () => any[];
|
|
10
|
+
args?: Record<string, string | any>;
|
|
11
|
+
outputType?: string | any;
|
|
12
|
+
};
|
|
13
|
+
export interface FieldExtensionBuilder {
|
|
14
|
+
fieldName(name: string): FieldExtensionBuilder;
|
|
15
|
+
resolver(fn: ResolverFunction): FieldExtensionBuilder;
|
|
16
|
+
resolverConfig(config: ResolverConfigOption): FieldExtensionBuilder;
|
|
17
|
+
typeDefs(sdl: string): FieldExtensionBuilder;
|
|
18
|
+
types(typesFn: () => any[]): FieldExtensionBuilder;
|
|
19
|
+
plugins(pluginsFn: () => any[]): FieldExtensionBuilder;
|
|
20
|
+
args(a: Record<string, string | any>): FieldExtensionBuilder;
|
|
21
|
+
outputType(type: string | any): FieldExtensionBuilder;
|
|
22
|
+
build(): GraphQLExtension;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Creates a fluent builder to extend a root field in the GraphQL schema.
|
|
26
|
+
* The field is automatically registered using Nexus. The output type must be defined
|
|
27
|
+
* using the outputType callback.
|
|
28
|
+
*
|
|
29
|
+
* @param rootType - Either 'Query' or 'Mutation'
|
|
30
|
+
*/
|
|
31
|
+
export declare const createGraphQLFieldBuilder: (rootType: string) => FieldExtensionBuilder;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createGraphQLFieldBuilder = void 0;
|
|
4
|
+
const nexus_1 = require("nexus");
|
|
5
|
+
const graphql_extension_1 = require("./graphql-extension");
|
|
6
|
+
/**
|
|
7
|
+
* Creates a fluent builder to extend a root field in the GraphQL schema.
|
|
8
|
+
* The field is automatically registered using Nexus. The output type must be defined
|
|
9
|
+
* using the outputType callback.
|
|
10
|
+
*
|
|
11
|
+
* @param rootType - Either 'Query' or 'Mutation'
|
|
12
|
+
*/
|
|
13
|
+
const createGraphQLFieldBuilder = (rootType) => {
|
|
14
|
+
const options = {
|
|
15
|
+
rootType,
|
|
16
|
+
fieldName: undefined,
|
|
17
|
+
resolver: () => {
|
|
18
|
+
throw new Error('Resolver function must be provided via .resolver()');
|
|
19
|
+
},
|
|
20
|
+
resolverConfig: {},
|
|
21
|
+
typeDefs: '',
|
|
22
|
+
types: () => [],
|
|
23
|
+
plugins: () => [],
|
|
24
|
+
args: {},
|
|
25
|
+
outputType: undefined
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
fieldName(name) {
|
|
29
|
+
options.fieldName = name;
|
|
30
|
+
return this;
|
|
31
|
+
},
|
|
32
|
+
resolver(fn) {
|
|
33
|
+
options.resolver = fn;
|
|
34
|
+
return this;
|
|
35
|
+
},
|
|
36
|
+
resolverConfig(config) {
|
|
37
|
+
options.resolverConfig = config;
|
|
38
|
+
return this;
|
|
39
|
+
},
|
|
40
|
+
typeDefs(sdl) {
|
|
41
|
+
options.typeDefs = sdl;
|
|
42
|
+
return this;
|
|
43
|
+
},
|
|
44
|
+
types(typesFn) {
|
|
45
|
+
options.types = typesFn;
|
|
46
|
+
return this;
|
|
47
|
+
},
|
|
48
|
+
plugins(pluginsFn) {
|
|
49
|
+
options.plugins = pluginsFn;
|
|
50
|
+
return this;
|
|
51
|
+
},
|
|
52
|
+
args(a) {
|
|
53
|
+
options.args = a;
|
|
54
|
+
return this;
|
|
55
|
+
},
|
|
56
|
+
outputType(type) {
|
|
57
|
+
options.outputType = type;
|
|
58
|
+
return this;
|
|
59
|
+
},
|
|
60
|
+
build() {
|
|
61
|
+
if (!options.fieldName) {
|
|
62
|
+
throw new Error('Field name must be provided via fieldName()');
|
|
63
|
+
}
|
|
64
|
+
if (!options.outputType) {
|
|
65
|
+
throw new Error(`Output type must be provided for field "${options.fieldName}" via outputType()`);
|
|
66
|
+
}
|
|
67
|
+
const nexusExtension = (0, nexus_1.extendType)({
|
|
68
|
+
type: options.rootType,
|
|
69
|
+
definition(t) {
|
|
70
|
+
// Build Nexus arguments if provided
|
|
71
|
+
let nexusArgs = {};
|
|
72
|
+
if (options.args) {
|
|
73
|
+
for (const [argName, argType] of Object.entries(options.args)) {
|
|
74
|
+
if (typeof argType !== 'string') {
|
|
75
|
+
nexusArgs[argName] = argType;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const isNonNull = argType.endsWith('!');
|
|
79
|
+
const baseType = isNonNull ? argType.slice(0, -1) : argType;
|
|
80
|
+
nexusArgs[argName] = isNonNull
|
|
81
|
+
? (0, nexus_1.nonNull)((0, nexus_1.arg)({ type: baseType }))
|
|
82
|
+
: (0, nexus_1.arg)({ type: baseType });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
t.field(options.fieldName, {
|
|
86
|
+
type: options.outputType,
|
|
87
|
+
args: nexusArgs,
|
|
88
|
+
resolve: options.resolver
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
// Merge the auto-generated Nexus extension with any additional Nexus types
|
|
93
|
+
const autoTypes = [nexusExtension, ...(options.types ? options.types() : [])];
|
|
94
|
+
return (0, graphql_extension_1.createGraphQLExtension)((strapi) => ({
|
|
95
|
+
// Provided typeDefs are optional; Nexus types take precedence.
|
|
96
|
+
typeDefs: () => options.typeDefs || '',
|
|
97
|
+
types: () => autoTypes,
|
|
98
|
+
plugins: () => (options.plugins ? options.plugins() : []),
|
|
99
|
+
resolvers: () => ({
|
|
100
|
+
[options.rootType]: {
|
|
101
|
+
[options.fieldName]: options.resolver
|
|
102
|
+
}
|
|
103
|
+
}),
|
|
104
|
+
resolversConfig: () => ({
|
|
105
|
+
[options.rootType]: {
|
|
106
|
+
[options.fieldName]: options.resolverConfig || {}
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
exports.createGraphQLFieldBuilder = createGraphQLFieldBuilder;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { GraphQLExtension, ResolverConfigOption, ResolverFunction, Strapi } from '../types';
|
|
2
|
+
type ResolversObject = {
|
|
3
|
+
Query?: Record<string, ResolverFunction>;
|
|
4
|
+
Mutation?: Record<string, ResolverFunction>;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Builder interface for configuring a GraphQLExtension.
|
|
8
|
+
*/
|
|
9
|
+
interface GraphQLExtensionBuilder {
|
|
10
|
+
init(fn: () => void): GraphQLExtensionBuilder;
|
|
11
|
+
typeDefs(sdl: string | (() => string)): GraphQLExtensionBuilder;
|
|
12
|
+
types(typesFn: (() => any[]) | any[]): GraphQLExtensionBuilder;
|
|
13
|
+
plugins(pluginsFn: (() => any[]) | any[]): GraphQLExtensionBuilder;
|
|
14
|
+
resolvers(resolversObj: (() => ResolversObject) | ResolversObject): GraphQLExtensionBuilder;
|
|
15
|
+
resolversConfig(config: (() => Record<string, ResolverConfigOption>) | Record<string, ResolverConfigOption>): GraphQLExtensionBuilder;
|
|
16
|
+
build(): GraphQLExtension;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Overloaded createGraphQLExtension:
|
|
20
|
+
* - When called with no arguments, returns a new builder.
|
|
21
|
+
* - When called with a factory function returns a GraphQLExtension.
|
|
22
|
+
*/
|
|
23
|
+
export declare function createGraphQLExtension(): GraphQLExtensionBuilder;
|
|
24
|
+
export declare function createGraphQLExtension(extension: ((strapi: Strapi) => GraphQLExtension)): GraphQLExtension;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createGraphQLExtension = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Internal function that creates a new builder instance.
|
|
6
|
+
*/
|
|
7
|
+
function graphQLExtensionBuilder() {
|
|
8
|
+
// Options to store configuration.
|
|
9
|
+
const options = {};
|
|
10
|
+
return {
|
|
11
|
+
init(fn) {
|
|
12
|
+
options.init = fn;
|
|
13
|
+
return this;
|
|
14
|
+
},
|
|
15
|
+
typeDefs(sdl) {
|
|
16
|
+
options.typeDefs = typeof sdl === 'string' ? () => sdl : sdl;
|
|
17
|
+
return this;
|
|
18
|
+
},
|
|
19
|
+
types(typesFn) {
|
|
20
|
+
options.types = typeof typesFn === 'function' ? typesFn : () => typesFn;
|
|
21
|
+
return this;
|
|
22
|
+
},
|
|
23
|
+
plugins(pluginsFn) {
|
|
24
|
+
options.plugins = typeof pluginsFn === 'function' ? pluginsFn : () => pluginsFn;
|
|
25
|
+
return this;
|
|
26
|
+
},
|
|
27
|
+
resolvers(resolversObj) {
|
|
28
|
+
options.resolvers = typeof resolversObj === 'function' ? resolversObj : () => resolversObj;
|
|
29
|
+
return this;
|
|
30
|
+
},
|
|
31
|
+
resolversConfig(configObj) {
|
|
32
|
+
options.resolversConfig = typeof configObj === 'function' ? configObj : () => configObj;
|
|
33
|
+
return this;
|
|
34
|
+
},
|
|
35
|
+
build() {
|
|
36
|
+
// Create the extension using the options collected.
|
|
37
|
+
return {
|
|
38
|
+
init: options.init,
|
|
39
|
+
typeDefs: options.typeDefs,
|
|
40
|
+
types: options.types,
|
|
41
|
+
plugins: options.plugins,
|
|
42
|
+
resolvers: options.resolvers,
|
|
43
|
+
resolversConfig: options.resolversConfig,
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function createGraphQLExtension(extension) {
|
|
49
|
+
if (!extension) {
|
|
50
|
+
// No argument passed: return a new builder.
|
|
51
|
+
return graphQLExtensionBuilder();
|
|
52
|
+
}
|
|
53
|
+
return extension(strapi);
|
|
54
|
+
}
|
|
55
|
+
exports.createGraphQLExtension = createGraphQLExtension;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export * from './types';
|
|
2
2
|
export * from './single-type';
|
|
3
3
|
export * from './collection-type';
|
|
4
|
+
export * from './field-builder';
|
|
5
|
+
export * from './graphql-extension';
|
|
4
6
|
export * from './middleware';
|
|
5
7
|
export * from './misc';
|
|
6
8
|
export * from './override';
|
|
9
|
+
export * from './shadow-crud';
|
|
@@ -17,6 +17,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./types"), exports);
|
|
18
18
|
__exportStar(require("./single-type"), exports);
|
|
19
19
|
__exportStar(require("./collection-type"), exports);
|
|
20
|
+
__exportStar(require("./field-builder"), exports);
|
|
21
|
+
__exportStar(require("./graphql-extension"), exports);
|
|
20
22
|
__exportStar(require("./middleware"), exports);
|
|
21
23
|
__exportStar(require("./misc"), exports);
|
|
22
24
|
__exportStar(require("./override"), exports);
|
|
25
|
+
__exportStar(require("./shadow-crud"), exports);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type Action = 'create' | 'update' | 'delete' | 'findOne' | 'find';
|
|
2
|
+
interface FieldOperations<T> {
|
|
3
|
+
disable(): this;
|
|
4
|
+
disableInput(): this;
|
|
5
|
+
disableOutput(): this;
|
|
6
|
+
disableFilters(): this;
|
|
7
|
+
isEnabled(): boolean;
|
|
8
|
+
isDisabled(): boolean;
|
|
9
|
+
hasInputEnabled(): boolean;
|
|
10
|
+
hasOutputEnabled(): boolean;
|
|
11
|
+
hasFiltersEnabled(): boolean;
|
|
12
|
+
}
|
|
13
|
+
interface ShadowCRUD<T> {
|
|
14
|
+
disable(): this;
|
|
15
|
+
disableActions(actions: Action[]): this;
|
|
16
|
+
disableAction(action: Action): this;
|
|
17
|
+
disableQueries(): this;
|
|
18
|
+
disableMutations(): this;
|
|
19
|
+
field<K extends keyof T>(name: K): FieldOperations<T[K]>;
|
|
20
|
+
isEnabled(): boolean;
|
|
21
|
+
isDisabled(): boolean;
|
|
22
|
+
areQueriesEnabled(): boolean;
|
|
23
|
+
areQueriesDisabled(): boolean;
|
|
24
|
+
areMutationsEnabled(): boolean;
|
|
25
|
+
areMutationsDisabled(): boolean;
|
|
26
|
+
isActionEnabled(action: Action): boolean;
|
|
27
|
+
isActionDisabled(action: Action): boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare const shadowCRUD: <Type extends unknown = null>(contentTypeUID: string) => ShadowCRUD<Type>;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.shadowCRUD = void 0;
|
|
4
|
+
const shadowCRUD = (contentTypeUID) => {
|
|
5
|
+
const extensionService = strapi.plugin('graphql').service('extension');
|
|
6
|
+
return extensionService.shadowCRUD(contentTypeUID);
|
|
7
|
+
};
|
|
8
|
+
exports.shadowCRUD = shadowCRUD;
|