@bobbykim/manguito-cms-api 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  persistParagraphField,
9
9
  resolveRelationBareIds,
10
10
  resolveRelationField
11
- } from "./chunk-D5AO4BTL.mjs";
11
+ } from "./chunk-JVP33FI2.mjs";
12
12
 
13
13
  // src/paths.ts
14
14
  function normalizePrefix(prefix) {
@@ -102,7 +102,7 @@ function createSecurityHeadersMiddleware(options = {}) {
102
102
  c.res.headers.set("X-Content-Type-Options", "nosniff");
103
103
  c.res.headers.set("X-Frame-Options", "DENY");
104
104
  c.res.headers.set("Referrer-Policy", "no-referrer");
105
- const isGraphiql = graphiqlPath !== void 0 && c.req.path === graphiqlPath;
105
+ const isGraphiql = graphiqlPath !== void 0 && (c.req.path === graphiqlPath || c.req.path.startsWith(`${graphiqlPath}/`));
106
106
  c.res.headers.set("Content-Security-Policy", isGraphiql ? graphiqlCsp : csp);
107
107
  };
108
108
  }
@@ -2733,7 +2733,7 @@ function registerUserRoutes(app, db, requirePermission, requireHierarchy) {
2733
2733
  import { sql as sql5 } from "drizzle-orm";
2734
2734
  var API_VERSION = (() => {
2735
2735
  try {
2736
- return "0.5.0";
2736
+ return "0.6.0";
2737
2737
  } catch {
2738
2738
  return "0.0.0";
2739
2739
  }
@@ -3323,20 +3323,6 @@ function createCmsApp(options) {
3323
3323
  sortableColumns
3324
3324
  });
3325
3325
  };
3326
- const graphqlRepos = Object.fromEntries([
3327
- ...Object.entries(registry.content_types).map(([typeName, ct]) => [
3328
- typeName,
3329
- createDrizzleContentRepository(db, ct.db.table_name, {
3330
- sortableColumns: sortableColumnsFor(typeName)
3331
- })
3332
- ]),
3333
- ...Object.entries(registry.taxonomy_types).map(([typeName, tt]) => [
3334
- typeName,
3335
- createDrizzleContentRepository(db, tt.db.table_name, {
3336
- sortableColumns: sortableColumnsFor(typeName)
3337
- })
3338
- ])
3339
- ]);
3340
3326
  registerAuthRoutes(app, db);
3341
3327
  app.use("/admin/api/*", authMiddleware);
3342
3328
  app.use("/admin/api/*", mustChangePasswordCheck);
@@ -3434,31 +3420,107 @@ function createCmsApp(options) {
3434
3420
  registerPublicMediaRoutes(app, mediaRepo, publicPaths, listRateLimit);
3435
3421
  if (options.graphql?.enabled) {
3436
3422
  const gqlOptions = options.graphql;
3437
- let gqlHandler = null;
3438
- let initError = null;
3439
- const ready = import("./handler-X7JDHJAL.mjs").then(({ createGraphQLHandler }) => {
3440
- gqlHandler = createGraphQLHandler(registry, graphqlRepos, fieldKeyMaps, programmaticResolver, db, gqlOptions);
3423
+ const makeGraphqlRepo = (_typeName, tableName, sortableColumns) => createDrizzleContentRepository(db, tableName, { sortableColumns });
3424
+ const gqlPasses = [
3425
+ ...options.versions !== void 0 ? model.live.map((v) => ({ version: v, projectionVersion: v })) : [],
3426
+ { version: null, projectionVersion: model.current }
3427
+ ];
3428
+ const mounts = gqlPasses.map((pass) => ({
3429
+ path: pass.version === null ? "/graphql" : `/graphql/${pass.version}`,
3430
+ version: pass.version,
3431
+ handler: null,
3432
+ error: null
3433
+ }));
3434
+ const ready = import("./handler-XZVDLKZ2.mjs").then(({ createGraphQLHandler }) => {
3435
+ gqlPasses.forEach((pass, i) => {
3436
+ const mount = mounts[i];
3437
+ try {
3438
+ const surface = buildVersionSurface({
3439
+ ...pass,
3440
+ prefix,
3441
+ registry,
3442
+ model,
3443
+ makeRepo: makeGraphqlRepo
3444
+ });
3445
+ const projection = model.projections[pass.projectionVersion];
3446
+ const currentProjection = model.projections[model.current];
3447
+ mount.handler = createGraphQLHandler(
3448
+ registry,
3449
+ surface.repos,
3450
+ surface.fieldKeyMaps,
3451
+ programmaticResolver,
3452
+ db,
3453
+ gqlOptions,
3454
+ {
3455
+ endpoint: mount.path,
3456
+ currentVersion: model.current,
3457
+ ...projection !== void 0 && { projection },
3458
+ ...currentProjection !== void 0 && { currentProjection }
3459
+ }
3460
+ );
3461
+ } catch (err) {
3462
+ mount.error = err;
3463
+ const message = err instanceof Error ? err.message : String(err);
3464
+ process.stderr.write(
3465
+ `\u2717 GraphQL schema failed to initialize for ${mount.path}; it will return 500. ${message}
3466
+ `
3467
+ );
3468
+ }
3469
+ });
3441
3470
  }).catch((err) => {
3442
- initError = err;
3471
+ for (const m of mounts) m.error = err;
3443
3472
  const message = err instanceof Error ? err.message : String(err);
3444
- process.stderr.write(`\u2717 GraphQL schema failed to initialize; /graphql will return 500. ${message}
3473
+ const paths = mounts.map((m) => m.path).join(", ");
3474
+ process.stderr.write(`\u2717 GraphQL module failed to load; ${paths} will return 500. ${message}
3445
3475
  `);
3446
3476
  });
3447
- const invokeGraphQL = async (c) => {
3448
- if (!gqlHandler && !initError) await ready;
3449
- if (!gqlHandler) {
3477
+ const invokeFor = (mount) => async (c) => {
3478
+ if (!mount.handler && !mount.error) await ready;
3479
+ if (!mount.handler) {
3450
3480
  return c.json(
3451
3481
  { ok: false, error: { code: "GRAPHQL_INIT_FAILED", message: "GraphQL schema failed to initialize" } },
3452
3482
  500
3453
3483
  );
3454
3484
  }
3455
- return gqlHandler(c, async () => {
3485
+ return mount.handler(c, async () => {
3456
3486
  });
3457
3487
  };
3458
- if (listRateLimit) {
3459
- app.all("/graphql", listRateLimit, invokeGraphQL);
3460
- } else {
3461
- app.all("/graphql", invokeGraphQL);
3488
+ for (const mount of mounts) {
3489
+ const headers = deprecationHeaders({
3490
+ requested: mount.version,
3491
+ model,
3492
+ successor: `/graphql/${model.current}`
3493
+ });
3494
+ if (headers === null) continue;
3495
+ const attach = async (c, next) => {
3496
+ await next();
3497
+ for (const [key, value] of Object.entries(headers)) c.res.headers.set(key, value);
3498
+ };
3499
+ app.use(mount.path, attach);
3500
+ }
3501
+ for (const mount of mounts) {
3502
+ if (listRateLimit) app.all(mount.path, listRateLimit, invokeFor(mount));
3503
+ else app.all(mount.path, invokeFor(mount));
3504
+ }
3505
+ if (options.versions !== void 0) {
3506
+ app.all("/graphql/:version", async (c, next) => {
3507
+ const segment = c.req.param("version");
3508
+ const kind = classifyVersion(segment, model);
3509
+ if (kind === "not-a-version" || kind === "live") return next();
3510
+ const live = model.live.join(", ");
3511
+ return c.json({
3512
+ errors: [
3513
+ {
3514
+ message: kind === "retired" ? `Version ${segment} is no longer served. Live versions: ${live}.` : `Version ${segment} does not exist. Live versions: ${live}.`,
3515
+ extensions: {
3516
+ code: kind === "retired" ? "VERSION_RETIRED" : "VERSION_UNKNOWN",
3517
+ current: model.current,
3518
+ live: model.live
3519
+ }
3520
+ }
3521
+ ]
3522
+ });
3523
+ });
3462
3524
  }
3463
3525
  }
3464
3526
  registerConfigRoute(