@kyro-cms/core 0.9.4 → 0.9.6
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/dist/api-handler-graphql.cjs +10 -10
- package/dist/api-handler-graphql.js +6 -6
- package/dist/api-handler-trpc.cjs +8 -8
- package/dist/api-handler-trpc.js +6 -6
- package/dist/api-handler.cjs +9 -9
- package/dist/api-handler.js +6 -6
- package/dist/{chunk-YFAVQQTU.js → chunk-AX2TZRQJ.js} +3 -3
- package/dist/{chunk-YFAVQQTU.js.map → chunk-AX2TZRQJ.js.map} +1 -1
- package/dist/{chunk-5H3MWQJS.js → chunk-CMXVTUYV.js} +12 -12
- package/dist/chunk-CMXVTUYV.js.map +1 -0
- package/dist/{chunk-E2763JUP.cjs → chunk-DRVOUQMT.cjs} +27 -27
- package/dist/chunk-DRVOUQMT.cjs.map +1 -0
- package/dist/{chunk-4M7X5HAB.cjs → chunk-FKKQUMXR.cjs} +109 -3
- package/dist/chunk-FKKQUMXR.cjs.map +1 -0
- package/dist/{chunk-PV2I2KMI.cjs → chunk-HVCUIII2.cjs} +21 -75
- package/dist/chunk-HVCUIII2.cjs.map +1 -0
- package/dist/{chunk-CJONKRHJ.js → chunk-NZEUU7QB.js} +108 -3
- package/dist/chunk-NZEUU7QB.js.map +1 -0
- package/dist/{chunk-NWUEVLQT.cjs → chunk-OZ3CCTTA.cjs} +5 -5
- package/dist/{chunk-NWUEVLQT.cjs.map → chunk-OZ3CCTTA.cjs.map} +1 -1
- package/dist/chunk-PONTBXR5.js +842 -0
- package/dist/chunk-PONTBXR5.js.map +1 -0
- package/dist/{chunk-CNKT4PME.cjs → chunk-QVJNSAQL.cjs} +71 -149
- package/dist/chunk-QVJNSAQL.cjs.map +1 -0
- package/dist/{chunk-OHC6UHFY.js → chunk-QX3WNQ7V.js} +18 -72
- package/dist/chunk-QX3WNQ7V.js.map +1 -0
- package/dist/chunk-RRKCIAPU.cjs +848 -0
- package/dist/chunk-RRKCIAPU.cjs.map +1 -0
- package/dist/{chunk-NI5D3F7H.cjs → chunk-U3VVLYXG.cjs} +55 -7
- package/dist/chunk-U3VVLYXG.cjs.map +1 -0
- package/dist/{chunk-IPTZM3VE.js → chunk-VLK5SJRI.js} +56 -134
- package/dist/chunk-VLK5SJRI.js.map +1 -0
- package/dist/{chunk-NFKRKH3P.js → chunk-X4BPPD6K.js} +52 -4
- package/dist/chunk-X4BPPD6K.js.map +1 -0
- package/dist/graphql/index.cjs +8 -4
- package/dist/graphql/index.d.cts +4 -1
- package/dist/graphql/index.d.ts +4 -1
- package/dist/graphql/index.js +2 -2
- package/dist/index.cjs +59 -59
- package/dist/index.js +7 -7
- package/dist/integration.cjs +2 -2
- package/dist/integration.js +1 -1
- package/dist/rest/index.cjs +4 -4
- package/dist/rest/index.js +2 -2
- package/dist/trpc/index.cjs +11 -11
- package/dist/trpc/index.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-3HR772HI.cjs +0 -555
- package/dist/chunk-3HR772HI.cjs.map +0 -1
- package/dist/chunk-4M7X5HAB.cjs.map +0 -1
- package/dist/chunk-5H3MWQJS.js.map +0 -1
- package/dist/chunk-CJONKRHJ.js.map +0 -1
- package/dist/chunk-CNKT4PME.cjs.map +0 -1
- package/dist/chunk-E2763JUP.cjs.map +0 -1
- package/dist/chunk-IPTZM3VE.js.map +0 -1
- package/dist/chunk-L5UKKZQN.js +0 -552
- package/dist/chunk-L5UKKZQN.js.map +0 -1
- package/dist/chunk-NFKRKH3P.js.map +0 -1
- package/dist/chunk-NI5D3F7H.cjs.map +0 -1
- package/dist/chunk-OHC6UHFY.js.map +0 -1
- package/dist/chunk-PV2I2KMI.cjs.map +0 -1
package/dist/trpc/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { createContext, createCountProcedure, createCreateProcedure, createDeleteProcedure, createDynamicRouter, createFindByIDProcedure, createFindProcedure, createKyroServer, createUpdateProcedure } from '../chunk-
|
|
1
|
+
export { createContext, createCountProcedure, createCreateProcedure, createDeleteProcedure, createDynamicRouter, createFindByIDProcedure, createFindProcedure, createKyroServer, createUpdateProcedure } from '../chunk-QX3WNQ7V.js';
|
|
2
2
|
import '../chunk-3UK5XBVJ.js';
|
|
3
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-NZEUU7QB.js';
|
|
4
4
|
import '../chunk-L4EZKIEX.js';
|
|
5
5
|
import '../chunk-4CV4JOE5.js';
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kyro-cms/core",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.6",
|
|
4
4
|
"description": "Astro-native headless CMS with multi-database adapters, multi-protocol APIs, and multi-vendor support",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22"
|
|
@@ -233,4 +233,4 @@
|
|
|
233
233
|
"use-sync-external-store": "1.5.0"
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
|
-
}
|
|
236
|
+
}
|
package/dist/chunk-3HR772HI.cjs
DELETED
|
@@ -1,555 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunk4M7X5HAB_cjs = require('./chunk-4M7X5HAB.cjs');
|
|
4
|
-
var chunkNKPKR5BW_cjs = require('./chunk-NKPKR5BW.cjs');
|
|
5
|
-
var graphql = require('graphql');
|
|
6
|
-
|
|
7
|
-
async function checkGraphQLAccess(collection, operation, context) {
|
|
8
|
-
const accessRule = collection.access?.[operation];
|
|
9
|
-
if (context.apiKey?.permissions?.length > 0) {
|
|
10
|
-
const resource = collection.slug;
|
|
11
|
-
const action = operation === "read" ? "read" : operation === "create" ? "create" : "update";
|
|
12
|
-
const permission = `${resource}:${action}`;
|
|
13
|
-
if (!chunk4M7X5HAB_cjs.hasApiKeyPermission(context.apiKey.permissions, permission) && !chunk4M7X5HAB_cjs.hasApiKeyPermission(context.apiKey.permissions, `${resource}:admin`)) {
|
|
14
|
-
return { allowed: false };
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
if (context.user) {
|
|
18
|
-
const resource = collection.slug;
|
|
19
|
-
const action = operation === "read" ? "read" : operation === "create" ? "create" : operation === "update" ? "update" : "delete";
|
|
20
|
-
const permission = `${resource}:${action}`;
|
|
21
|
-
const userHasPermission = chunkNKPKR5BW_cjs.hasPermission(
|
|
22
|
-
{ id: context.user.id, email: context.user.email, role: context.user.role },
|
|
23
|
-
permission
|
|
24
|
-
);
|
|
25
|
-
if (!userHasPermission && !chunkNKPKR5BW_cjs.hasPermission(
|
|
26
|
-
{ id: context.user.id, email: context.user.email, role: context.user.role },
|
|
27
|
-
`${resource}:admin`
|
|
28
|
-
)) {
|
|
29
|
-
if (!accessRule) {
|
|
30
|
-
return { allowed: false };
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
if (!accessRule) {
|
|
35
|
-
if (!context.user && !context.apiKey) {
|
|
36
|
-
return { allowed: false };
|
|
37
|
-
}
|
|
38
|
-
return { allowed: true };
|
|
39
|
-
}
|
|
40
|
-
const result = await chunk4M7X5HAB_cjs.evaluateAccess(accessRule, {
|
|
41
|
-
req: context.req,
|
|
42
|
-
user: context.user,
|
|
43
|
-
tenantID: context.tenantID
|
|
44
|
-
});
|
|
45
|
-
if (typeof result === "boolean") {
|
|
46
|
-
return { allowed: result };
|
|
47
|
-
}
|
|
48
|
-
return { allowed: true, extraWhere: result };
|
|
49
|
-
}
|
|
50
|
-
async function checkGlobalAccess(global, operation, context) {
|
|
51
|
-
const accessRule = global.access?.[operation];
|
|
52
|
-
if (!accessRule) {
|
|
53
|
-
if (!context.user) {
|
|
54
|
-
return { allowed: false };
|
|
55
|
-
}
|
|
56
|
-
const userRole = context.user.role;
|
|
57
|
-
if (userRole === "super_admin" || userRole === "admin") {
|
|
58
|
-
return { allowed: true };
|
|
59
|
-
}
|
|
60
|
-
return { allowed: false };
|
|
61
|
-
}
|
|
62
|
-
const result = await chunk4M7X5HAB_cjs.evaluateAccess(accessRule, {
|
|
63
|
-
req: context.req,
|
|
64
|
-
user: context.user,
|
|
65
|
-
tenantID: context.tenantID
|
|
66
|
-
});
|
|
67
|
-
if (typeof result === "boolean") {
|
|
68
|
-
return { allowed: result };
|
|
69
|
-
}
|
|
70
|
-
return { allowed: true };
|
|
71
|
-
}
|
|
72
|
-
function fieldToGraphQLType(field, registry, collectionTypes, isInputType = false) {
|
|
73
|
-
switch (field.type) {
|
|
74
|
-
case "text":
|
|
75
|
-
case "email":
|
|
76
|
-
case "password":
|
|
77
|
-
case "textarea":
|
|
78
|
-
case "color":
|
|
79
|
-
case "code":
|
|
80
|
-
case "markdown":
|
|
81
|
-
case "date":
|
|
82
|
-
case "select":
|
|
83
|
-
case "radio":
|
|
84
|
-
case "upload":
|
|
85
|
-
return graphql.GraphQLString;
|
|
86
|
-
case "number":
|
|
87
|
-
return field.integer ? graphql.GraphQLInt : graphql.GraphQLFloat;
|
|
88
|
-
case "checkbox":
|
|
89
|
-
return graphql.GraphQLBoolean;
|
|
90
|
-
case "json":
|
|
91
|
-
case "richtext":
|
|
92
|
-
return graphql.GraphQLString;
|
|
93
|
-
// JSON as string
|
|
94
|
-
case "relationship":
|
|
95
|
-
if (typeof field.relationTo === "string") {
|
|
96
|
-
if (isInputType) {
|
|
97
|
-
return graphql.GraphQLString;
|
|
98
|
-
}
|
|
99
|
-
if (collectionTypes?.[field.relationTo]) {
|
|
100
|
-
return collectionTypes[field.relationTo];
|
|
101
|
-
}
|
|
102
|
-
const relatedCollection = registry.getCollection(field.relationTo);
|
|
103
|
-
if (relatedCollection) {
|
|
104
|
-
return new graphql.GraphQLObjectType({
|
|
105
|
-
name: `${field.relationTo}_ref`,
|
|
106
|
-
fields: () => ({
|
|
107
|
-
id: { type: graphql.GraphQLString },
|
|
108
|
-
...buildFieldsFromCollection(relatedCollection, registry, collectionTypes)
|
|
109
|
-
})
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return graphql.GraphQLString;
|
|
114
|
-
case "array":
|
|
115
|
-
return new graphql.GraphQLList(graphql.GraphQLString);
|
|
116
|
-
// Simplified
|
|
117
|
-
case "group":
|
|
118
|
-
return graphql.GraphQLString;
|
|
119
|
-
// Simplified - JSON string
|
|
120
|
-
case "blocks":
|
|
121
|
-
return new graphql.GraphQLList(graphql.GraphQLString);
|
|
122
|
-
// Simplified
|
|
123
|
-
case "row":
|
|
124
|
-
case "collapsible":
|
|
125
|
-
case "tabs":
|
|
126
|
-
return graphql.GraphQLString;
|
|
127
|
-
default:
|
|
128
|
-
return graphql.GraphQLString;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
function buildFieldsFromCollection(config, registry, collectionTypes) {
|
|
132
|
-
const fields = {};
|
|
133
|
-
for (const field of config.fields) {
|
|
134
|
-
if (field.name && field.admin?.hidden !== true) {
|
|
135
|
-
fields[field.name] = {
|
|
136
|
-
type: field.required ? new graphql.GraphQLNonNull(fieldToGraphQLType(field, registry, collectionTypes)) : fieldToGraphQLType(field, registry, collectionTypes),
|
|
137
|
-
description: field.admin?.description || field.label
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return fields;
|
|
142
|
-
}
|
|
143
|
-
function buildGraphQLSchema(options) {
|
|
144
|
-
const { registry, db, user, req, tenantID, apiKey, settings } = options;
|
|
145
|
-
const apiAccess = settings?.access?.apiAccess;
|
|
146
|
-
if (apiAccess?.graphqlEnabled === false) {
|
|
147
|
-
throw new Error("GraphQL API is disabled");
|
|
148
|
-
}
|
|
149
|
-
const collections = registry.getCollections();
|
|
150
|
-
const globals = registry.getGlobals();
|
|
151
|
-
const collectionTypes = {};
|
|
152
|
-
const collectionInputTypes = {};
|
|
153
|
-
for (const collection of collections) {
|
|
154
|
-
collectionTypes[collection.slug] = new graphql.GraphQLObjectType({
|
|
155
|
-
name: `${collection.slug.replace(/-/g, "_")}_type`,
|
|
156
|
-
fields: () => ({
|
|
157
|
-
id: { type: graphql.GraphQLString },
|
|
158
|
-
...buildFieldsFromCollection(collection, registry, collectionTypes),
|
|
159
|
-
...collection.timestamps ? {
|
|
160
|
-
createdAt: { type: graphql.GraphQLString },
|
|
161
|
-
updatedAt: { type: graphql.GraphQLString }
|
|
162
|
-
} : {},
|
|
163
|
-
...collection.tenantScoped ? {
|
|
164
|
-
tenantID: { type: graphql.GraphQLString }
|
|
165
|
-
} : {}
|
|
166
|
-
})
|
|
167
|
-
});
|
|
168
|
-
const inputFields = {};
|
|
169
|
-
for (const field of collection.fields) {
|
|
170
|
-
if (field.name && field.name !== "id") {
|
|
171
|
-
inputFields[field.name] = {
|
|
172
|
-
type: fieldToGraphQLType(field, registry, collectionTypes, true)
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
collectionInputTypes[collection.slug] = new graphql.GraphQLInputObjectType({
|
|
177
|
-
name: `${collection.slug.replace(/-/g, "_")}_input`,
|
|
178
|
-
fields: () => inputFields
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
const globalTypes = {};
|
|
182
|
-
const globalInputTypes = {};
|
|
183
|
-
for (const global of globals) {
|
|
184
|
-
globalTypes[global.slug] = new graphql.GraphQLObjectType({
|
|
185
|
-
name: `${global.slug.replace(/-/g, "_")}_global_type`,
|
|
186
|
-
fields: () => ({
|
|
187
|
-
id: { type: graphql.GraphQLString },
|
|
188
|
-
...buildFieldsFromCollection(
|
|
189
|
-
{ slug: global.slug, fields: global.fields },
|
|
190
|
-
registry,
|
|
191
|
-
collectionTypes
|
|
192
|
-
)
|
|
193
|
-
})
|
|
194
|
-
});
|
|
195
|
-
globalInputTypes[global.slug] = new graphql.GraphQLInputObjectType({
|
|
196
|
-
name: `${global.slug.replace(/-/g, "_")}_global_input`,
|
|
197
|
-
fields: () => {
|
|
198
|
-
const inputFields = {};
|
|
199
|
-
for (const field of global.fields) {
|
|
200
|
-
if (field.name && field.name !== "id") {
|
|
201
|
-
inputFields[field.name] = {
|
|
202
|
-
type: fieldToGraphQLType(field, registry, collectionTypes, true)
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return inputFields;
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
const queryFields = {};
|
|
211
|
-
for (const collection of collections) {
|
|
212
|
-
const type = collectionTypes[collection.slug];
|
|
213
|
-
if (!type) continue;
|
|
214
|
-
queryFields[`${collection.slug.replace(/-/g, "_")}Find`] = {
|
|
215
|
-
type: new graphql.GraphQLObjectType({
|
|
216
|
-
name: `${collection.slug.replace(/-/g, "_")}_find_result`,
|
|
217
|
-
fields: {
|
|
218
|
-
docs: { type: new graphql.GraphQLList(type) },
|
|
219
|
-
totalDocs: { type: graphql.GraphQLInt },
|
|
220
|
-
page: { type: graphql.GraphQLInt },
|
|
221
|
-
totalPages: { type: graphql.GraphQLInt },
|
|
222
|
-
hasNextPage: { type: graphql.GraphQLBoolean },
|
|
223
|
-
hasPrevPage: { type: graphql.GraphQLBoolean }
|
|
224
|
-
}
|
|
225
|
-
}),
|
|
226
|
-
args: {
|
|
227
|
-
where: { type: graphql.GraphQLString },
|
|
228
|
-
sort: { type: graphql.GraphQLString },
|
|
229
|
-
limit: { type: graphql.GraphQLInt },
|
|
230
|
-
page: { type: graphql.GraphQLInt },
|
|
231
|
-
draft: { type: graphql.GraphQLBoolean }
|
|
232
|
-
},
|
|
233
|
-
resolve: async (_, args, context) => {
|
|
234
|
-
const access = await checkGraphQLAccess(collection, "read", {
|
|
235
|
-
user,
|
|
236
|
-
req,
|
|
237
|
-
tenantID,
|
|
238
|
-
apiKey
|
|
239
|
-
});
|
|
240
|
-
if (!access.allowed) {
|
|
241
|
-
throw new Error("Access denied");
|
|
242
|
-
}
|
|
243
|
-
if (tenantID) {
|
|
244
|
-
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
245
|
-
}
|
|
246
|
-
let where = {};
|
|
247
|
-
if (args.where) {
|
|
248
|
-
try {
|
|
249
|
-
where = JSON.parse(args.where);
|
|
250
|
-
} catch {
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
if (access.extraWhere) {
|
|
254
|
-
where = { ...where, ...access.extraWhere };
|
|
255
|
-
}
|
|
256
|
-
const isDraft = args.draft ?? !!user;
|
|
257
|
-
return db.find({
|
|
258
|
-
collection: collection.slug,
|
|
259
|
-
where,
|
|
260
|
-
sort: args.sort,
|
|
261
|
-
limit: args.limit || 10,
|
|
262
|
-
page: args.page || 1,
|
|
263
|
-
tenantID,
|
|
264
|
-
draft: isDraft
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
|
-
queryFields[`${collection.slug.replace(/-/g, "_")}FindByID`] = {
|
|
269
|
-
type,
|
|
270
|
-
args: {
|
|
271
|
-
id: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) },
|
|
272
|
-
draft: { type: graphql.GraphQLBoolean }
|
|
273
|
-
},
|
|
274
|
-
resolve: async (_, args, context) => {
|
|
275
|
-
const access = await checkGraphQLAccess(collection, "read", {
|
|
276
|
-
user,
|
|
277
|
-
req,
|
|
278
|
-
tenantID,
|
|
279
|
-
apiKey
|
|
280
|
-
});
|
|
281
|
-
if (!access.allowed) {
|
|
282
|
-
throw new Error("Access denied");
|
|
283
|
-
}
|
|
284
|
-
if (tenantID) {
|
|
285
|
-
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
286
|
-
}
|
|
287
|
-
const isDraft = args.draft ?? !!user;
|
|
288
|
-
const doc = await db.findByID({
|
|
289
|
-
collection: collection.slug,
|
|
290
|
-
id: args.id,
|
|
291
|
-
tenantID,
|
|
292
|
-
draft: isDraft
|
|
293
|
-
});
|
|
294
|
-
return doc;
|
|
295
|
-
}
|
|
296
|
-
};
|
|
297
|
-
queryFields[`${collection.slug.replace(/-/g, "_")}Count`] = {
|
|
298
|
-
type: new graphql.GraphQLObjectType({
|
|
299
|
-
name: `${collection.slug.replace(/-/g, "_")}_count`,
|
|
300
|
-
fields: {
|
|
301
|
-
totalDocs: { type: graphql.GraphQLInt }
|
|
302
|
-
}
|
|
303
|
-
}),
|
|
304
|
-
args: {
|
|
305
|
-
where: { type: graphql.GraphQLString }
|
|
306
|
-
},
|
|
307
|
-
resolve: async (_, args, context) => {
|
|
308
|
-
const access = await checkGraphQLAccess(collection, "read", {
|
|
309
|
-
user,
|
|
310
|
-
req,
|
|
311
|
-
tenantID,
|
|
312
|
-
apiKey
|
|
313
|
-
});
|
|
314
|
-
if (!access.allowed) {
|
|
315
|
-
return { totalDocs: 0 };
|
|
316
|
-
}
|
|
317
|
-
let where = {};
|
|
318
|
-
if (args.where) {
|
|
319
|
-
try {
|
|
320
|
-
where = JSON.parse(args.where);
|
|
321
|
-
} catch {
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
const count = await db.count({
|
|
325
|
-
collection: collection.slug,
|
|
326
|
-
where,
|
|
327
|
-
tenantID
|
|
328
|
-
});
|
|
329
|
-
return { totalDocs: count };
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
for (const global of globals) {
|
|
334
|
-
const type = globalTypes[global.slug];
|
|
335
|
-
if (!type) continue;
|
|
336
|
-
queryFields[`${global.slug.replace(/-/g, "_")}Get`] = {
|
|
337
|
-
type,
|
|
338
|
-
resolve: async () => {
|
|
339
|
-
const access = await checkGlobalAccess(global, "read", {
|
|
340
|
-
user,
|
|
341
|
-
req,
|
|
342
|
-
tenantID
|
|
343
|
-
});
|
|
344
|
-
if (!access.allowed) {
|
|
345
|
-
throw new Error("Access denied: cannot read global");
|
|
346
|
-
}
|
|
347
|
-
if (tenantID) {
|
|
348
|
-
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
349
|
-
}
|
|
350
|
-
return db.findOne({
|
|
351
|
-
collection: `_globals_${global.slug}`,
|
|
352
|
-
where: {},
|
|
353
|
-
tenantID
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
const Query = new graphql.GraphQLObjectType({
|
|
359
|
-
name: "Query",
|
|
360
|
-
fields: queryFields
|
|
361
|
-
});
|
|
362
|
-
const mutationFields = {};
|
|
363
|
-
for (const collection of collections) {
|
|
364
|
-
const type = collectionTypes[collection.slug];
|
|
365
|
-
const inputType = collectionInputTypes[collection.slug];
|
|
366
|
-
if (!type || !inputType) continue;
|
|
367
|
-
mutationFields[`${collection.slug.replace(/-/g, "_")}Create`] = {
|
|
368
|
-
type: new graphql.GraphQLObjectType({
|
|
369
|
-
name: `${collection.slug.replace(/-/g, "_")}_create_result`,
|
|
370
|
-
fields: {
|
|
371
|
-
doc: { type },
|
|
372
|
-
message: { type: graphql.GraphQLString }
|
|
373
|
-
}
|
|
374
|
-
}),
|
|
375
|
-
args: {
|
|
376
|
-
data: { type: new graphql.GraphQLNonNull(inputType) }
|
|
377
|
-
},
|
|
378
|
-
resolve: async (_, args, context) => {
|
|
379
|
-
const access = await checkGraphQLAccess(collection, "create", {
|
|
380
|
-
user,
|
|
381
|
-
req,
|
|
382
|
-
tenantID,
|
|
383
|
-
apiKey
|
|
384
|
-
});
|
|
385
|
-
if (!access.allowed) {
|
|
386
|
-
throw new Error("Access denied: cannot create");
|
|
387
|
-
}
|
|
388
|
-
if (tenantID) {
|
|
389
|
-
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
390
|
-
}
|
|
391
|
-
const schema = registry.getCreateZodSchema(collection.slug);
|
|
392
|
-
const validated = schema.parse(args.data);
|
|
393
|
-
const doc = await db.create({
|
|
394
|
-
collection: collection.slug,
|
|
395
|
-
data: validated,
|
|
396
|
-
tenantID
|
|
397
|
-
});
|
|
398
|
-
return { doc, message: "Created successfully" };
|
|
399
|
-
}
|
|
400
|
-
};
|
|
401
|
-
mutationFields[`${collection.slug.replace(/-/g, "_")}Update`] = {
|
|
402
|
-
type: new graphql.GraphQLObjectType({
|
|
403
|
-
name: `${collection.slug.replace(/-/g, "_")}_update_result`,
|
|
404
|
-
fields: {
|
|
405
|
-
doc: { type },
|
|
406
|
-
message: { type: graphql.GraphQLString }
|
|
407
|
-
}
|
|
408
|
-
}),
|
|
409
|
-
args: {
|
|
410
|
-
id: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) },
|
|
411
|
-
data: { type: new graphql.GraphQLNonNull(inputType) },
|
|
412
|
-
baseUpdatedAt: { type: graphql.GraphQLString }
|
|
413
|
-
},
|
|
414
|
-
resolve: async (_, args, context) => {
|
|
415
|
-
const access = await checkGraphQLAccess(collection, "update", {
|
|
416
|
-
user,
|
|
417
|
-
req,
|
|
418
|
-
tenantID,
|
|
419
|
-
apiKey
|
|
420
|
-
});
|
|
421
|
-
if (!access.allowed) {
|
|
422
|
-
throw new Error("Access denied: cannot update");
|
|
423
|
-
}
|
|
424
|
-
if (tenantID) {
|
|
425
|
-
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
426
|
-
}
|
|
427
|
-
if (args.baseUpdatedAt) {
|
|
428
|
-
const originalDoc = await db.findByID({
|
|
429
|
-
collection: collection.slug,
|
|
430
|
-
id: args.id,
|
|
431
|
-
tenantID,
|
|
432
|
-
draft: true
|
|
433
|
-
});
|
|
434
|
-
if (originalDoc && originalDoc.updatedAt && args.baseUpdatedAt !== originalDoc.updatedAt) {
|
|
435
|
-
throw new Error(`Revision conflict: document has changed since ${args.baseUpdatedAt}. Current updatedAt: ${originalDoc.updatedAt}`);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
const schema = registry.getUpdateZodSchema(collection.slug);
|
|
439
|
-
const validated = schema.parse(args.data);
|
|
440
|
-
const doc = await db.update({
|
|
441
|
-
collection: collection.slug,
|
|
442
|
-
id: args.id,
|
|
443
|
-
data: validated,
|
|
444
|
-
tenantID
|
|
445
|
-
});
|
|
446
|
-
return { doc, message: "Updated successfully" };
|
|
447
|
-
}
|
|
448
|
-
};
|
|
449
|
-
mutationFields[`${collection.slug.replace(/-/g, "_")}Delete`] = {
|
|
450
|
-
type: new graphql.GraphQLObjectType({
|
|
451
|
-
name: `${collection.slug.replace(/-/g, "_")}_delete_result`,
|
|
452
|
-
fields: {
|
|
453
|
-
doc: { type },
|
|
454
|
-
message: { type: graphql.GraphQLString }
|
|
455
|
-
}
|
|
456
|
-
}),
|
|
457
|
-
args: {
|
|
458
|
-
id: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) }
|
|
459
|
-
},
|
|
460
|
-
resolve: async (_, args, context) => {
|
|
461
|
-
const access = await checkGraphQLAccess(collection, "delete", {
|
|
462
|
-
user,
|
|
463
|
-
req,
|
|
464
|
-
tenantID,
|
|
465
|
-
apiKey
|
|
466
|
-
});
|
|
467
|
-
if (!access.allowed) {
|
|
468
|
-
throw new Error("Access denied: cannot delete");
|
|
469
|
-
}
|
|
470
|
-
if (tenantID) {
|
|
471
|
-
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
472
|
-
}
|
|
473
|
-
const doc = await db.delete({
|
|
474
|
-
collection: collection.slug,
|
|
475
|
-
id: args.id,
|
|
476
|
-
tenantID
|
|
477
|
-
});
|
|
478
|
-
return { doc, message: "Deleted successfully" };
|
|
479
|
-
}
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
for (const global of globals) {
|
|
483
|
-
const inputType = globalInputTypes[global.slug];
|
|
484
|
-
if (!inputType) continue;
|
|
485
|
-
mutationFields[`${global.slug.replace(/-/g, "_")}Update`] = {
|
|
486
|
-
type: new graphql.GraphQLObjectType({
|
|
487
|
-
name: `${global.slug.replace(/-/g, "_")}_update_result`,
|
|
488
|
-
fields: {
|
|
489
|
-
doc: { type: globalTypes[global.slug] || graphql.GraphQLString },
|
|
490
|
-
message: { type: graphql.GraphQLString }
|
|
491
|
-
}
|
|
492
|
-
}),
|
|
493
|
-
args: {
|
|
494
|
-
data: { type: new graphql.GraphQLNonNull(inputType) }
|
|
495
|
-
},
|
|
496
|
-
resolve: async (_, args, context) => {
|
|
497
|
-
const access = await checkGlobalAccess(global, "update", {
|
|
498
|
-
user,
|
|
499
|
-
req,
|
|
500
|
-
tenantID
|
|
501
|
-
});
|
|
502
|
-
if (!access.allowed) {
|
|
503
|
-
throw new Error("Access denied: cannot update global");
|
|
504
|
-
}
|
|
505
|
-
if (tenantID) {
|
|
506
|
-
db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? "", role: user?.role, isSuperAdmin: user?.role === "super_admin" });
|
|
507
|
-
}
|
|
508
|
-
const doc = await db.findOne({
|
|
509
|
-
collection: `_globals_${global.slug}`,
|
|
510
|
-
where: {},
|
|
511
|
-
tenantID
|
|
512
|
-
});
|
|
513
|
-
let result;
|
|
514
|
-
if (doc) {
|
|
515
|
-
result = await db.update({
|
|
516
|
-
collection: `_globals_${global.slug}`,
|
|
517
|
-
id: doc.id,
|
|
518
|
-
data: args.data,
|
|
519
|
-
tenantID
|
|
520
|
-
});
|
|
521
|
-
} else {
|
|
522
|
-
result = await db.create({
|
|
523
|
-
collection: `_globals_${global.slug}`,
|
|
524
|
-
data: args.data,
|
|
525
|
-
tenantID
|
|
526
|
-
});
|
|
527
|
-
}
|
|
528
|
-
return { doc: result, message: "Updated successfully" };
|
|
529
|
-
}
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
const Mutation = new graphql.GraphQLObjectType({
|
|
533
|
-
name: "Mutation",
|
|
534
|
-
fields: mutationFields
|
|
535
|
-
});
|
|
536
|
-
return new graphql.GraphQLSchema({
|
|
537
|
-
query: Query,
|
|
538
|
-
mutation: Mutation
|
|
539
|
-
});
|
|
540
|
-
}
|
|
541
|
-
function createGraphQLSchema(registry, db, options) {
|
|
542
|
-
return buildGraphQLSchema({
|
|
543
|
-
registry,
|
|
544
|
-
db,
|
|
545
|
-
user: options?.user,
|
|
546
|
-
req: options?.req,
|
|
547
|
-
tenantID: options?.tenantID,
|
|
548
|
-
apiKey: options?.apiKey
|
|
549
|
-
});
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
exports.buildGraphQLSchema = buildGraphQLSchema;
|
|
553
|
-
exports.createGraphQLSchema = createGraphQLSchema;
|
|
554
|
-
//# sourceMappingURL=chunk-3HR772HI.cjs.map
|
|
555
|
-
//# sourceMappingURL=chunk-3HR772HI.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/graphql/schema.ts"],"names":["hasApiKeyPermission","hasPermission","evaluateAccess","GraphQLString","GraphQLInt","GraphQLFloat","GraphQLBoolean","GraphQLObjectType","GraphQLList","GraphQLNonNull","GraphQLInputObjectType","GraphQLSchema"],"mappings":"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","file":"chunk-3HR772HI.cjs","sourcesContent":["import {\n GraphQLSchema,\n GraphQLObjectType,\n GraphQLString,\n GraphQLInt,\n GraphQLBoolean,\n GraphQLFloat,\n GraphQLList,\n GraphQLNonNull,\n GraphQLInputObjectType,\n type GraphQLFieldConfig,\n type GraphQLType,\n} from \"graphql\";\nimport type {\n CollectionConfig,\n GlobalConfig,\n BaseAdapter,\n} from \"../../registry/types.js\";\nimport { Registry } from \"../../registry/index.js\";\nimport type { Field, SelectField } from \"../../fields/types.js\";\nimport { evaluateAccess, type WhereClause } from \"../../access/types.js\";\nimport type { User, Request } from \"../../hooks/types.js\";\nimport type { TenantContext } from \"../../auth/rls/tenant.js\";\nimport { hasApiKeyPermission } from \"../../auth/api-key.js\";\nimport { hasPermission } from \"../../auth/rbac/checker.js\";\n\n// ============================================================================\n// Access Control Helper\n// ============================================================================\n\nasync function checkGraphQLAccess(\n collection: { access?: any; slug: string },\n operation: \"read\" | \"create\" | \"update\" | \"delete\",\n context: { user?: User; req?: Request; tenantID?: string; apiKey?: any },\n): Promise<{ allowed: boolean; extraWhere?: WhereClause }> {\n const accessRule = collection.access?.[operation];\n\n // API key permission check\n if (context.apiKey?.permissions?.length > 0) {\n const resource = collection.slug;\n const action = operation === \"read\" ? \"read\" : operation === \"create\" ? \"create\" : \"update\";\n const permission = `${resource}:${action}`;\n if (\n !hasApiKeyPermission(context.apiKey.permissions, permission) &&\n !hasApiKeyPermission(context.apiKey.permissions, `${resource}:admin`)\n ) {\n return { allowed: false };\n }\n }\n\n // RBAC check for authenticated users\n if (context.user) {\n const resource = collection.slug;\n const action = operation === \"read\" ? \"read\" : operation === \"create\" ? \"create\" : operation === \"update\" ? \"update\" : \"delete\";\n const permission = `${resource}:${action}`;\n const userHasPermission = hasPermission(\n { id: context.user.id, email: context.user.email, role: context.user.role } as any,\n permission,\n );\n if (!userHasPermission && !hasPermission(\n { id: context.user.id, email: context.user.email, role: context.user.role } as any,\n `${resource}:admin`,\n )) {\n if (!accessRule) {\n return { allowed: false };\n }\n }\n }\n\n if (!accessRule) {\n if (!context.user && !context.apiKey) {\n return { allowed: false };\n }\n return { allowed: true };\n }\n\n const result = await evaluateAccess(accessRule, {\n req: context.req!,\n user: context.user,\n tenantID: context.tenantID,\n });\n\n if (typeof result === \"boolean\") {\n return { allowed: result };\n }\n\n return { allowed: true, extraWhere: result };\n}\n\nasync function checkGlobalAccess(\n global: { access?: any },\n operation: \"read\" | \"update\",\n context: { user?: User; req?: Request; tenantID?: string },\n): Promise<{ allowed: boolean }> {\n const accessRule = global.access?.[operation];\n\n if (!accessRule) {\n if (!context.user) {\n return { allowed: false };\n }\n const userRole = context.user.role;\n if (userRole === \"super_admin\" || userRole === \"admin\") {\n return { allowed: true };\n }\n return { allowed: false };\n }\n\n const result = await evaluateAccess(accessRule, {\n req: context.req!,\n user: context.user,\n tenantID: context.tenantID,\n });\n\n if (typeof result === \"boolean\") {\n return { allowed: result };\n }\n\n return { allowed: true };\n}\n\n// ============================================================================\n// Field → GraphQL Type Mapping\n// ============================================================================\n\nfunction fieldToGraphQLType(\n field: Field,\n registry: Registry,\n collectionTypes?: Record<string, GraphQLObjectType>,\n isInputType = false,\n): GraphQLType {\n switch (field.type) {\n case \"text\":\n case \"email\":\n case \"password\":\n case \"textarea\":\n case \"color\":\n case \"code\":\n case \"markdown\":\n case \"date\":\n case \"select\":\n case \"radio\":\n case \"upload\":\n return GraphQLString;\n case \"number\":\n return field.integer ? GraphQLInt : GraphQLFloat;\n case \"checkbox\":\n return GraphQLBoolean;\n case \"json\":\n case \"richtext\":\n return GraphQLString; // JSON as string\n case \"relationship\":\n if (typeof field.relationTo === \"string\") {\n if (isInputType) {\n return GraphQLString;\n }\n if (collectionTypes?.[field.relationTo]) {\n return collectionTypes[field.relationTo];\n }\n const relatedCollection = registry.getCollection(field.relationTo);\n if (relatedCollection) {\n return new GraphQLObjectType({\n name: `${field.relationTo}_ref`,\n fields: () => ({\n id: { type: GraphQLString },\n ...buildFieldsFromCollection(relatedCollection, registry, collectionTypes),\n }),\n });\n }\n }\n return GraphQLString;\n case \"array\":\n return new GraphQLList(GraphQLString); // Simplified\n case \"group\":\n return GraphQLString; // Simplified - JSON string\n case \"blocks\":\n return new GraphQLList(GraphQLString); // Simplified\n case \"row\":\n case \"collapsible\":\n case \"tabs\":\n return GraphQLString;\n default:\n return GraphQLString;\n }\n}\n\nfunction buildFieldsFromCollection(\n config: CollectionConfig,\n registry: Registry,\n collectionTypes?: Record<string, GraphQLObjectType>,\n): Record<string, GraphQLFieldConfig<any, any>> {\n const fields: Record<string, GraphQLFieldConfig<any, any>> = {};\n\n for (const field of config.fields) {\n if (field.name && field.admin?.hidden !== true) {\n fields[field.name] = {\n type: field.required\n ? new GraphQLNonNull(fieldToGraphQLType(field, registry, collectionTypes) as any)\n : (fieldToGraphQLType(field, registry, collectionTypes) as any),\n description: field.admin?.description || field.label,\n };\n }\n }\n\n return fields;\n}\n\n// ============================================================================\n// GraphQL Schema Builder\n// ============================================================================\n\nexport interface GraphQLSchemaOptions {\n registry: Registry;\n db: BaseAdapter;\n user?: User;\n req?: Request;\n tenantID?: string;\n apiKey?: any;\n settings?: Record<string, any>;\n}\n\nexport function buildGraphQLSchema(\n options: GraphQLSchemaOptions,\n): GraphQLSchema {\n const { registry, db, user, req, tenantID, apiKey, settings } = options;\n\n // Check if GraphQL is disabled in settings\n const apiAccess = settings?.access?.apiAccess;\n if (apiAccess?.graphqlEnabled === false) {\n throw new Error(\"GraphQL API is disabled\");\n }\n\n const collections = registry.getCollections();\n const globals = registry.getGlobals();\n\n // Build collection types\n const collectionTypes: Record<string, GraphQLObjectType> = {};\n const collectionInputTypes: Record<string, GraphQLInputObjectType> = {};\n\n for (const collection of collections) {\n // Output type\n collectionTypes[collection.slug] = new GraphQLObjectType({\n name: `${collection.slug.replace(/-/g, \"_\")}_type`,\n fields: () => ({\n id: { type: GraphQLString },\n ...buildFieldsFromCollection(collection, registry, collectionTypes),\n ...(collection.timestamps\n ? {\n createdAt: { type: GraphQLString },\n updatedAt: { type: GraphQLString },\n }\n : {}),\n ...(collection.tenantScoped\n ? {\n tenantID: { type: GraphQLString },\n }\n : {}),\n }),\n });\n\n // Input type for create/update\n const inputFields: Record<string, { type: GraphQLType }> = {};\n for (const field of collection.fields) {\n if (field.name && field.name !== \"id\") {\n inputFields[field.name] = {\n type: fieldToGraphQLType(field, registry, collectionTypes, true) as any,\n };\n }\n }\n\n collectionInputTypes[collection.slug] = new GraphQLInputObjectType({\n name: `${collection.slug.replace(/-/g, \"_\")}_input`,\n fields: () => inputFields as any,\n });\n }\n\n // Build global types and input types\n const globalTypes: Record<string, GraphQLObjectType> = {};\n const globalInputTypes: Record<string, GraphQLInputObjectType> = {};\n\n for (const global of globals) {\n globalTypes[global.slug] = new GraphQLObjectType({\n name: `${global.slug.replace(/-/g, \"_\")}_global_type`,\n fields: () => ({\n id: { type: GraphQLString },\n ...buildFieldsFromCollection(\n { slug: global.slug, fields: global.fields } as CollectionConfig,\n registry,\n collectionTypes,\n ),\n }),\n });\n\n globalInputTypes[global.slug] = new GraphQLInputObjectType({\n name: `${global.slug.replace(/-/g, \"_\")}_global_input`,\n fields: () => {\n const inputFields: Record<string, { type: GraphQLType }> = {};\n for (const field of global.fields) {\n if (field.name && field.name !== \"id\") {\n inputFields[field.name] = {\n type: fieldToGraphQLType(field, registry, collectionTypes, true) as any,\n };\n }\n }\n return inputFields as any;\n },\n });\n }\n\n // Build query type\n const queryFields: Record<string, GraphQLFieldConfig<any, any>> = {};\n\n // List queries for each collection\n for (const collection of collections) {\n const type = collectionTypes[collection.slug];\n if (!type) continue;\n\n // FindMany query\n queryFields[`${collection.slug.replace(/-/g, \"_\")}Find`] = {\n type: new GraphQLObjectType({\n name: `${collection.slug.replace(/-/g, \"_\")}_find_result`,\n fields: {\n docs: { type: new GraphQLList(type) },\n totalDocs: { type: GraphQLInt },\n page: { type: GraphQLInt },\n totalPages: { type: GraphQLInt },\n hasNextPage: { type: GraphQLBoolean },\n hasPrevPage: { type: GraphQLBoolean },\n },\n }),\n args: {\n where: { type: GraphQLString },\n sort: { type: GraphQLString },\n limit: { type: GraphQLInt },\n page: { type: GraphQLInt },\n draft: { type: GraphQLBoolean },\n },\n resolve: async (_: any, args: any, context: any) => {\n const access = await checkGraphQLAccess(collection, \"read\", {\n user,\n req,\n tenantID,\n apiKey,\n });\n if (!access.allowed) {\n throw new Error(\"Access denied\");\n }\n\n if (tenantID) {\n db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? '', role: user?.role, isSuperAdmin: user?.role === 'super_admin' });\n }\n\n let where = {};\n if (args.where) {\n try {\n where = JSON.parse(args.where);\n } catch {}\n }\n\n if (access.extraWhere) {\n where = { ...where, ...access.extraWhere };\n }\n\n const isDraft = args.draft ?? !!user;\n\n return db.find({\n collection: collection.slug,\n where,\n sort: args.sort,\n limit: args.limit || 10,\n page: args.page || 1,\n tenantID,\n draft: isDraft,\n });\n },\n };\n\n // FindByID query\n queryFields[`${collection.slug.replace(/-/g, \"_\")}FindByID`] = {\n type,\n args: {\n id: { type: new GraphQLNonNull(GraphQLString) },\n draft: { type: GraphQLBoolean },\n },\n resolve: async (_: any, args: any, context: any) => {\n const access = await checkGraphQLAccess(collection, \"read\", {\n user,\n req,\n tenantID,\n apiKey,\n });\n if (!access.allowed) {\n throw new Error(\"Access denied\");\n }\n\n if (tenantID) {\n db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? '', role: user?.role, isSuperAdmin: user?.role === 'super_admin' });\n }\n\n const isDraft = args.draft ?? !!user;\n const doc = await db.findByID({\n collection: collection.slug,\n id: args.id,\n tenantID,\n draft: isDraft,\n });\n return doc;\n },\n };\n\n // Count query\n queryFields[`${collection.slug.replace(/-/g, \"_\")}Count`] = {\n type: new GraphQLObjectType({\n name: `${collection.slug.replace(/-/g, \"_\")}_count`,\n fields: {\n totalDocs: { type: GraphQLInt },\n },\n }),\n args: {\n where: { type: GraphQLString },\n },\n resolve: async (_: any, args: any, context: any) => {\n const access = await checkGraphQLAccess(collection, \"read\", {\n user,\n req,\n tenantID,\n apiKey,\n });\n if (!access.allowed) {\n return { totalDocs: 0 };\n }\n let where = {};\n if (args.where) {\n try {\n where = JSON.parse(args.where);\n } catch {}\n }\n const count = await db.count({\n collection: collection.slug,\n where,\n tenantID,\n });\n return { totalDocs: count };\n },\n };\n }\n\n // Global queries\n for (const global of globals) {\n const type = globalTypes[global.slug];\n if (!type) continue;\n\n queryFields[`${global.slug.replace(/-/g, \"_\")}Get`] = {\n type,\n resolve: async () => {\n const access = await checkGlobalAccess(global, \"read\", {\n user,\n req,\n tenantID,\n });\n if (!access.allowed) {\n throw new Error(\"Access denied: cannot read global\");\n }\n if (tenantID) {\n db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? '', role: user?.role, isSuperAdmin: user?.role === 'super_admin' });\n }\n return db.findOne({\n collection: `_globals_${global.slug}`,\n where: {},\n tenantID,\n });\n },\n };\n }\n\n const Query = new GraphQLObjectType({\n name: \"Query\",\n fields: queryFields,\n });\n\n // Build mutation type\n const mutationFields: Record<string, GraphQLFieldConfig<any, any>> = {};\n\n for (const collection of collections) {\n const type = collectionTypes[collection.slug];\n const inputType = collectionInputTypes[collection.slug];\n if (!type || !inputType) continue;\n\n // Create mutation\n mutationFields[`${collection.slug.replace(/-/g, \"_\")}Create`] = {\n type: new GraphQLObjectType({\n name: `${collection.slug.replace(/-/g, \"_\")}_create_result`,\n fields: {\n doc: { type },\n message: { type: GraphQLString },\n },\n }),\n args: {\n data: { type: new GraphQLNonNull(inputType) },\n },\n resolve: async (_: any, args: any, context: any) => {\n const access = await checkGraphQLAccess(collection, \"create\", {\n user,\n req,\n tenantID,\n apiKey,\n });\n if (!access.allowed) {\n throw new Error(\"Access denied: cannot create\");\n }\n if (tenantID) {\n db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? '', role: user?.role, isSuperAdmin: user?.role === 'super_admin' });\n }\n const schema = registry.getCreateZodSchema(collection.slug);\n\n const validated = schema.parse(args.data);\n\n const doc = await db.create({\n collection: collection.slug,\n data: validated,\n tenantID,\n });\n\n return { doc, message: \"Created successfully\" };\n },\n };\n\n // Update mutation\n mutationFields[`${collection.slug.replace(/-/g, \"_\")}Update`] = {\n type: new GraphQLObjectType({\n name: `${collection.slug.replace(/-/g, \"_\")}_update_result`,\n fields: {\n doc: { type },\n message: { type: GraphQLString },\n },\n }),\n args: {\n id: { type: new GraphQLNonNull(GraphQLString) },\n data: { type: new GraphQLNonNull(inputType) },\n baseUpdatedAt: { type: GraphQLString },\n },\n resolve: async (_: any, args: any, context: any) => {\n const access = await checkGraphQLAccess(collection, \"update\", {\n user,\n req,\n tenantID,\n apiKey,\n });\n if (!access.allowed) {\n throw new Error(\"Access denied: cannot update\");\n }\n if (tenantID) {\n db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? '', role: user?.role, isSuperAdmin: user?.role === 'super_admin' });\n }\n\n // Revision conflict detection\n if (args.baseUpdatedAt) {\n const originalDoc = await db.findByID<Record<string, any>>({\n collection: collection.slug,\n id: args.id,\n tenantID,\n draft: true,\n });\n if (originalDoc && originalDoc.updatedAt && args.baseUpdatedAt !== originalDoc.updatedAt) {\n throw new Error(`Revision conflict: document has changed since ${args.baseUpdatedAt}. Current updatedAt: ${originalDoc.updatedAt}`);\n }\n }\n\n const schema = registry.getUpdateZodSchema(collection.slug);\n\n const validated = schema.parse(args.data);\n\n const doc = await db.update({\n collection: collection.slug,\n id: args.id,\n data: validated,\n tenantID,\n });\n\n return { doc, message: \"Updated successfully\" };\n },\n };\n\n // Delete mutation\n mutationFields[`${collection.slug.replace(/-/g, \"_\")}Delete`] = {\n type: new GraphQLObjectType({\n name: `${collection.slug.replace(/-/g, \"_\")}_delete_result`,\n fields: {\n doc: { type },\n message: { type: GraphQLString },\n },\n }),\n args: {\n id: { type: new GraphQLNonNull(GraphQLString) },\n },\n resolve: async (_: any, args: any, context: any) => {\n const access = await checkGraphQLAccess(collection, \"delete\", {\n user,\n req,\n tenantID,\n apiKey,\n });\n if (!access.allowed) {\n throw new Error(\"Access denied: cannot delete\");\n }\n if (tenantID) {\n db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? '', role: user?.role, isSuperAdmin: user?.role === 'super_admin' });\n }\n const doc = await db.delete({\n collection: collection.slug,\n id: args.id,\n tenantID,\n });\n\n return { doc, message: \"Deleted successfully\" };\n },\n };\n }\n\n // Global mutations\n for (const global of globals) {\n const inputType = globalInputTypes[global.slug];\n if (!inputType) continue;\n\n mutationFields[`${global.slug.replace(/-/g, \"_\")}Update`] = {\n type: new GraphQLObjectType({\n name: `${global.slug.replace(/-/g, \"_\")}_update_result`,\n fields: {\n doc: { type: globalTypes[global.slug] || GraphQLString },\n message: { type: GraphQLString },\n },\n }),\n args: {\n data: { type: new GraphQLNonNull(inputType) },\n },\n resolve: async (_: any, args: any, context: any) => {\n const access = await checkGlobalAccess(global, \"update\", {\n user,\n req,\n tenantID,\n });\n if (!access.allowed) {\n throw new Error(\"Access denied: cannot update global\");\n }\n if (tenantID) {\n db.setTenantContext({ tenantId: tenantID, userId: user?.id ?? '', role: user?.role, isSuperAdmin: user?.role === 'super_admin' });\n }\n\n const doc = await db.findOne({\n collection: `_globals_${global.slug}`,\n where: {},\n tenantID,\n });\n\n let result;\n if (doc) {\n result = await db.update({\n collection: `_globals_${global.slug}`,\n id: doc.id,\n data: args.data,\n tenantID,\n });\n } else {\n result = await db.create({\n collection: `_globals_${global.slug}`,\n data: args.data,\n tenantID,\n });\n }\n\n return { doc: result, message: \"Updated successfully\" };\n },\n };\n }\n\n const Mutation = new GraphQLObjectType({\n name: \"Mutation\",\n fields: mutationFields,\n });\n\n return new GraphQLSchema({\n query: Query,\n mutation: Mutation,\n });\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport function createGraphQLSchema(\n registry: Registry,\n db: BaseAdapter,\n options?: {\n user?: User;\n req?: Request;\n tenantID?: string;\n apiKey?: any;\n },\n): GraphQLSchema {\n return buildGraphQLSchema({\n registry,\n db,\n user: options?.user,\n req: options?.req,\n tenantID: options?.tenantID,\n apiKey: options?.apiKey,\n });\n}\n"]}
|