@bobbykim/manguito-cms-api 0.3.3 → 0.4.1
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/{chunk-TK4DNRFF.mjs → chunk-4F2CRXPG.mjs} +76 -12
- package/dist/chunk-4F2CRXPG.mjs.map +1 -0
- package/dist/{chunk-GM55HGWA.mjs → chunk-S4NT6FUM.mjs} +39 -25
- package/dist/chunk-S4NT6FUM.mjs.map +1 -0
- package/dist/graphql/index.d.mts +14 -1
- package/dist/graphql/index.d.ts +14 -1
- package/dist/graphql/index.js +77 -33
- package/dist/graphql/index.js.map +1 -1
- package/dist/graphql/index.mjs +2 -2
- package/dist/handler-7LVYEU5C.mjs +8 -0
- package/dist/index.js +348 -142
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +236 -111
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-GM55HGWA.mjs.map +0 -1
- package/dist/chunk-TK4DNRFF.mjs.map +0 -1
- package/dist/handler-CGHZG3J5.mjs +0 -8
- /package/dist/{handler-CGHZG3J5.mjs.map → handler-7LVYEU5C.mjs.map} +0 -0
package/dist/graphql/index.js
CHANGED
|
@@ -144,14 +144,14 @@ var SortOrderEnum = new import_graphql3.GraphQLEnumType({
|
|
|
144
144
|
values: { ASC: { value: "asc" }, DESC: { value: "desc" } }
|
|
145
145
|
});
|
|
146
146
|
var SORTABLE = [
|
|
147
|
-
{ gql: "title",
|
|
148
|
-
{ gql: "createdAt",
|
|
149
|
-
{ gql: "updatedAt",
|
|
147
|
+
{ gql: "title", value: "title" },
|
|
148
|
+
{ gql: "createdAt", value: "created_at" },
|
|
149
|
+
{ gql: "updatedAt", value: "updated_at" }
|
|
150
150
|
];
|
|
151
151
|
function buildSortFieldEnum(typeName) {
|
|
152
152
|
return new import_graphql3.GraphQLEnumType({
|
|
153
153
|
name: `${typeName}SortField`,
|
|
154
|
-
values: Object.fromEntries(SORTABLE.map((s) => [s.gql, { value: s.
|
|
154
|
+
values: Object.fromEntries(SORTABLE.map((s) => [s.gql, { value: s.value }]))
|
|
155
155
|
});
|
|
156
156
|
}
|
|
157
157
|
function comparableFilterInput(name, scalar) {
|
|
@@ -211,12 +211,13 @@ function buildFilterInputType(type) {
|
|
|
211
211
|
if (Object.keys(fields).length === 0) return null;
|
|
212
212
|
return new import_graphql3.GraphQLInputObjectType({ name: `${graphqlTypeName(type.name)}Filter`, fields });
|
|
213
213
|
}
|
|
214
|
-
function translateFilters(input, nameMap) {
|
|
214
|
+
function translateFilters(input, nameMap, columnFor) {
|
|
215
215
|
const out = {};
|
|
216
216
|
if (!input) return out;
|
|
217
217
|
for (const [gqlField, raw] of Object.entries(input)) {
|
|
218
218
|
if (raw === null || typeof raw !== "object") continue;
|
|
219
|
-
const
|
|
219
|
+
const label = nameMap.toSchema(gqlField);
|
|
220
|
+
const column = columnFor?.(label) ?? label;
|
|
220
221
|
const spec = raw;
|
|
221
222
|
if (spec["eq"] !== void 0) {
|
|
222
223
|
out[column] = spec["eq"];
|
|
@@ -235,35 +236,51 @@ function translateFilters(input, nameMap) {
|
|
|
235
236
|
|
|
236
237
|
// src/graphql/resolvers.ts
|
|
237
238
|
var import_graphql4 = require("graphql");
|
|
239
|
+
|
|
240
|
+
// src/field-keys.ts
|
|
241
|
+
function isColumnBacked(field) {
|
|
242
|
+
const col = field.db_column;
|
|
243
|
+
if (col === null) return false;
|
|
244
|
+
if (col.column_name === "") return false;
|
|
245
|
+
if (col.junction) return false;
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/graphql/resolvers.ts
|
|
238
250
|
function codeError(code, message) {
|
|
239
251
|
return new import_graphql4.GraphQLError(message, { extensions: { code } });
|
|
240
252
|
}
|
|
241
253
|
function isPublished(item) {
|
|
242
254
|
return !!item && item["published"] === true;
|
|
243
255
|
}
|
|
244
|
-
function
|
|
245
|
-
|
|
256
|
+
function resolveFieldValue(field, row) {
|
|
257
|
+
const key = isColumnBacked(field) ? field.db_column.column_name : field.name;
|
|
258
|
+
return row[key] ?? null;
|
|
259
|
+
}
|
|
260
|
+
function scalarFieldResolver(field) {
|
|
261
|
+
return (parent) => resolveFieldValue(field, parent);
|
|
246
262
|
}
|
|
247
263
|
function relationFieldResolver(typeName, schemaFieldName) {
|
|
248
264
|
return (parent, _args, ctx) => ctx.loaders.load(typeName, schemaFieldName, parent);
|
|
249
265
|
}
|
|
250
|
-
function programmaticFieldResolver(typeName, schemaFieldName, mediaFieldNames = []) {
|
|
266
|
+
function programmaticFieldResolver(typeName, schemaFieldName, mediaFieldNames = [], fieldKeys) {
|
|
251
267
|
return async (parent, _args, ctx) => {
|
|
252
268
|
let p = ctx.programmaticMemo.get(parent);
|
|
253
269
|
if (!p) {
|
|
254
|
-
p = resolveProgrammaticRow(typeName, parent, ctx, mediaFieldNames);
|
|
270
|
+
p = resolveProgrammaticRow(typeName, parent, ctx, mediaFieldNames, fieldKeys);
|
|
255
271
|
ctx.programmaticMemo.set(parent, p);
|
|
256
272
|
}
|
|
257
273
|
return (await p)[schemaFieldName];
|
|
258
274
|
};
|
|
259
275
|
}
|
|
260
|
-
async function resolveProgrammaticRow(typeName, parent, ctx, mediaFieldNames) {
|
|
261
|
-
|
|
276
|
+
async function resolveProgrammaticRow(typeName, parent, ctx, mediaFieldNames, fieldKeys) {
|
|
277
|
+
const toLabels = (row) => fieldKeys ? fieldKeys.toLabels(row) : row;
|
|
278
|
+
if (mediaFieldNames.length === 0) return ctx.resolver.resolveItem(typeName, toLabels(parent));
|
|
262
279
|
const enriched = { ...parent };
|
|
263
280
|
await Promise.all(mediaFieldNames.map((name) => ctx.loaders.load(typeName, name, enriched)));
|
|
264
|
-
return ctx.resolver.resolveItem(typeName, enriched);
|
|
281
|
+
return ctx.resolver.resolveItem(typeName, toLabels(enriched));
|
|
265
282
|
}
|
|
266
|
-
function collectionResolver(typeName, nameMap) {
|
|
283
|
+
function collectionResolver(typeName, nameMap, fieldKeys) {
|
|
267
284
|
return async (_root, args, ctx) => {
|
|
268
285
|
const page = args.page ?? 1;
|
|
269
286
|
const perPage = args.perPage ?? 10;
|
|
@@ -274,13 +291,15 @@ function collectionResolver(typeName, nameMap) {
|
|
|
274
291
|
throw codeError("INVALID_PAGINATION", "perPage must be between 1 and 100");
|
|
275
292
|
}
|
|
276
293
|
const repo = ctx.repos[typeName];
|
|
294
|
+
const sortBy = args.sortBy ?? "created_at";
|
|
295
|
+
const sortColumn = fieldKeys?.columnFor(sortBy) ?? sortBy;
|
|
277
296
|
const result = await repo.findMany({
|
|
278
297
|
published_only: true,
|
|
279
298
|
page,
|
|
280
299
|
per_page: perPage,
|
|
281
|
-
sort_by:
|
|
300
|
+
sort_by: sortColumn,
|
|
282
301
|
sort_order: args.sortOrder ?? "asc",
|
|
283
|
-
filters: translateFilters(args.filter, nameMap)
|
|
302
|
+
filters: translateFilters(args.filter, nameMap, fieldKeys?.columnFor)
|
|
284
303
|
});
|
|
285
304
|
return { data: result.data, meta: result.meta };
|
|
286
305
|
};
|
|
@@ -333,7 +352,7 @@ var MEDIA = new import_graphql5.GraphQLObjectType({
|
|
|
333
352
|
duration: { type: import_graphql5.GraphQLInt, resolve: (m) => m.duration }
|
|
334
353
|
}
|
|
335
354
|
});
|
|
336
|
-
function buildGraphQLSchema(registry) {
|
|
355
|
+
function buildGraphQLSchema(registry, fieldKeyMaps = {}) {
|
|
337
356
|
const objectTypes = /* @__PURE__ */ new Map();
|
|
338
357
|
const enumTypes = /* @__PURE__ */ new Map();
|
|
339
358
|
for (const [name, enumType] of Object.entries(registry.enum_types)) {
|
|
@@ -409,11 +428,16 @@ function buildGraphQLSchema(registry) {
|
|
|
409
428
|
const outType = outputTypeForField(field);
|
|
410
429
|
let resolve;
|
|
411
430
|
if (field.field_type === "programmatic") {
|
|
412
|
-
resolve = programmaticFieldResolver(
|
|
431
|
+
resolve = programmaticFieldResolver(
|
|
432
|
+
machineName,
|
|
433
|
+
field.name,
|
|
434
|
+
mediaFieldNames,
|
|
435
|
+
fieldKeyMaps[machineName]
|
|
436
|
+
);
|
|
413
437
|
} else if (field.field_type === "reference" || field.field_type === "paragraph" || field.field_type === "image" || field.field_type === "video" || field.field_type === "file") {
|
|
414
438
|
resolve = relationFieldResolver(machineName, field.name);
|
|
415
439
|
} else {
|
|
416
|
-
resolve = scalarFieldResolver(field
|
|
440
|
+
resolve = scalarFieldResolver(field);
|
|
417
441
|
}
|
|
418
442
|
fields[gqlName] = { type: outType, resolve };
|
|
419
443
|
}
|
|
@@ -469,7 +493,7 @@ function buildGraphQLSchema(registry) {
|
|
|
469
493
|
sortOrder: { type: SortOrderEnum },
|
|
470
494
|
...filterType ? { filter: { type: filterType } } : {}
|
|
471
495
|
},
|
|
472
|
-
resolve: collectionResolver(name, nameMap)
|
|
496
|
+
resolve: collectionResolver(name, nameMap, fieldKeyMaps[name])
|
|
473
497
|
};
|
|
474
498
|
queryFields[singleQueryName(name)] = {
|
|
475
499
|
type: objType,
|
|
@@ -489,7 +513,7 @@ function buildGraphQLSchema(registry) {
|
|
|
489
513
|
queryFields[collectionQueryName(name)] = {
|
|
490
514
|
type: new import_graphql5.GraphQLNonNull(listType),
|
|
491
515
|
args: { page: { type: import_graphql5.GraphQLInt }, perPage: { type: import_graphql5.GraphQLInt } },
|
|
492
|
-
resolve: collectionResolver(name, buildFieldNameMap(tt.fields.map((f) => f.name)))
|
|
516
|
+
resolve: collectionResolver(name, buildFieldNameMap(tt.fields.map((f) => f.name)), fieldKeyMaps[name])
|
|
493
517
|
};
|
|
494
518
|
queryFields[singleQueryName(name)] = {
|
|
495
519
|
type: objType,
|
|
@@ -555,22 +579,34 @@ function groupBy(items, key) {
|
|
|
555
579
|
}
|
|
556
580
|
return result;
|
|
557
581
|
}
|
|
582
|
+
function needsFkResolution(row, fkColumn, fieldName) {
|
|
583
|
+
if (fkColumn !== fieldName && !(fkColumn in row)) return false;
|
|
584
|
+
const current = row[fieldName];
|
|
585
|
+
return !(typeof current === "object" && current !== null);
|
|
586
|
+
}
|
|
558
587
|
async function resolveRelationField(db, rows, fieldName, rel, cache, publishedOnly = false) {
|
|
559
588
|
if (rows.length === 0) return;
|
|
589
|
+
const batch = [...new Set(rows)];
|
|
560
590
|
if (rel.type === "paragraph") {
|
|
561
|
-
const parentIds =
|
|
591
|
+
const parentIds = batch.map((r) => r["id"]);
|
|
562
592
|
const inList = import_drizzle_orm.sql.join(parentIds.map((id) => import_drizzle_orm.sql`${id}`), import_drizzle_orm.sql`, `);
|
|
563
593
|
const result = await db.execute(
|
|
564
594
|
import_drizzle_orm.sql`SELECT * FROM ${import_drizzle_orm.sql.raw(quoteIdent(rel.table))} WHERE parent_id IN (${inList}) AND parent_field = ${fieldName} ORDER BY "order" ASC`
|
|
565
595
|
);
|
|
566
596
|
const byParent = groupBy(result.rows, "parent_id");
|
|
567
|
-
for (const row of
|
|
597
|
+
for (const row of batch) {
|
|
568
598
|
row[fieldName] = byParent[row["id"]] ?? [];
|
|
569
599
|
}
|
|
570
600
|
} else if (rel.type === "reference") {
|
|
571
|
-
const
|
|
601
|
+
const dropFk = rel.fk_column !== fieldName;
|
|
602
|
+
const pending = batch.filter((r) => needsFkResolution(r, rel.fk_column, fieldName));
|
|
603
|
+
if (pending.length === 0) return;
|
|
604
|
+
const fkValues = pending.map((r) => r[rel.fk_column]).filter(Boolean);
|
|
572
605
|
if (fkValues.length === 0) {
|
|
573
|
-
for (const row of
|
|
606
|
+
for (const row of pending) {
|
|
607
|
+
row[fieldName] = null;
|
|
608
|
+
if (dropFk) delete row[rel.fk_column];
|
|
609
|
+
}
|
|
574
610
|
return;
|
|
575
611
|
}
|
|
576
612
|
const unique = [...new Set(fkValues)];
|
|
@@ -585,12 +621,13 @@ async function resolveRelationField(db, rows, fieldName, rel, cache, publishedOn
|
|
|
585
621
|
cache.set(`${rel.table}:${item["id"]}`, item);
|
|
586
622
|
}
|
|
587
623
|
}
|
|
588
|
-
for (const row of
|
|
624
|
+
for (const row of pending) {
|
|
589
625
|
const fkVal = row[rel.fk_column];
|
|
590
626
|
row[fieldName] = fkVal ? cache.get(`${rel.table}:${fkVal}`) ?? null : null;
|
|
627
|
+
if (dropFk) delete row[rel.fk_column];
|
|
591
628
|
}
|
|
592
629
|
} else if (rel.type === "junction") {
|
|
593
|
-
const parentIds =
|
|
630
|
+
const parentIds = batch.map((r) => r["id"]);
|
|
594
631
|
const inList = import_drizzle_orm.sql.join(parentIds.map((id) => import_drizzle_orm.sql`${id}`), import_drizzle_orm.sql`, `);
|
|
595
632
|
const orderBy = rel.order_column ? import_drizzle_orm.sql` ORDER BY "order" ASC` : import_drizzle_orm.sql``;
|
|
596
633
|
const junctionResult = await db.execute(
|
|
@@ -610,14 +647,20 @@ async function resolveRelationField(db, rows, fieldName, rel, cache, publishedOn
|
|
|
610
647
|
}
|
|
611
648
|
}
|
|
612
649
|
const byLeft = groupBy(jRows, rel.left_column);
|
|
613
|
-
for (const row of
|
|
650
|
+
for (const row of batch) {
|
|
614
651
|
const jEntries = byLeft[row["id"]] ?? [];
|
|
615
652
|
row[fieldName] = jEntries.map((jr) => cache.get(`${rel.table}:${jr[rel.right_column]}`)).filter(Boolean);
|
|
616
653
|
}
|
|
617
654
|
} else if (rel.type === "media") {
|
|
618
|
-
const
|
|
655
|
+
const dropFk = rel.fk_column !== fieldName;
|
|
656
|
+
const pending = batch.filter((r) => needsFkResolution(r, rel.fk_column, fieldName));
|
|
657
|
+
if (pending.length === 0) return;
|
|
658
|
+
const fkValues = pending.map((r) => r[rel.fk_column]).filter(Boolean);
|
|
619
659
|
if (fkValues.length === 0) {
|
|
620
|
-
for (const row of
|
|
660
|
+
for (const row of pending) {
|
|
661
|
+
row[fieldName] = null;
|
|
662
|
+
if (dropFk) delete row[rel.fk_column];
|
|
663
|
+
}
|
|
621
664
|
return;
|
|
622
665
|
}
|
|
623
666
|
const unique = [...new Set(fkValues)];
|
|
@@ -629,9 +672,10 @@ async function resolveRelationField(db, rows, fieldName, rel, cache, publishedOn
|
|
|
629
672
|
cache.set(`media:${item["id"]}`, item);
|
|
630
673
|
}
|
|
631
674
|
}
|
|
632
|
-
for (const row of
|
|
675
|
+
for (const row of pending) {
|
|
633
676
|
const fkVal = row[rel.fk_column];
|
|
634
677
|
row[fieldName] = fkVal ? cache.get(`media:${fkVal}`) ?? null : null;
|
|
678
|
+
if (dropFk) delete row[rel.fk_column];
|
|
635
679
|
}
|
|
636
680
|
}
|
|
637
681
|
}
|
|
@@ -710,8 +754,8 @@ function isClientSafeGraphQLError(error) {
|
|
|
710
754
|
}
|
|
711
755
|
return false;
|
|
712
756
|
}
|
|
713
|
-
function createGraphQLHandler(registry, repos, resolver, db, options) {
|
|
714
|
-
const schema = buildGraphQLSchema(registry);
|
|
757
|
+
function createGraphQLHandler(registry, repos, fieldKeyMaps, resolver, db, options) {
|
|
758
|
+
const schema = buildGraphQLSchema(registry, fieldKeyMaps);
|
|
715
759
|
const { plugins } = buildArmorPlugin({
|
|
716
760
|
maxDepth: options.maxDepth,
|
|
717
761
|
maxComplexity: options.maxComplexity
|