buro26-strapi-graphql 0.2.0 → 0.3.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/README.md +53 -8
- package/dist/server/utils/field-builder/builder.js +67 -14
- package/dist/server/utils/field-builder/types.d.ts +20 -10
- package/dist/server/utils/loaders.d.ts +29 -13
- package/dist/server/utils/loaders.js +74 -18
- package/dist/server/utils/registry/global-registry.d.ts +13 -2
- package/dist/server/utils/registry/global-registry.js +13 -2
- package/dist/server/utils/strapi-compat.d.ts +8 -3
- package/dist/server/utils/strapi-compat.js +16 -7
- package/dist/tsconfig.server.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -59,13 +59,16 @@ const resetTypeNameCache = () => {
|
|
|
59
59
|
};
|
|
60
60
|
exports.resetTypeNameCache = resetTypeNameCache;
|
|
61
61
|
/**
|
|
62
|
-
* Describes the GraphQL field(s) Strapi itself generates for a
|
|
62
|
+
* Describes the GraphQL field(s) Strapi itself generates for a relation or media attribute, so we can
|
|
63
63
|
* (re)define them with exactly the same type, arguments, resolver and permission scope.
|
|
64
64
|
*
|
|
65
65
|
* - v4: to-one → `XEntityResponse`, to-many → `XRelationResponseCollection` (with filters/pagination args).
|
|
66
66
|
* - v5: to-one → `X` (unwrapped), to-many → `[X]!` (unwrapped `nodes`) **and** `<field>_connection`
|
|
67
67
|
* returning `XRelationResponseCollection`.
|
|
68
68
|
*
|
|
69
|
+
* Media (`type: 'media'`) resolves against `plugin::upload.file`; Strapi generates the same fields as
|
|
70
|
+
* for a relation, with `multiple` deciding the to-one/to-many shape.
|
|
71
|
+
*
|
|
69
72
|
* All variants use Strapi's own `buildAssociationResolver`, so query validation, output sanitizing and
|
|
70
73
|
* draft/publish handling stay identical to the generated field.
|
|
71
74
|
*
|
|
@@ -73,20 +76,22 @@ exports.resetTypeNameCache = resetTypeNameCache;
|
|
|
73
76
|
*
|
|
74
77
|
* @param resolveOverride - Replaces Strapi's association resolver. It must return Strapi's response
|
|
75
78
|
* wrapper (`{ value }` / `{ nodes }`); v5 unwrapping is applied on top.
|
|
76
|
-
* @throws Error when the content type is unknown or the attribute is not a
|
|
79
|
+
* @throws Error when the content type is unknown or the attribute is not a relation or media attribute.
|
|
77
80
|
*/
|
|
78
81
|
const relationFieldSpecs = (contentTypeUID, attributeName, resolveOverride) => {
|
|
79
82
|
var _a;
|
|
80
83
|
const contentType = getModel(contentTypeUID);
|
|
81
84
|
const attribute = (_a = contentType.attributes) === null || _a === void 0 ? void 0 : _a[attributeName];
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
const isMedia = (attribute === null || attribute === void 0 ? void 0 : attribute.type) === 'media';
|
|
86
|
+
if (!attribute || (!isMedia && (attribute.type !== 'relation' || !attribute.target))) {
|
|
87
|
+
throw new Error(`[buro26-strapi-graphql] "${contentTypeUID}.${attributeName}" is not a relation or media attribute`);
|
|
84
88
|
}
|
|
85
89
|
const { naming } = getGraphQLService('utils');
|
|
86
90
|
const { getContentTypeArgs } = getGraphQLService('builders').utils;
|
|
87
91
|
const { buildAssociationResolver } = getGraphQLService('builders').get('content-api');
|
|
88
|
-
const
|
|
89
|
-
const
|
|
92
|
+
const targetUID = isMedia ? 'plugin::upload.file' : attribute.target;
|
|
93
|
+
const targetContentType = getModel(targetUID);
|
|
94
|
+
const isToMany = isMedia ? Boolean(attribute.multiple) : String(attribute.relation).endsWith('Many');
|
|
90
95
|
const parentTypeName = naming.getTypeName(contentType);
|
|
91
96
|
const associationResolver = resolveOverride !== null && resolveOverride !== void 0 ? resolveOverride : buildAssociationResolver({ contentTypeUID, attributeName, strapi });
|
|
92
97
|
if (!(0, exports.isStrapiV5)()) {
|
|
@@ -145,11 +150,15 @@ exports.relationFieldSpecs = relationFieldSpecs;
|
|
|
145
150
|
* exactly like the generated relation fields do. Pass it to an extension's `resolversConfig` when you
|
|
146
151
|
* define relation fields yourself.
|
|
147
152
|
*
|
|
148
|
-
*
|
|
153
|
+
* Media fields get no scope, because Strapi does not attach one to the media fields it generates.
|
|
154
|
+
*
|
|
155
|
+
* @returns A map of `Type.field` paths to `{ auth: { scope } }`, or `{}` for media.
|
|
149
156
|
*/
|
|
150
157
|
const relationResolversConfig = (contentTypeUID, attributeName) => {
|
|
151
158
|
var _a;
|
|
152
159
|
const attribute = (_a = getModel(contentTypeUID).attributes) === null || _a === void 0 ? void 0 : _a[attributeName];
|
|
160
|
+
if ((attribute === null || attribute === void 0 ? void 0 : attribute.type) === 'media')
|
|
161
|
+
return {};
|
|
153
162
|
const scope = [`${attribute.target}.find`];
|
|
154
163
|
return Object.fromEntries((0, exports.relationFieldSpecs)(contentTypeUID, attributeName).flatMap((spec) => spec.resolverConfigPaths.map((path) => [path, { auth: { scope } }])));
|
|
155
164
|
};
|