@bobbykim/manguito-cms-cli 0.6.0 → 0.6.2
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.
|
@@ -49,7 +49,7 @@ var init_esm_shims = __esm({
|
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
// ../api/dist/chunk-
|
|
52
|
+
// ../api/dist/chunk-FXPKGPYF.mjs
|
|
53
53
|
init_esm_shims();
|
|
54
54
|
import crypto from "crypto";
|
|
55
55
|
|
|
@@ -1212,7 +1212,7 @@ Subquery.prototype.getSQL = function() {
|
|
|
1212
1212
|
return new SQL([this]);
|
|
1213
1213
|
};
|
|
1214
1214
|
|
|
1215
|
-
// ../api/dist/chunk-
|
|
1215
|
+
// ../api/dist/chunk-FXPKGPYF.mjs
|
|
1216
1216
|
function isColumnBacked(field) {
|
|
1217
1217
|
const col = field.db_column;
|
|
1218
1218
|
if (col === null) return false;
|
|
@@ -1220,14 +1220,15 @@ function isColumnBacked(field) {
|
|
|
1220
1220
|
if (col.junction) return false;
|
|
1221
1221
|
return true;
|
|
1222
1222
|
}
|
|
1223
|
-
function buildFieldKeyMap(pairs, allLabels,
|
|
1223
|
+
function buildFieldKeyMap(pairs, allLabels, droppedColumns, droppedLabels) {
|
|
1224
1224
|
const labelToColumn = /* @__PURE__ */ new Map();
|
|
1225
1225
|
const columnToLabel = /* @__PURE__ */ new Map();
|
|
1226
1226
|
for (const { label, column } of pairs) {
|
|
1227
1227
|
labelToColumn.set(label, column);
|
|
1228
1228
|
columnToLabel.set(column, label);
|
|
1229
1229
|
}
|
|
1230
|
-
for (const label of allLabels) {
|
|
1230
|
+
for (const { label, ownColumn } of allLabels) {
|
|
1231
|
+
if (ownColumn !== void 0) continue;
|
|
1231
1232
|
const columnOwner = columnToLabel.get(label);
|
|
1232
1233
|
if (columnOwner !== void 0 && columnOwner !== label) {
|
|
1233
1234
|
throw new Error(
|
|
@@ -1236,23 +1237,33 @@ function buildFieldKeyMap(pairs, allLabels, droppedKeys) {
|
|
|
1236
1237
|
}
|
|
1237
1238
|
}
|
|
1238
1239
|
for (const label of labelToColumn.keys()) {
|
|
1239
|
-
if (
|
|
1240
|
+
if (droppedLabels.has(label)) labelToColumn.delete(label);
|
|
1240
1241
|
}
|
|
1241
1242
|
for (const column of columnToLabel.keys()) {
|
|
1242
|
-
if (
|
|
1243
|
+
if (droppedColumns.has(column)) columnToLabel.delete(column);
|
|
1243
1244
|
}
|
|
1244
1245
|
const diverges = [...labelToColumn].some(([label, column]) => label !== column);
|
|
1245
|
-
function remap(input, lookup) {
|
|
1246
|
+
function remap(input, lookup, dropped, droppedIfUnmapped) {
|
|
1246
1247
|
const out = {};
|
|
1247
1248
|
for (const key of Object.keys(input)) {
|
|
1248
|
-
|
|
1249
|
-
|
|
1249
|
+
const mapped = lookup.get(key);
|
|
1250
|
+
if (mapped !== void 0) {
|
|
1251
|
+
out[mapped] = input[key];
|
|
1252
|
+
continue;
|
|
1253
|
+
}
|
|
1254
|
+
if (dropped.has(key) || droppedIfUnmapped?.has(key)) continue;
|
|
1255
|
+
out[key] = input[key];
|
|
1250
1256
|
}
|
|
1251
1257
|
return out;
|
|
1252
1258
|
}
|
|
1253
1259
|
return {
|
|
1254
|
-
toStorage
|
|
1255
|
-
|
|
1260
|
+
// toStorage reads LABEL-keyed input: a live label maps and writes
|
|
1261
|
+
// regardless of either drop set; an unmapped key is refused if it is
|
|
1262
|
+
// EITHER the tombstone's own name (droppedLabels) or a raw, unexposed
|
|
1263
|
+
// column (droppedColumns) — see remap's comment.
|
|
1264
|
+
// toLabels reads COLUMN-keyed input, so it consults only droppedColumns.
|
|
1265
|
+
toStorage: (input) => remap(input, labelToColumn, droppedLabels, droppedColumns),
|
|
1266
|
+
toLabels: (row) => remap(row, columnToLabel, droppedColumns),
|
|
1256
1267
|
columnFor: (label) => labelToColumn.get(label),
|
|
1257
1268
|
labelFor: (column) => columnToLabel.get(column),
|
|
1258
1269
|
labels: [...labelToColumn.keys()],
|
|
@@ -1260,37 +1271,52 @@ function buildFieldKeyMap(pairs, allLabels, droppedKeys) {
|
|
|
1260
1271
|
};
|
|
1261
1272
|
}
|
|
1262
1273
|
function createFieldKeyMap(fields) {
|
|
1263
|
-
const
|
|
1274
|
+
const droppedColumns = /* @__PURE__ */ new Set();
|
|
1275
|
+
const droppedLabels = /* @__PURE__ */ new Set();
|
|
1264
1276
|
const pairs = [];
|
|
1265
1277
|
for (const f of fields) {
|
|
1266
1278
|
if (!isColumnBacked(f)) continue;
|
|
1267
1279
|
pairs.push({ label: f.name, column: f.db_column.column_name });
|
|
1268
1280
|
if (f.removed === true) {
|
|
1269
|
-
|
|
1270
|
-
|
|
1281
|
+
droppedLabels.add(f.name);
|
|
1282
|
+
droppedColumns.add(f.db_column.column_name);
|
|
1271
1283
|
}
|
|
1272
1284
|
}
|
|
1273
1285
|
return buildFieldKeyMap(
|
|
1274
1286
|
pairs,
|
|
1275
|
-
fields.map((f) =>
|
|
1276
|
-
|
|
1287
|
+
fields.map((f) => ({
|
|
1288
|
+
label: f.name,
|
|
1289
|
+
// Conditional spread, not a plain assignment — exactOptionalPropertyTypes
|
|
1290
|
+
// forbids present-and-undefined.
|
|
1291
|
+
...isColumnBacked(f) && { ownColumn: f.db_column.column_name }
|
|
1292
|
+
})),
|
|
1293
|
+
droppedColumns,
|
|
1294
|
+
droppedLabels
|
|
1277
1295
|
);
|
|
1278
1296
|
}
|
|
1279
1297
|
function createFieldKeyMapFromProjection(projectionType, allFields) {
|
|
1280
1298
|
const pairs = projectionType.fields.map((f) => ({ label: f.exposed_as, column: f.column_name }));
|
|
1281
|
-
const
|
|
1282
|
-
const
|
|
1299
|
+
const projectedColumns = new Set(pairs.map((p) => p.column));
|
|
1300
|
+
const projectedLabels = new Set(pairs.map((p) => p.label));
|
|
1301
|
+
const droppedColumns = /* @__PURE__ */ new Set();
|
|
1302
|
+
const droppedLabels = /* @__PURE__ */ new Set();
|
|
1283
1303
|
for (const f of allFields) {
|
|
1284
1304
|
if (!isColumnBacked(f)) continue;
|
|
1285
|
-
|
|
1286
|
-
|
|
1305
|
+
if (!projectedColumns.has(f.db_column.column_name)) droppedColumns.add(f.db_column.column_name);
|
|
1306
|
+
if (!projectedLabels.has(f.name)) droppedLabels.add(f.name);
|
|
1287
1307
|
}
|
|
1288
|
-
for (const p of pairs) dropped.delete(p.column);
|
|
1289
|
-
for (const label of projected) dropped.delete(label);
|
|
1290
1308
|
return buildFieldKeyMap(
|
|
1291
1309
|
pairs,
|
|
1292
|
-
allFields.map((f) =>
|
|
1293
|
-
|
|
1310
|
+
allFields.map((f) => ({
|
|
1311
|
+
label: f.name,
|
|
1312
|
+
// See buildFieldKeyMap's collision check: `ownColumn` marks every
|
|
1313
|
+
// column-backed field so the check skips it entirely — only a
|
|
1314
|
+
// paragraph/junction/programmatic label (no column of its own) can
|
|
1315
|
+
// still collide.
|
|
1316
|
+
...isColumnBacked(f) && { ownColumn: f.db_column.column_name }
|
|
1317
|
+
})),
|
|
1318
|
+
droppedColumns,
|
|
1319
|
+
droppedLabels
|
|
1294
1320
|
);
|
|
1295
1321
|
}
|
|
1296
1322
|
function quoteIdent(name) {
|
|
@@ -1462,9 +1488,8 @@ function groupBy(items, key) {
|
|
|
1462
1488
|
}
|
|
1463
1489
|
return result;
|
|
1464
1490
|
}
|
|
1465
|
-
function needsFkResolution(row, fkColumn
|
|
1466
|
-
|
|
1467
|
-
const current = row[fieldName];
|
|
1491
|
+
function needsFkResolution(row, fkColumn) {
|
|
1492
|
+
const current = row[fkColumn];
|
|
1468
1493
|
return !(typeof current === "object" && current !== null);
|
|
1469
1494
|
}
|
|
1470
1495
|
async function resolveRelationField(db, rows, fieldName, rel, cache, publishedOnly = false) {
|
|
@@ -1481,15 +1506,11 @@ async function resolveRelationField(db, rows, fieldName, rel, cache, publishedOn
|
|
|
1481
1506
|
row[fieldName] = byParent[row["id"]] ?? [];
|
|
1482
1507
|
}
|
|
1483
1508
|
} else if (rel.type === "reference") {
|
|
1484
|
-
const
|
|
1485
|
-
const pending = batch.filter((r) => needsFkResolution(r, rel.fk_column, fieldName));
|
|
1509
|
+
const pending = batch.filter((r) => needsFkResolution(r, rel.fk_column));
|
|
1486
1510
|
if (pending.length === 0) return;
|
|
1487
1511
|
const fkValues = pending.map((r) => r[rel.fk_column]).filter(Boolean);
|
|
1488
1512
|
if (fkValues.length === 0) {
|
|
1489
|
-
for (const row of pending)
|
|
1490
|
-
row[fieldName] = null;
|
|
1491
|
-
if (dropFk) delete row[rel.fk_column];
|
|
1492
|
-
}
|
|
1513
|
+
for (const row of pending) row[rel.fk_column] = null;
|
|
1493
1514
|
return;
|
|
1494
1515
|
}
|
|
1495
1516
|
const unique = [...new Set(fkValues)];
|
|
@@ -1506,8 +1527,7 @@ async function resolveRelationField(db, rows, fieldName, rel, cache, publishedOn
|
|
|
1506
1527
|
}
|
|
1507
1528
|
for (const row of pending) {
|
|
1508
1529
|
const fkVal = row[rel.fk_column];
|
|
1509
|
-
row[
|
|
1510
|
-
if (dropFk) delete row[rel.fk_column];
|
|
1530
|
+
row[rel.fk_column] = fkVal ? cache.get(`${rel.table}:${fkVal}`) ?? null : null;
|
|
1511
1531
|
}
|
|
1512
1532
|
} else if (rel.type === "junction") {
|
|
1513
1533
|
const parentIds = batch.map((r) => r["id"]);
|
|
@@ -1535,15 +1555,11 @@ async function resolveRelationField(db, rows, fieldName, rel, cache, publishedOn
|
|
|
1535
1555
|
row[fieldName] = jEntries.map((jr) => cache.get(`${rel.table}:${jr[rel.right_column]}`)).filter(Boolean);
|
|
1536
1556
|
}
|
|
1537
1557
|
} else if (rel.type === "media") {
|
|
1538
|
-
const
|
|
1539
|
-
const pending = batch.filter((r) => needsFkResolution(r, rel.fk_column, fieldName));
|
|
1558
|
+
const pending = batch.filter((r) => needsFkResolution(r, rel.fk_column));
|
|
1540
1559
|
if (pending.length === 0) return;
|
|
1541
1560
|
const fkValues = pending.map((r) => r[rel.fk_column]).filter(Boolean);
|
|
1542
1561
|
if (fkValues.length === 0) {
|
|
1543
|
-
for (const row of pending)
|
|
1544
|
-
row[fieldName] = null;
|
|
1545
|
-
if (dropFk) delete row[rel.fk_column];
|
|
1546
|
-
}
|
|
1562
|
+
for (const row of pending) row[rel.fk_column] = null;
|
|
1547
1563
|
return;
|
|
1548
1564
|
}
|
|
1549
1565
|
const unique = [...new Set(fkValues)];
|
|
@@ -1557,8 +1573,7 @@ async function resolveRelationField(db, rows, fieldName, rel, cache, publishedOn
|
|
|
1557
1573
|
}
|
|
1558
1574
|
for (const row of pending) {
|
|
1559
1575
|
const fkVal = row[rel.fk_column];
|
|
1560
|
-
row[
|
|
1561
|
-
if (dropFk) delete row[rel.fk_column];
|
|
1576
|
+
row[rel.fk_column] = fkVal ? cache.get(`media:${fkVal}`) ?? null : null;
|
|
1562
1577
|
}
|
|
1563
1578
|
}
|
|
1564
1579
|
}
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
init_esm_shims,
|
|
12
12
|
isColumnBacked,
|
|
13
13
|
resolveRelationField
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-52I54C3X.js";
|
|
15
15
|
|
|
16
16
|
// ../../node_modules/.pnpm/@whatwg-node+fetch@0.10.13/node_modules/@whatwg-node/fetch/dist/shouldSkipPonyfill.js
|
|
17
17
|
var require_shouldSkipPonyfill = __commonJS({
|
|
@@ -10786,10 +10786,10 @@ var require_parser = __commonJS({
|
|
|
10786
10786
|
}
|
|
10787
10787
|
});
|
|
10788
10788
|
|
|
10789
|
-
// ../api/dist/handler-
|
|
10789
|
+
// ../api/dist/handler-GED3I7Z2.mjs
|
|
10790
10790
|
init_esm_shims();
|
|
10791
10791
|
|
|
10792
|
-
// ../api/dist/chunk-
|
|
10792
|
+
// ../api/dist/chunk-4LLELFAZ.mjs
|
|
10793
10793
|
init_esm_shims();
|
|
10794
10794
|
|
|
10795
10795
|
// ../../node_modules/.pnpm/graphql-yoga@5.21.2_graphql@16.14.2/node_modules/graphql-yoga/esm/index.js
|
|
@@ -30122,7 +30122,7 @@ function createYoga(options) {
|
|
|
30122
30122
|
});
|
|
30123
30123
|
}
|
|
30124
30124
|
|
|
30125
|
-
// ../api/dist/chunk-
|
|
30125
|
+
// ../api/dist/chunk-4LLELFAZ.mjs
|
|
30126
30126
|
var import_dataloader = __toESM(require_dataloader(), 1);
|
|
30127
30127
|
|
|
30128
30128
|
// ../../node_modules/.pnpm/@escape.tech+graphql-armor@3.2.0_@envelop+core@5.5.1_@escape.tech+graphql-armor-types@0.7.0/node_modules/@escape.tech/graphql-armor/dist/graphql-armor.esm.js
|
|
@@ -30880,7 +30880,7 @@ var EnvelopArmor = class {
|
|
|
30880
30880
|
}
|
|
30881
30881
|
};
|
|
30882
30882
|
|
|
30883
|
-
// ../api/dist/chunk-
|
|
30883
|
+
// ../api/dist/chunk-4LLELFAZ.mjs
|
|
30884
30884
|
var DateTimeScalar = new GraphQLScalarType({
|
|
30885
30885
|
name: "DateTime",
|
|
30886
30886
|
description: "ISO-8601 date-time string",
|
|
@@ -30979,10 +30979,13 @@ var SORTABLE = [
|
|
|
30979
30979
|
{ gql: "createdAt", value: "created_at" },
|
|
30980
30980
|
{ gql: "updatedAt", value: "updated_at" }
|
|
30981
30981
|
];
|
|
30982
|
-
function buildSortFieldEnum(typeName) {
|
|
30982
|
+
function buildSortFieldEnum(typeName, fieldKeys) {
|
|
30983
|
+
const resolvable = SORTABLE.filter(
|
|
30984
|
+
(s) => s.gql === "createdAt" || s.gql === "updatedAt" || fieldKeys === void 0 || fieldKeys.columnFor(s.value) !== void 0
|
|
30985
|
+
);
|
|
30983
30986
|
return new GraphQLEnumType({
|
|
30984
30987
|
name: `${typeName}SortField`,
|
|
30985
|
-
values: Object.fromEntries(
|
|
30988
|
+
values: Object.fromEntries(resolvable.map((s) => [s.gql, { value: s.value }]))
|
|
30986
30989
|
});
|
|
30987
30990
|
}
|
|
30988
30991
|
function comparableFilterInput(name, scalar) {
|
|
@@ -31026,18 +31029,19 @@ function filterInputForField(fieldType) {
|
|
|
31026
31029
|
if (scalar === null) return null;
|
|
31027
31030
|
return StringFilter;
|
|
31028
31031
|
}
|
|
31029
|
-
function buildFilterInputType(type) {
|
|
31032
|
+
function buildFilterInputType(type, viewFields) {
|
|
31030
31033
|
const fields = {};
|
|
31031
31034
|
fields["id"] = { type: IDFilter };
|
|
31032
31035
|
fields["published"] = { type: BooleanFilter };
|
|
31033
31036
|
fields["createdAt"] = { type: DateTimeFilter };
|
|
31034
31037
|
fields["updatedAt"] = { type: DateTimeFilter };
|
|
31035
31038
|
if (type.schema_type === "content-type") fields["slug"] = { type: StringFilter };
|
|
31036
|
-
|
|
31039
|
+
const entries = viewFields !== void 0 ? viewFields.map((v) => ({ field: v.field, exposedAs: v.exposedAs })) : type.fields.filter((f) => f.removed !== true).map((f) => ({ field: f, exposedAs: f.name }));
|
|
31040
|
+
for (const { field: f, exposedAs } of entries) {
|
|
31037
31041
|
if (f.field_type === "programmatic" || f.field_type === "paragraph") continue;
|
|
31038
31042
|
if (f.field_type === "image" || f.field_type === "video" || f.field_type === "file") continue;
|
|
31039
31043
|
const input = filterInputForField(f.field_type);
|
|
31040
|
-
if (input) fields[buildFieldNameMap([
|
|
31044
|
+
if (input) fields[buildFieldNameMap([exposedAs]).toGraphql(exposedAs)] = { type: input };
|
|
31041
31045
|
}
|
|
31042
31046
|
if (Object.keys(fields).length === 0) return null;
|
|
31043
31047
|
return new GraphQLInputObjectType({ name: `${graphqlTypeName(type.name)}Filter`, fields });
|
|
@@ -31070,12 +31074,14 @@ function codeError(code, message) {
|
|
|
31070
31074
|
function isPublished(item) {
|
|
31071
31075
|
return !!item && item["published"] === true;
|
|
31072
31076
|
}
|
|
31073
|
-
function resolveFieldValue(field, row) {
|
|
31077
|
+
function resolveFieldValue(field, row, fallback) {
|
|
31074
31078
|
const key = isColumnBacked(field) ? field.db_column.column_name : field.name;
|
|
31075
|
-
|
|
31079
|
+
const value = row[key];
|
|
31080
|
+
if ((value === null || value === void 0) && fallback !== void 0) return fallback;
|
|
31081
|
+
return value ?? null;
|
|
31076
31082
|
}
|
|
31077
|
-
function scalarFieldResolver(field) {
|
|
31078
|
-
return (parent) => resolveFieldValue(field, parent);
|
|
31083
|
+
function scalarFieldResolver(field, fallback) {
|
|
31084
|
+
return (parent) => resolveFieldValue(field, parent, fallback);
|
|
31079
31085
|
}
|
|
31080
31086
|
function relationFieldResolver(typeName, schemaFieldName) {
|
|
31081
31087
|
return (parent, _args, ctx) => ctx.loaders.load(typeName, schemaFieldName, parent);
|
|
@@ -31167,7 +31173,7 @@ var MEDIA = new GraphQLObjectType({
|
|
|
31167
31173
|
duration: { type: GraphQLInt, resolve: (m) => m.duration }
|
|
31168
31174
|
}
|
|
31169
31175
|
});
|
|
31170
|
-
function buildGraphQLSchema(registry, fieldKeyMaps = {}) {
|
|
31176
|
+
function buildGraphQLSchema(registry, fieldKeyMaps = {}, view, programmaticKeyMaps = fieldKeyMaps) {
|
|
31171
31177
|
const objectTypes = /* @__PURE__ */ new Map();
|
|
31172
31178
|
const enumTypes = /* @__PURE__ */ new Map();
|
|
31173
31179
|
for (const [name, enumType] of Object.entries(registry.enum_types)) {
|
|
@@ -31186,14 +31192,14 @@ function buildGraphQLSchema(registry, fieldKeyMaps = {}) {
|
|
|
31186
31192
|
);
|
|
31187
31193
|
}
|
|
31188
31194
|
}
|
|
31189
|
-
function outputTypeForField(field) {
|
|
31195
|
+
function outputTypeForField(field, required) {
|
|
31190
31196
|
const scalar = scalarOutputType(field.field_type);
|
|
31191
|
-
if (scalar) return
|
|
31197
|
+
if (scalar) return required ? new GraphQLNonNull(scalar) : scalar;
|
|
31192
31198
|
if (field.field_type === "enum") {
|
|
31193
31199
|
const ref = field.ui_component.component === "select" ? field.ui_component.enum_ref : void 0;
|
|
31194
31200
|
const et = ref ? enumTypes.get(ref) : void 0;
|
|
31195
31201
|
const t = et ?? GraphQLString;
|
|
31196
|
-
return
|
|
31202
|
+
return required ? new GraphQLNonNull(t) : t;
|
|
31197
31203
|
}
|
|
31198
31204
|
if (field.field_type === "image" || field.field_type === "video" || field.field_type === "file") {
|
|
31199
31205
|
return MEDIA;
|
|
@@ -31223,8 +31229,17 @@ function buildGraphQLSchema(registry, fieldKeyMaps = {}) {
|
|
|
31223
31229
|
}
|
|
31224
31230
|
return GraphQLString;
|
|
31225
31231
|
}
|
|
31232
|
+
function exposedFields(type) {
|
|
31233
|
+
return type.fields.filter((f) => f.removed !== true);
|
|
31234
|
+
}
|
|
31235
|
+
function viewFieldsFor(machineName, type) {
|
|
31236
|
+
return view?.[machineName]?.fields ?? exposedFields(type).map((f) => ({ field: f, exposedAs: f.name, required: f.required }));
|
|
31237
|
+
}
|
|
31226
31238
|
function buildObjectType(machineName, type) {
|
|
31227
|
-
const
|
|
31239
|
+
const visible = viewFieldsFor(machineName, type);
|
|
31240
|
+
const mediaFieldNames = type.fields.filter(
|
|
31241
|
+
(f) => f.removed !== true && (f.field_type === "image" || f.field_type === "video" || f.field_type === "file")
|
|
31242
|
+
).map((f) => f.name);
|
|
31228
31243
|
return new GraphQLObjectType({
|
|
31229
31244
|
name: graphqlTypeName(machineName),
|
|
31230
31245
|
fields: () => {
|
|
@@ -31238,23 +31253,25 @@ function buildGraphQLSchema(registry, fieldKeyMaps = {}) {
|
|
|
31238
31253
|
}
|
|
31239
31254
|
fields["createdAt"] = { type: new GraphQLNonNull(DateTimeScalar), resolve: (p) => p["created_at"] };
|
|
31240
31255
|
fields["updatedAt"] = { type: new GraphQLNonNull(DateTimeScalar), resolve: (p) => p["updated_at"] };
|
|
31241
|
-
for (const
|
|
31242
|
-
const
|
|
31243
|
-
const
|
|
31256
|
+
for (const vf of visible) {
|
|
31257
|
+
const field = vf.field;
|
|
31258
|
+
const gqlName = toCamelCase(vf.exposedAs);
|
|
31259
|
+
const outType = outputTypeForField(field, vf.required);
|
|
31244
31260
|
let resolve;
|
|
31245
31261
|
if (field.field_type === "programmatic") {
|
|
31246
|
-
resolve = programmaticFieldResolver(
|
|
31247
|
-
machineName,
|
|
31248
|
-
field.name,
|
|
31249
|
-
mediaFieldNames,
|
|
31250
|
-
fieldKeyMaps[machineName]
|
|
31251
|
-
);
|
|
31262
|
+
resolve = programmaticFieldResolver(machineName, field.name, mediaFieldNames, programmaticKeyMaps[machineName]);
|
|
31252
31263
|
} else if (field.field_type === "reference" || field.field_type === "paragraph" || field.field_type === "image" || field.field_type === "video" || field.field_type === "file") {
|
|
31253
31264
|
resolve = relationFieldResolver(machineName, field.name);
|
|
31254
31265
|
} else {
|
|
31255
|
-
resolve = scalarFieldResolver(field);
|
|
31266
|
+
resolve = scalarFieldResolver(field, vf.fallback);
|
|
31256
31267
|
}
|
|
31257
|
-
fields[gqlName] = {
|
|
31268
|
+
fields[gqlName] = {
|
|
31269
|
+
type: outType,
|
|
31270
|
+
resolve,
|
|
31271
|
+
// Conditional spread, not `deprecationReason: vf.deprecationReason`
|
|
31272
|
+
// — exactOptionalPropertyTypes forbids present-and-undefined.
|
|
31273
|
+
...vf.deprecationReason !== void 0 && { deprecationReason: vf.deprecationReason }
|
|
31274
|
+
};
|
|
31258
31275
|
}
|
|
31259
31276
|
return fields;
|
|
31260
31277
|
}
|
|
@@ -31286,7 +31303,11 @@ function buildGraphQLSchema(registry, fieldKeyMaps = {}) {
|
|
|
31286
31303
|
const queryFields = {};
|
|
31287
31304
|
for (const [name, ct] of Object.entries(registry.content_types)) {
|
|
31288
31305
|
const objType = objectTypes.get(name);
|
|
31289
|
-
const
|
|
31306
|
+
const visible = viewFieldsFor(name, ct);
|
|
31307
|
+
const nameMap = buildFieldNameMap([
|
|
31308
|
+
...visible.map((v) => v.exposedAs),
|
|
31309
|
+
...ct.system_fields.map((s) => s.name)
|
|
31310
|
+
]);
|
|
31290
31311
|
if (ct.only_one) {
|
|
31291
31312
|
queryFields[singleQueryName(name)] = { type: objType, resolve: singletonResolver(name) };
|
|
31292
31313
|
continue;
|
|
@@ -31298,13 +31319,13 @@ function buildGraphQLSchema(registry, fieldKeyMaps = {}) {
|
|
|
31298
31319
|
meta: { type: new GraphQLNonNull(PAGE_META), resolve: (r) => r.meta }
|
|
31299
31320
|
}
|
|
31300
31321
|
});
|
|
31301
|
-
const filterType = buildFilterInputType(ct);
|
|
31322
|
+
const filterType = buildFilterInputType(ct, visible);
|
|
31302
31323
|
queryFields[collectionQueryName(name)] = {
|
|
31303
31324
|
type: new GraphQLNonNull(listType),
|
|
31304
31325
|
args: {
|
|
31305
31326
|
page: { type: GraphQLInt },
|
|
31306
31327
|
perPage: { type: GraphQLInt },
|
|
31307
|
-
sortBy: { type: buildSortFieldEnum(graphqlTypeName(name)) },
|
|
31328
|
+
sortBy: { type: buildSortFieldEnum(graphqlTypeName(name), fieldKeyMaps[name]) },
|
|
31308
31329
|
sortOrder: { type: SortOrderEnum },
|
|
31309
31330
|
...filterType ? { filter: { type: filterType } } : {}
|
|
31310
31331
|
},
|
|
@@ -31328,7 +31349,11 @@ function buildGraphQLSchema(registry, fieldKeyMaps = {}) {
|
|
|
31328
31349
|
queryFields[collectionQueryName(name)] = {
|
|
31329
31350
|
type: new GraphQLNonNull(listType),
|
|
31330
31351
|
args: { page: { type: GraphQLInt }, perPage: { type: GraphQLInt } },
|
|
31331
|
-
resolve: collectionResolver(
|
|
31352
|
+
resolve: collectionResolver(
|
|
31353
|
+
name,
|
|
31354
|
+
buildFieldNameMap(viewFieldsFor(name, tt).map((v) => v.exposedAs)),
|
|
31355
|
+
fieldKeyMaps[name]
|
|
31356
|
+
)
|
|
31332
31357
|
};
|
|
31333
31358
|
queryFields[singleQueryName(name)] = {
|
|
31334
31359
|
type: objType,
|
|
@@ -31340,6 +31365,68 @@ function buildGraphQLSchema(registry, fieldKeyMaps = {}) {
|
|
|
31340
31365
|
query: new GraphQLObjectType({ name: "Query", fields: queryFields })
|
|
31341
31366
|
});
|
|
31342
31367
|
}
|
|
31368
|
+
function byColumn(fields) {
|
|
31369
|
+
const out = /* @__PURE__ */ new Map();
|
|
31370
|
+
for (const f of fields) {
|
|
31371
|
+
if (!isColumnBacked(f)) continue;
|
|
31372
|
+
out.set(f.db_column.column_name, f);
|
|
31373
|
+
}
|
|
31374
|
+
return out;
|
|
31375
|
+
}
|
|
31376
|
+
function deprecationFor(field, currentLabels, currentVersion) {
|
|
31377
|
+
const currentLabel = currentLabels.get(field.column_name);
|
|
31378
|
+
if (currentLabel === void 0) {
|
|
31379
|
+
return `Removed in ${currentVersion}; column retained while this version is live.`;
|
|
31380
|
+
}
|
|
31381
|
+
if (currentLabel !== field.exposed_as) {
|
|
31382
|
+
return `Renamed to '${currentLabel}' in ${currentVersion}.`;
|
|
31383
|
+
}
|
|
31384
|
+
return void 0;
|
|
31385
|
+
}
|
|
31386
|
+
function buildVersionView(input) {
|
|
31387
|
+
const { registry, projection, currentProjection, currentVersion } = input;
|
|
31388
|
+
const out = {};
|
|
31389
|
+
const sources = [
|
|
31390
|
+
registry.content_types,
|
|
31391
|
+
registry.taxonomy_types,
|
|
31392
|
+
registry.paragraph_types
|
|
31393
|
+
];
|
|
31394
|
+
for (const source of sources) {
|
|
31395
|
+
for (const [typeName, type] of Object.entries(source)) {
|
|
31396
|
+
const projectionType = projection?.types[typeName];
|
|
31397
|
+
if (projectionType === void 0) {
|
|
31398
|
+
out[typeName] = {
|
|
31399
|
+
fields: type.fields.filter((f) => f.removed !== true).map((f) => ({ field: f, exposedAs: f.name, required: f.required }))
|
|
31400
|
+
};
|
|
31401
|
+
continue;
|
|
31402
|
+
}
|
|
31403
|
+
const columns = byColumn(type.fields);
|
|
31404
|
+
const currentLabels = /* @__PURE__ */ new Map();
|
|
31405
|
+
for (const f of currentProjection?.types[typeName]?.fields ?? []) {
|
|
31406
|
+
currentLabels.set(f.column_name, f.exposed_as);
|
|
31407
|
+
}
|
|
31408
|
+
const fields = [];
|
|
31409
|
+
for (const pf of projectionType.fields) {
|
|
31410
|
+
const field = columns.get(pf.column_name);
|
|
31411
|
+
if (field === void 0) continue;
|
|
31412
|
+
const reason = deprecationFor(pf, currentLabels, currentVersion);
|
|
31413
|
+
fields.push({
|
|
31414
|
+
field,
|
|
31415
|
+
exposedAs: pf.exposed_as,
|
|
31416
|
+
required: pf.required,
|
|
31417
|
+
...pf.fallback !== void 0 && { fallback: pf.fallback },
|
|
31418
|
+
...reason !== void 0 && { deprecationReason: reason }
|
|
31419
|
+
});
|
|
31420
|
+
}
|
|
31421
|
+
for (const f of type.fields) {
|
|
31422
|
+
if (isColumnBacked(f) || f.removed === true) continue;
|
|
31423
|
+
fields.push({ field: f, exposedAs: f.name, required: f.required });
|
|
31424
|
+
}
|
|
31425
|
+
out[typeName] = { fields };
|
|
31426
|
+
}
|
|
31427
|
+
}
|
|
31428
|
+
return out;
|
|
31429
|
+
}
|
|
31343
31430
|
function createRelationLoaders(db, registry) {
|
|
31344
31431
|
const relMaps = /* @__PURE__ */ new Map();
|
|
31345
31432
|
const loaders = /* @__PURE__ */ new Map();
|
|
@@ -31361,7 +31448,8 @@ function createRelationLoaders(db, registry) {
|
|
|
31361
31448
|
async (parents) => {
|
|
31362
31449
|
const rows = parents;
|
|
31363
31450
|
await resolveRelationField(db, rows, fieldName, rel, cache, true);
|
|
31364
|
-
|
|
31451
|
+
const resultKey = rel.type === "reference" || rel.type === "media" ? rel.fk_column : fieldName;
|
|
31452
|
+
return rows.map((r) => r[resultKey]);
|
|
31365
31453
|
},
|
|
31366
31454
|
// Batch within a tick; do not memoize by parent identity (rows are mutated
|
|
31367
31455
|
// and may recur across nesting levels).
|
|
@@ -31407,15 +31495,29 @@ function isClientSafeGraphQLError(error) {
|
|
|
31407
31495
|
}
|
|
31408
31496
|
return false;
|
|
31409
31497
|
}
|
|
31410
|
-
function createGraphQLHandler(registry, repos, fieldKeyMaps, resolver, db, options) {
|
|
31411
|
-
|
|
31498
|
+
function createGraphQLHandler(registry, repos, fieldKeyMaps, resolver, db, options, versioning = {}) {
|
|
31499
|
+
let view;
|
|
31500
|
+
if (versioning.projection !== void 0) {
|
|
31501
|
+
if (versioning.currentVersion === void 0) {
|
|
31502
|
+
throw new Error(
|
|
31503
|
+
'createGraphQLHandler: currentVersion is required when a projection is supplied \u2014 deprecation reasons name it, and an empty one ships "Removed in ." into published SDL.'
|
|
31504
|
+
);
|
|
31505
|
+
}
|
|
31506
|
+
view = buildVersionView({
|
|
31507
|
+
registry,
|
|
31508
|
+
projection: versioning.projection,
|
|
31509
|
+
currentProjection: versioning.currentProjection,
|
|
31510
|
+
currentVersion: versioning.currentVersion
|
|
31511
|
+
});
|
|
31512
|
+
}
|
|
31513
|
+
const schema = buildGraphQLSchema(registry, fieldKeyMaps, view, versioning.currentFieldKeyMaps ?? fieldKeyMaps);
|
|
31412
31514
|
const { plugins } = buildArmorPlugin({
|
|
31413
31515
|
maxDepth: options.maxDepth,
|
|
31414
31516
|
maxComplexity: options.maxComplexity
|
|
31415
31517
|
});
|
|
31416
31518
|
const yoga = createYoga({
|
|
31417
31519
|
schema,
|
|
31418
|
-
graphqlEndpoint: "/graphql",
|
|
31520
|
+
graphqlEndpoint: versioning.endpoint ?? "/graphql",
|
|
31419
31521
|
graphiql: options.graphiql,
|
|
31420
31522
|
landingPage: false,
|
|
31421
31523
|
maskedErrors: {
|
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
resolveRelationField,
|
|
40
40
|
sql,
|
|
41
41
|
tracer
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-52I54C3X.js";
|
|
43
43
|
|
|
44
44
|
// ../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js
|
|
45
45
|
var require_identity = __commonJS({
|
|
@@ -30444,7 +30444,7 @@ function buildProjections(input2) {
|
|
|
30444
30444
|
const fields = type.fields.filter((f) => isColumnBacked2(f) && f.removed !== true).map((f) => {
|
|
30445
30445
|
const column_name = f.db_column.column_name;
|
|
30446
30446
|
const fallback = fallbacks.get(`${typeName}.${column_name}`);
|
|
30447
|
-
return fallback === void 0 ? { column_name, exposed_as: f.name } : { column_name, exposed_as: f.name, fallback };
|
|
30447
|
+
return fallback === void 0 ? { column_name, exposed_as: f.name, required: f.required } : { column_name, exposed_as: f.name, required: f.required, fallback };
|
|
30448
30448
|
});
|
|
30449
30449
|
types3[typeName] = { fields };
|
|
30450
30450
|
}
|
|
@@ -47129,7 +47129,7 @@ function createSecurityHeadersMiddleware(options = {}) {
|
|
|
47129
47129
|
c.res.headers.set("X-Content-Type-Options", "nosniff");
|
|
47130
47130
|
c.res.headers.set("X-Frame-Options", "DENY");
|
|
47131
47131
|
c.res.headers.set("Referrer-Policy", "no-referrer");
|
|
47132
|
-
const isGraphiql = graphiqlPath !== void 0 && c.req.path === graphiqlPath;
|
|
47132
|
+
const isGraphiql = graphiqlPath !== void 0 && (c.req.path === graphiqlPath || c.req.path.startsWith(`${graphiqlPath}/`));
|
|
47133
47133
|
c.res.headers.set("Content-Security-Policy", isGraphiql ? graphiqlCsp : csp);
|
|
47134
47134
|
};
|
|
47135
47135
|
}
|
|
@@ -47618,14 +47618,16 @@ function isPlainRow(v2) {
|
|
|
47618
47618
|
return typeof v2 === "object" && v2 !== null && !Array.isArray(v2) && !(v2 instanceof Date);
|
|
47619
47619
|
}
|
|
47620
47620
|
var MEDIA_FIELD_TYPES = /* @__PURE__ */ new Set(["image", "video", "file"]);
|
|
47621
|
-
function nestedTargets(fields) {
|
|
47621
|
+
function nestedTargets(fields, map2) {
|
|
47622
47622
|
const out = [];
|
|
47623
47623
|
for (const f of fields) {
|
|
47624
47624
|
if (MEDIA_FIELD_TYPES.has(f.field_type)) continue;
|
|
47625
47625
|
if (f.field_type !== "paragraph" && f.field_type !== "reference") continue;
|
|
47626
47626
|
const ref = f.ui_component.ref;
|
|
47627
47627
|
if (!ref) continue;
|
|
47628
|
-
|
|
47628
|
+
const label = isColumnBacked(f) ? map2.labelFor(f.db_column.column_name) : f.name;
|
|
47629
|
+
if (label === void 0) continue;
|
|
47630
|
+
out.push({ label, target: ref });
|
|
47629
47631
|
}
|
|
47630
47632
|
return out;
|
|
47631
47633
|
}
|
|
@@ -47643,7 +47645,7 @@ function buildProjectors(registry2, fieldKeyMaps, fallbacks) {
|
|
|
47643
47645
|
const typeFallbacks = fallbacks?.[typeName];
|
|
47644
47646
|
projectors[typeName] = {
|
|
47645
47647
|
map: map2,
|
|
47646
|
-
nested: nestedTargets(type.fields),
|
|
47648
|
+
nested: nestedTargets(type.fields, map2),
|
|
47647
47649
|
// Spread rather than assign: with exactOptionalPropertyTypes, an optional
|
|
47648
47650
|
// property may be ABSENT but not present-and-undefined.
|
|
47649
47651
|
...typeFallbacks !== void 0 && { fallbacks: typeFallbacks }
|
|
@@ -47723,7 +47725,28 @@ function parseFilters(url2, validFields, columnFor) {
|
|
|
47723
47725
|
function isPublished(item) {
|
|
47724
47726
|
return item["published"] === true;
|
|
47725
47727
|
}
|
|
47726
|
-
function registerPublicContentRoutes(app, registry2, repos, projectors, paths, listRateLimit, resolver) {
|
|
47728
|
+
function registerPublicContentRoutes(app, registry2, repos, projectors, paths, listRateLimit, resolver, resolverProjectors) {
|
|
47729
|
+
const forResolver = resolverProjectors ?? projectors;
|
|
47730
|
+
function pickProgrammatic(resolved, names) {
|
|
47731
|
+
const out = {};
|
|
47732
|
+
for (const name of names) if (name in resolved) out[name] = resolved[name];
|
|
47733
|
+
return out;
|
|
47734
|
+
}
|
|
47735
|
+
async function respondItem(row, typeName, programmatic) {
|
|
47736
|
+
const data = projectRow(row, typeName, projectors);
|
|
47737
|
+
if (!resolver?.hasSchema(typeName)) return data;
|
|
47738
|
+
const resolved = await resolver.resolveItem(typeName, projectRow(row, typeName, forResolver));
|
|
47739
|
+
return { ...data, ...pickProgrammatic(resolved, programmatic) };
|
|
47740
|
+
}
|
|
47741
|
+
async function respondList(rows, typeName, programmatic) {
|
|
47742
|
+
const data = rows.map((row) => projectRow(row, typeName, projectors));
|
|
47743
|
+
if (!resolver?.hasSchema(typeName)) return data;
|
|
47744
|
+
const resolved = await resolver.resolveList(
|
|
47745
|
+
typeName,
|
|
47746
|
+
rows.map((row) => projectRow(row, typeName, forResolver))
|
|
47747
|
+
);
|
|
47748
|
+
return data.map((d2, i) => ({ ...d2, ...pickProgrammatic(resolved[i], programmatic) }));
|
|
47749
|
+
}
|
|
47727
47750
|
function registerListRoute(path7, handler) {
|
|
47728
47751
|
if (listRateLimit) {
|
|
47729
47752
|
app.get(path7, listRateLimit, handler);
|
|
@@ -47747,18 +47770,29 @@ function registerPublicContentRoutes(app, registry2, repos, projectors, paths, l
|
|
|
47747
47770
|
return c.json({ ok: true, data });
|
|
47748
47771
|
});
|
|
47749
47772
|
for (const [typeName, contentType] of Object.entries(registry2.content_types)) {
|
|
47773
|
+
let translateInclude2 = function(requested) {
|
|
47774
|
+
const include = [];
|
|
47775
|
+
for (const field of requested) {
|
|
47776
|
+
const registryName = includeNames.get(field);
|
|
47777
|
+
if (registryName === void 0) return { ok: false, field };
|
|
47778
|
+
include.push(registryName);
|
|
47779
|
+
}
|
|
47780
|
+
return { ok: true, include };
|
|
47781
|
+
};
|
|
47782
|
+
var translateInclude = translateInclude2;
|
|
47750
47783
|
const basePath = contentType.default_base_path;
|
|
47751
47784
|
const repo = repos[typeName];
|
|
47752
47785
|
if (!repo) continue;
|
|
47753
47786
|
const fieldKeys = projectors[typeName].map;
|
|
47754
|
-
const
|
|
47787
|
+
const programmatic = contentType.fields.filter((f) => f.field_type === "programmatic").map((f) => f.name);
|
|
47788
|
+
const includeNames = /* @__PURE__ */ new Map();
|
|
47755
47789
|
for (const f of contentType.fields) {
|
|
47756
47790
|
if (!RELATION_FIELD_TYPES.has(f.field_type)) continue;
|
|
47757
47791
|
if (isColumnBacked(f)) {
|
|
47758
47792
|
const label = fieldKeys.labelFor(f.db_column.column_name);
|
|
47759
|
-
if (label !== void 0)
|
|
47793
|
+
if (label !== void 0) includeNames.set(label, f.name);
|
|
47760
47794
|
} else {
|
|
47761
|
-
|
|
47795
|
+
includeNames.set(f.name, f.name);
|
|
47762
47796
|
}
|
|
47763
47797
|
}
|
|
47764
47798
|
const filterableFieldNames = /* @__PURE__ */ new Set([
|
|
@@ -47777,8 +47811,11 @@ function registerPublicContentRoutes(app, registry2, repos, projectors, paths, l
|
|
|
47777
47811
|
404
|
|
47778
47812
|
);
|
|
47779
47813
|
}
|
|
47780
|
-
|
|
47781
|
-
|
|
47814
|
+
const data = await respondItem(
|
|
47815
|
+
result.data[0],
|
|
47816
|
+
typeName,
|
|
47817
|
+
programmatic
|
|
47818
|
+
);
|
|
47782
47819
|
return c.json({ ok: true, data });
|
|
47783
47820
|
});
|
|
47784
47821
|
} else {
|
|
@@ -47835,21 +47872,20 @@ function registerPublicContentRoutes(app, registry2, repos, projectors, paths, l
|
|
|
47835
47872
|
400
|
|
47836
47873
|
);
|
|
47837
47874
|
}
|
|
47838
|
-
const
|
|
47839
|
-
|
|
47840
|
-
|
|
47841
|
-
|
|
47842
|
-
|
|
47843
|
-
|
|
47844
|
-
|
|
47845
|
-
|
|
47846
|
-
|
|
47847
|
-
|
|
47848
|
-
|
|
47849
|
-
|
|
47850
|
-
);
|
|
47851
|
-
}
|
|
47875
|
+
const translated = translateInclude2(parseInclude(c.req.query("include")));
|
|
47876
|
+
if (!translated.ok) {
|
|
47877
|
+
return c.json(
|
|
47878
|
+
{
|
|
47879
|
+
ok: false,
|
|
47880
|
+
error: {
|
|
47881
|
+
code: "INVALID_INCLUDE_FIELD",
|
|
47882
|
+
message: `'${translated.field}' is not a valid relation field`
|
|
47883
|
+
}
|
|
47884
|
+
},
|
|
47885
|
+
400
|
|
47886
|
+
);
|
|
47852
47887
|
}
|
|
47888
|
+
const include = translated.include;
|
|
47853
47889
|
const sortColumn = fieldKeys.labels.includes(sortBy) ? fieldKeys.columnFor(sortBy) : sortBy;
|
|
47854
47890
|
const result = await repo.findMany({
|
|
47855
47891
|
published_only: true,
|
|
@@ -47860,29 +47896,25 @@ function registerPublicContentRoutes(app, registry2, repos, projectors, paths, l
|
|
|
47860
47896
|
filters: filtersResult.filters,
|
|
47861
47897
|
include
|
|
47862
47898
|
});
|
|
47863
|
-
const
|
|
47864
|
-
(row) => projectRow(row, typeName, projectors)
|
|
47865
|
-
);
|
|
47866
|
-
const data = resolver?.hasSchema(typeName) ? await resolver.resolveList(typeName, labeled) : labeled;
|
|
47899
|
+
const data = await respondList(result.data, typeName, programmatic);
|
|
47867
47900
|
return c.json({ ...result, data });
|
|
47868
47901
|
});
|
|
47869
47902
|
app.get(paths.item(basePath), async (c) => {
|
|
47870
47903
|
const slug = c.req.param("slug");
|
|
47871
|
-
const
|
|
47872
|
-
|
|
47873
|
-
|
|
47874
|
-
|
|
47875
|
-
|
|
47876
|
-
|
|
47877
|
-
|
|
47878
|
-
|
|
47879
|
-
|
|
47880
|
-
|
|
47881
|
-
|
|
47882
|
-
|
|
47883
|
-
);
|
|
47884
|
-
}
|
|
47904
|
+
const translated = translateInclude2(parseInclude(c.req.query("include")));
|
|
47905
|
+
if (!translated.ok) {
|
|
47906
|
+
return c.json(
|
|
47907
|
+
{
|
|
47908
|
+
ok: false,
|
|
47909
|
+
error: {
|
|
47910
|
+
code: "INVALID_INCLUDE_FIELD",
|
|
47911
|
+
message: `'${translated.field}' is not a valid relation field`
|
|
47912
|
+
}
|
|
47913
|
+
},
|
|
47914
|
+
400
|
|
47915
|
+
);
|
|
47885
47916
|
}
|
|
47917
|
+
const include = translated.include;
|
|
47886
47918
|
const item = await repo.findBySlug(slug, include);
|
|
47887
47919
|
if (!item || !isPublished(item)) {
|
|
47888
47920
|
return c.json(
|
|
@@ -47893,15 +47925,15 @@ function registerPublicContentRoutes(app, registry2, repos, projectors, paths, l
|
|
|
47893
47925
|
404
|
|
47894
47926
|
);
|
|
47895
47927
|
}
|
|
47896
|
-
|
|
47897
|
-
if (resolver?.hasSchema(typeName)) data = await resolver.resolveItem(typeName, data);
|
|
47928
|
+
const data = await respondItem(item, typeName, programmatic);
|
|
47898
47929
|
return c.json({ ok: true, data });
|
|
47899
47930
|
});
|
|
47900
47931
|
}
|
|
47901
47932
|
}
|
|
47902
|
-
for (const [typeName] of Object.entries(registry2.taxonomy_types)) {
|
|
47933
|
+
for (const [typeName, taxonomyType] of Object.entries(registry2.taxonomy_types)) {
|
|
47903
47934
|
const repo = repos[typeName];
|
|
47904
47935
|
if (!repo) continue;
|
|
47936
|
+
const programmatic = taxonomyType.fields.filter((f) => f.field_type === "programmatic").map((f) => f.name);
|
|
47905
47937
|
registerListRoute(paths.taxonomyCollection(typeName), async (c) => {
|
|
47906
47938
|
const pagination = parsePagination(c.req.query("page"), c.req.query("per_page"));
|
|
47907
47939
|
if (!pagination.ok) {
|
|
@@ -47921,10 +47953,7 @@ function registerPublicContentRoutes(app, registry2, repos, projectors, paths, l
|
|
|
47921
47953
|
page: pagination.page,
|
|
47922
47954
|
per_page: pagination.per_page
|
|
47923
47955
|
});
|
|
47924
|
-
const
|
|
47925
|
-
(row) => projectRow(row, typeName, projectors)
|
|
47926
|
-
);
|
|
47927
|
-
const data = resolver?.hasSchema(typeName) ? await resolver.resolveList(typeName, labeled) : labeled;
|
|
47956
|
+
const data = await respondList(result.data, typeName, programmatic);
|
|
47928
47957
|
return c.json({ ...result, data });
|
|
47929
47958
|
});
|
|
47930
47959
|
app.get(paths.taxonomyItem(typeName), async (c) => {
|
|
@@ -47939,8 +47968,7 @@ function registerPublicContentRoutes(app, registry2, repos, projectors, paths, l
|
|
|
47939
47968
|
404
|
|
47940
47969
|
);
|
|
47941
47970
|
}
|
|
47942
|
-
|
|
47943
|
-
if (resolver?.hasSchema(typeName)) data = await resolver.resolveItem(typeName, data);
|
|
47971
|
+
const data = await respondItem(item, typeName, programmatic);
|
|
47944
47972
|
return c.json({ ok: true, data });
|
|
47945
47973
|
});
|
|
47946
47974
|
}
|
|
@@ -49702,7 +49730,7 @@ function registerUserRoutes(app, db, requirePermission, requireHierarchy) {
|
|
|
49702
49730
|
}
|
|
49703
49731
|
var API_VERSION = (() => {
|
|
49704
49732
|
try {
|
|
49705
|
-
return "0.
|
|
49733
|
+
return "0.7.0";
|
|
49706
49734
|
} catch {
|
|
49707
49735
|
return "0.0.0";
|
|
49708
49736
|
}
|
|
@@ -50277,20 +50305,6 @@ function createCmsApp(options) {
|
|
|
50277
50305
|
sortableColumns
|
|
50278
50306
|
});
|
|
50279
50307
|
};
|
|
50280
|
-
const graphqlRepos = Object.fromEntries([
|
|
50281
|
-
...Object.entries(registry2.content_types).map(([typeName, ct2]) => [
|
|
50282
|
-
typeName,
|
|
50283
|
-
createDrizzleContentRepository(db, ct2.db.table_name, {
|
|
50284
|
-
sortableColumns: sortableColumnsFor(typeName)
|
|
50285
|
-
})
|
|
50286
|
-
]),
|
|
50287
|
-
...Object.entries(registry2.taxonomy_types).map(([typeName, tt2]) => [
|
|
50288
|
-
typeName,
|
|
50289
|
-
createDrizzleContentRepository(db, tt2.db.table_name, {
|
|
50290
|
-
sortableColumns: sortableColumnsFor(typeName)
|
|
50291
|
-
})
|
|
50292
|
-
])
|
|
50293
|
-
]);
|
|
50294
50308
|
registerAuthRoutes(app, db);
|
|
50295
50309
|
app.use("/admin/api/*", authMiddleware);
|
|
50296
50310
|
app.use("/admin/api/*", mustChangePasswordCheck);
|
|
@@ -50357,7 +50371,7 @@ function createCmsApp(options) {
|
|
|
50357
50371
|
app.use(path7, attachDeprecationHeaders);
|
|
50358
50372
|
}
|
|
50359
50373
|
}
|
|
50360
|
-
registerPublicContentRoutes(app, registry2, surface.repos, surface.projectors, surface.paths, listRateLimit, programmaticResolver);
|
|
50374
|
+
registerPublicContentRoutes(app, registry2, surface.repos, surface.projectors, surface.paths, listRateLimit, programmaticResolver, projectors);
|
|
50361
50375
|
}
|
|
50362
50376
|
if (options.versions !== void 0) {
|
|
50363
50377
|
app.all(`${prefix}/:version/*`, async (c, next) => {
|
|
@@ -50388,31 +50402,108 @@ function createCmsApp(options) {
|
|
|
50388
50402
|
registerPublicMediaRoutes(app, mediaRepo, publicPaths, listRateLimit);
|
|
50389
50403
|
if (options.graphql?.enabled) {
|
|
50390
50404
|
const gqlOptions = options.graphql;
|
|
50391
|
-
|
|
50392
|
-
|
|
50393
|
-
|
|
50394
|
-
|
|
50405
|
+
const makeGraphqlRepo = (_typeName, tableName, sortableColumns) => createDrizzleContentRepository(db, tableName, { sortableColumns });
|
|
50406
|
+
const gqlPasses = [
|
|
50407
|
+
...options.versions !== void 0 ? model.live.map((v2) => ({ version: v2, projectionVersion: v2 })) : [],
|
|
50408
|
+
{ version: null, projectionVersion: model.current }
|
|
50409
|
+
];
|
|
50410
|
+
const mounts = gqlPasses.map((pass) => ({
|
|
50411
|
+
path: pass.version === null ? "/graphql" : `/graphql/${pass.version}`,
|
|
50412
|
+
version: pass.version,
|
|
50413
|
+
handler: null,
|
|
50414
|
+
error: null
|
|
50415
|
+
}));
|
|
50416
|
+
const ready = import("./handler-GED3I7Z2-HZAD77OI.js").then(({ createGraphQLHandler }) => {
|
|
50417
|
+
gqlPasses.forEach((pass, i) => {
|
|
50418
|
+
const mount = mounts[i];
|
|
50419
|
+
try {
|
|
50420
|
+
const surface = buildVersionSurface({
|
|
50421
|
+
...pass,
|
|
50422
|
+
prefix,
|
|
50423
|
+
registry: registry2,
|
|
50424
|
+
model,
|
|
50425
|
+
makeRepo: makeGraphqlRepo
|
|
50426
|
+
});
|
|
50427
|
+
const projection = model.projections[pass.projectionVersion];
|
|
50428
|
+
const currentProjection = model.projections[model.current];
|
|
50429
|
+
mount.handler = createGraphQLHandler(
|
|
50430
|
+
registry2,
|
|
50431
|
+
surface.repos,
|
|
50432
|
+
surface.fieldKeyMaps,
|
|
50433
|
+
programmaticResolver,
|
|
50434
|
+
db,
|
|
50435
|
+
gqlOptions,
|
|
50436
|
+
{
|
|
50437
|
+
endpoint: mount.path,
|
|
50438
|
+
currentVersion: model.current,
|
|
50439
|
+
...projection !== void 0 && { projection },
|
|
50440
|
+
...currentProjection !== void 0 && { currentProjection },
|
|
50441
|
+
currentFieldKeyMaps: fieldKeyMaps
|
|
50442
|
+
}
|
|
50443
|
+
);
|
|
50444
|
+
} catch (err) {
|
|
50445
|
+
mount.error = err;
|
|
50446
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
50447
|
+
process.stderr.write(
|
|
50448
|
+
`\u2717 GraphQL schema failed to initialize for ${mount.path}; it will return 500. ${message}
|
|
50449
|
+
`
|
|
50450
|
+
);
|
|
50451
|
+
}
|
|
50452
|
+
});
|
|
50395
50453
|
}).catch((err) => {
|
|
50396
|
-
|
|
50454
|
+
for (const m2 of mounts) m2.error = err;
|
|
50397
50455
|
const message = err instanceof Error ? err.message : String(err);
|
|
50398
|
-
|
|
50456
|
+
const paths = mounts.map((m2) => m2.path).join(", ");
|
|
50457
|
+
process.stderr.write(`\u2717 GraphQL module failed to load; ${paths} will return 500. ${message}
|
|
50399
50458
|
`);
|
|
50400
50459
|
});
|
|
50401
|
-
const
|
|
50402
|
-
if (!
|
|
50403
|
-
if (!
|
|
50460
|
+
const invokeFor = (mount) => async (c) => {
|
|
50461
|
+
if (!mount.handler && !mount.error) await ready;
|
|
50462
|
+
if (!mount.handler) {
|
|
50404
50463
|
return c.json(
|
|
50405
50464
|
{ ok: false, error: { code: "GRAPHQL_INIT_FAILED", message: "GraphQL schema failed to initialize" } },
|
|
50406
50465
|
500
|
|
50407
50466
|
);
|
|
50408
50467
|
}
|
|
50409
|
-
return
|
|
50468
|
+
return mount.handler(c, async () => {
|
|
50410
50469
|
});
|
|
50411
50470
|
};
|
|
50412
|
-
|
|
50413
|
-
|
|
50414
|
-
|
|
50415
|
-
|
|
50471
|
+
for (const mount of mounts) {
|
|
50472
|
+
const headers = deprecationHeaders({
|
|
50473
|
+
requested: mount.version,
|
|
50474
|
+
model,
|
|
50475
|
+
successor: `/graphql/${model.current}`
|
|
50476
|
+
});
|
|
50477
|
+
if (headers === null) continue;
|
|
50478
|
+
const attach = async (c, next) => {
|
|
50479
|
+
await next();
|
|
50480
|
+
for (const [key, value] of Object.entries(headers)) c.res.headers.set(key, value);
|
|
50481
|
+
};
|
|
50482
|
+
app.use(mount.path, attach);
|
|
50483
|
+
}
|
|
50484
|
+
for (const mount of mounts) {
|
|
50485
|
+
if (listRateLimit) app.all(mount.path, listRateLimit, invokeFor(mount));
|
|
50486
|
+
else app.all(mount.path, invokeFor(mount));
|
|
50487
|
+
}
|
|
50488
|
+
if (options.versions !== void 0) {
|
|
50489
|
+
app.all("/graphql/:version", async (c, next) => {
|
|
50490
|
+
const segment = c.req.param("version");
|
|
50491
|
+
const kind = classifyVersion(segment, model);
|
|
50492
|
+
if (kind === "not-a-version" || kind === "live") return next();
|
|
50493
|
+
const live = model.live.join(", ");
|
|
50494
|
+
return c.json({
|
|
50495
|
+
errors: [
|
|
50496
|
+
{
|
|
50497
|
+
message: kind === "retired" ? `Version ${segment} is no longer served. Live versions: ${live}.` : `Version ${segment} does not exist. Live versions: ${live}.`,
|
|
50498
|
+
extensions: {
|
|
50499
|
+
code: kind === "retired" ? "VERSION_RETIRED" : "VERSION_UNKNOWN",
|
|
50500
|
+
current: model.current,
|
|
50501
|
+
live: model.live
|
|
50502
|
+
}
|
|
50503
|
+
}
|
|
50504
|
+
]
|
|
50505
|
+
});
|
|
50506
|
+
});
|
|
50416
50507
|
}
|
|
50417
50508
|
}
|
|
50418
50509
|
registerConfigRoute(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobbykim/manguito-cms-cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Bobby Kim <bobby.sihun.kim@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/bobbykim89/manguito-cms",
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"tsup": "^8.5.1",
|
|
30
30
|
"typescript": "^6.0.3",
|
|
31
31
|
"vite": "^8.1.3",
|
|
32
|
-
"@bobbykim/manguito-cms-admin": "0.4.
|
|
33
|
-
"@bobbykim/manguito-cms-core": "0.
|
|
34
|
-
"@bobbykim/manguito-cms-
|
|
35
|
-
"@bobbykim/manguito-cms-
|
|
32
|
+
"@bobbykim/manguito-cms-admin": "0.4.3",
|
|
33
|
+
"@bobbykim/manguito-cms-core": "0.6.0",
|
|
34
|
+
"@bobbykim/manguito-cms-api": "0.7.0",
|
|
35
|
+
"@bobbykim/manguito-cms-db": "0.1.6"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^25.9.5",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"scripts": {
|
|
43
43
|
"build": "tsup",
|
|
44
44
|
"dev": "tsup --watch",
|
|
45
|
-
"test": "dotenv -e
|
|
45
|
+
"test": "dotenv -e ../../.env.test -- vitest run",
|
|
46
46
|
"lint": "eslint src",
|
|
47
47
|
"typecheck": "tsc --noEmit"
|
|
48
48
|
}
|