@llmops/app 0.1.7 → 0.1.9-beta.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.
Files changed (115) hide show
  1. package/dist/.vite/manifest.json +285 -366
  2. package/dist/assets/Form-DHA5ZPmK.js +1 -0
  3. package/dist/assets/_environment-Bj632BW3.js +1 -0
  4. package/dist/assets/_observability-Bsw31e8i.js +1 -0
  5. package/dist/assets/_settings-MuCcKpRb.js +1 -0
  6. package/dist/assets/{_tabs-DaucGqpx.js → _tabs-DR5WY23M.js} +1 -1
  7. package/dist/assets/{_tabs-D9USU0yw.js → _tabs-Osf37WI9.js} +1 -1
  8. package/dist/assets/_variant-DGrwitKk.js +30 -0
  9. package/dist/assets/{_variants-Bjp8ZEvO.js → _variants-C7fc4T8_.js} +1 -1
  10. package/dist/assets/{area.css-CSjofvHM.js → area.css-ByjMFuMe.js} +1 -1
  11. package/dist/assets/auth-BkNQi67-.css +1 -0
  12. package/dist/assets/auth.css-CbKu-iME.js +1 -0
  13. package/dist/assets/button-J5fxAIyE.js +1 -0
  14. package/dist/assets/check-BdOT-uCr.js +1 -0
  15. package/dist/assets/{chevron-right-fMWRsRLZ.js → chevron-right-CcvZen9O.js} +1 -1
  16. package/dist/assets/combobox-BKEpKROu.js +1 -0
  17. package/dist/assets/configs-BEKTOPIS.js +1 -0
  18. package/dist/assets/{copy-DADLeZ69.js → copy-Btrg1ewH.js} +1 -1
  19. package/dist/assets/{costs-Fh0OPnEw.js → costs-C0sD1amq.js} +1 -1
  20. package/dist/assets/environments-CZ6PX9PA.js +1 -0
  21. package/dist/assets/index-C1Qc7Z7W.js +27 -0
  22. package/dist/assets/index-C8Gwa2Ui.js +1 -0
  23. package/dist/assets/{index-DeuSY0Yv.js → index-CAScpK2G.js} +1 -1
  24. package/dist/assets/{index-DW-cTzEh.js → index-CPQ3xdGh.js} +1 -1
  25. package/dist/assets/index-CPokRl9v.js +1 -0
  26. package/dist/assets/index-CQALuvff.js +1 -0
  27. package/dist/assets/{index-BFe2NM3q.css → index-CgbnU9Zg.css} +1 -1
  28. package/dist/assets/{index-Cns5MLjo.js → index-ChLdrp-m.js} +1 -1
  29. package/dist/assets/{index.esm-oCSEvUVx.js → index.esm-BVbruXk6.js} +1 -1
  30. package/dist/assets/info-box.css-BzqwxgQm.js +1 -0
  31. package/dist/assets/logo-D4ybjOzp.css +1 -0
  32. package/dist/assets/logo.css-BHDDnlVa.js +1 -0
  33. package/dist/assets/new-config-state-B8sMe-TC.css +1 -0
  34. package/dist/assets/new-config-state.css-DccH1TI0.js +1 -0
  35. package/dist/assets/{observability.css-wgjHtY3p.js → observability.css-D5kKsJ4z.js} +1 -1
  36. package/dist/assets/{overview-D1QIYPBL.js → overview-Czui5UTZ.js} +5 -5
  37. package/dist/assets/plus-DqiZvCBU.js +1 -0
  38. package/dist/assets/popover-BndR7yWD.js +1 -0
  39. package/dist/assets/requests-DrSJLtrE.js +1 -0
  40. package/dist/assets/{route-Df57lqxl.js → route-22shZRiS.js} +1 -1
  41. package/dist/assets/route-7Tn2yELm.js +1 -0
  42. package/dist/assets/{route-CjAw8hSU.js → route-CqIm0KnA.js} +1 -1
  43. package/dist/assets/{route-timDYxX2.js → route-D_QnUz7-.js} +1 -1
  44. package/dist/assets/{route-DmWZbVk6.js → route-DwYQMwtZ.js} +1 -1
  45. package/dist/assets/secrets-DnWQ2F0V.js +1 -0
  46. package/dist/assets/settings-c6c9IYPa.js +1 -0
  47. package/dist/assets/settings-sisslKb5.js +1 -0
  48. package/dist/assets/setup-G_oS-RU-.js +1 -0
  49. package/dist/assets/signin-B-qadLup.js +1 -0
  50. package/dist/assets/table-jMzD3FNy.js +1 -0
  51. package/dist/assets/{tabs.css-CG5ugi0p.js → tabs.css-CkcP1Ksc.js} +1 -1
  52. package/dist/assets/targeting-CaE84Lx8.js +1 -0
  53. package/dist/assets/tooltip-BiUUXiGj.js +1 -0
  54. package/dist/assets/{update-or-create-name-B-M46wHl.js → update-or-create-name-DGt2MGEI.js} +1 -1
  55. package/dist/assets/useAnalytics-CHDelHQa.js +1 -0
  56. package/dist/assets/useConfigList-Bx9xKceA.js +1 -0
  57. package/dist/assets/{useConfigVariants-CLc_hPw1.js → useConfigVariants-CB0S5gfJ.js} +1 -1
  58. package/dist/assets/useEnvironments-DILRhv_b.js +1 -0
  59. package/dist/assets/{useMutation-D4JglXWk.js → useMutation-CNzYa4ST.js} +1 -1
  60. package/dist/assets/usePopupAutoResize-CaO9EPHk.js +1 -0
  61. package/dist/assets/{useSetTargeting-bk0Ixhqq.js → useSetTargeting-DY3jI95T.js} +1 -1
  62. package/dist/assets/useTargetingRules-D10mXxut.js +1 -0
  63. package/dist/assets/useValueChanged-8LsiEynk.js +1 -0
  64. package/dist/assets/{user-profile-BB3dPOc5.js → user-profile-8xq1f7_D.js} +1 -1
  65. package/dist/assets/variants-rQQlpgeF.js +1 -0
  66. package/dist/assets/variants.css-Dzb38Nu1.js +1 -0
  67. package/dist/assets/{workspace-general-DYXfOF9H.js → workspace-general-dH65Sm8D.js} +1 -1
  68. package/dist/index.cjs +136 -66
  69. package/dist/index.d.cts +8 -5
  70. package/dist/index.d.mts +8 -5
  71. package/dist/index.mjs +138 -68
  72. package/package.json +4 -3
  73. package/dist/assets/Form-Bh6BPtQ_.js +0 -1
  74. package/dist/assets/InternalBackdrop-Za9lpJi7.js +0 -12
  75. package/dist/assets/_environment-COxSWJ9w.js +0 -1
  76. package/dist/assets/_observability-C8wSXZk2.js +0 -1
  77. package/dist/assets/_settings-DOmj1R7I.js +0 -1
  78. package/dist/assets/_variant-DxME2BL0.js +0 -30
  79. package/dist/assets/button-CMZqhyXB.js +0 -1
  80. package/dist/assets/check-D9E8RKB4.js +0 -1
  81. package/dist/assets/chevron-down-BJFxhYkh.js +0 -1
  82. package/dist/assets/combobox-iSbUYz0A.js +0 -1
  83. package/dist/assets/configs-BflhBVlY.js +0 -1
  84. package/dist/assets/environments-ChldQPyq.js +0 -1
  85. package/dist/assets/getDisabledMountTransitionStyles-TZFYxPIU.js +0 -1
  86. package/dist/assets/index-BDsrc1Q7.js +0 -1
  87. package/dist/assets/index-BWU02PnY.js +0 -1
  88. package/dist/assets/index-DYoud8po.js +0 -1
  89. package/dist/assets/index-FrTQ7TcS.js +0 -16
  90. package/dist/assets/info-box.css-DuVI9M9-.js +0 -1
  91. package/dist/assets/llmops-B3IIte87.css +0 -1
  92. package/dist/assets/llmops-CdOQq40D.js +0 -1
  93. package/dist/assets/plus-JQ0TORpd.js +0 -1
  94. package/dist/assets/popover-DXj4s-ni.js +0 -1
  95. package/dist/assets/popupStateMapping-DolkyTT3.js +0 -1
  96. package/dist/assets/requests-CzvYwfwV.js +0 -1
  97. package/dist/assets/reselect-DVmmTZGf.js +0 -1
  98. package/dist/assets/secrets-BxFGEuKj.js +0 -1
  99. package/dist/assets/settings-DpSRw7LL.js +0 -1
  100. package/dist/assets/settings-pgWZnVf6.js +0 -1
  101. package/dist/assets/table-DggTSlPh.js +0 -1
  102. package/dist/assets/targeting-CkqRTjnZ.js +0 -1
  103. package/dist/assets/tooltip-BuSsMQ8P.js +0 -1
  104. package/dist/assets/useAnalytics-DTf81POS.js +0 -1
  105. package/dist/assets/useButton-CsZ8hBM8.js +0 -1
  106. package/dist/assets/useConfigList-CAf01_dV.js +0 -1
  107. package/dist/assets/useEnvironments-Bu_0SIUj.js +0 -1
  108. package/dist/assets/useFocus-9TCY0h5x.js +0 -1
  109. package/dist/assets/usePopupAutoResize-D6RSlB-m.js +0 -1
  110. package/dist/assets/useRole-CiSaVva3.js +0 -1
  111. package/dist/assets/useSyncedFloatingRootContext-BKbVh8Gq.js +0 -1
  112. package/dist/assets/useTargetingRules-BrgaEdxR.js +0 -1
  113. package/dist/assets/useValueChanged-CTjBqaGs.js +0 -1
  114. package/dist/assets/variants-BH682hHM.js +0 -1
  115. package/dist/assets/variants.css-rCWHZycz.js +0 -1
package/dist/index.cjs CHANGED
@@ -51,19 +51,19 @@ let hono_serve_static = require("hono/serve-static");
51
51
  let url = require("url");
52
52
  let path = require("path");
53
53
  let fs_promises = require("fs/promises");
54
- let hono_basic_auth = require("hono/basic-auth");
54
+ let hono_http_exception = require("hono/http-exception");
55
55
  let __hono_zod_validator = require("@hono/zod-validator");
56
56
  let hono_pretty_json = require("hono/pretty-json");
57
- let hono_http_exception = require("hono/http-exception");
58
57
  let hono_cors = require("hono/cors");
59
58
  let node_crypto = require("node:crypto");
60
59
  let __llmops_gateway = require("@llmops/gateway");
61
60
  __llmops_gateway = __toESM(__llmops_gateway);
62
61
  let node_process = require("node:process");
63
62
  let __llmops_core_db = require("@llmops/core/db");
63
+ let better_auth = require("better-auth");
64
64
 
65
65
  //#region src/client/index.tsx?url
66
- var client_default = "/assets/index-FrTQ7TcS.js";
66
+ var client_default = "/assets/index-C1Qc7Z7W.js";
67
67
 
68
68
  //#endregion
69
69
  //#region src/client/styles/styles.css?url
@@ -94,7 +94,7 @@ const ReactRefresh = () => {
94
94
  const { renderToString } = react_dom_server.default;
95
95
  const manifestPath = (0, node_path.join)((0, node_path.dirname)((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href)), "./.vite/manifest.json");
96
96
  const manifest = (0, node_fs.existsSync)(manifestPath) ? JSON.parse((0, node_fs.readFileSync)(manifestPath, "utf-8")) : {};
97
- const renderer = ({ basePath = "", dev = false, llmProviders, authType }) => {
97
+ const renderer = ({ basePath = "", dev = false, llmProviders, authType, setupComplete = false }) => {
98
98
  const stylesPath = basePath === "/" ? styles_default : basePath + styles_default;
99
99
  const clientPath = basePath === "/" ? client_default : basePath + client_default;
100
100
  const faviconPath = basePath === "/" ? "/favicon.ico" : basePath + "/assets/favicon.ico";
@@ -103,7 +103,7 @@ const renderer = ({ basePath = "", dev = false, llmProviders, authType }) => {
103
103
  });
104
104
  return renderToString(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("html", {
105
105
  lang: "en",
106
- className: "dark",
106
+ className: "",
107
107
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("head", { children: [
108
108
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("meta", {
109
109
  name: "viewport",
@@ -358,7 +358,8 @@ const renderer = ({ basePath = "", dev = false, llmProviders, authType }) => {
358
358
  window.bootstrapData = {
359
359
  basePath: "${basePath}",
360
360
  llmProviders: ${JSON.stringify(llmProviders || [])},
361
- authType: "${authType || "basic"}"
361
+ authType: "${authType || "basic"}",
362
+ setupComplete: ${setupComplete}
362
363
  };
363
364
  ` }),
364
365
  dev && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReactRefresh, {})
@@ -12815,7 +12816,7 @@ function parseTags(tagsJson) {
12815
12816
  /**
12816
12817
  * Analytics API routes for cost and usage tracking
12817
12818
  */
12818
- const app$10 = new hono.Hono().get("/requests", zv("query", zod_default.object({
12819
+ const app$11 = new hono.Hono().get("/requests", zv("query", zod_default.object({
12819
12820
  limit: zod_default.string().transform(Number).optional(),
12820
12821
  offset: zod_default.string().transform(Number).optional(),
12821
12822
  configId: zod_default.string().uuid().optional(),
@@ -12829,13 +12830,6 @@ const app$10 = new hono.Hono().get("/requests", zv("query", zod_default.object({
12829
12830
  })), async (c) => {
12830
12831
  const db = c.get("db");
12831
12832
  const query = c.req.valid("query");
12832
- console.log("[Analytics] Request filters:", {
12833
- configId: query.configId,
12834
- variantId: query.variantId,
12835
- environmentId: query.environmentId,
12836
- startDate: query.startDate,
12837
- endDate: query.endDate
12838
- });
12839
12833
  let parsedTags;
12840
12834
  if (query.tags) try {
12841
12835
  parsedTags = JSON.parse(query.tags);
@@ -13017,11 +13011,11 @@ const app$10 = new hono.Hono().get("/requests", zv("query", zod_default.object({
13017
13011
  return c.json(internalServerError("Failed to fetch tags", 500), 500);
13018
13012
  }
13019
13013
  });
13020
- var analytics_default = app$10;
13014
+ var analytics_default = app$11;
13021
13015
 
13022
13016
  //#endregion
13023
13017
  //#region src/server/handlers/configs/index.ts
13024
- const app$9 = new hono.Hono().post("/", zv("json", zod_default.object({ name: zod_default.string().min(1) })), async (c) => {
13018
+ const app$10 = new hono.Hono().post("/", zv("json", zod_default.object({ name: zod_default.string().min(1) })), async (c) => {
13025
13019
  const db = c.get("db");
13026
13020
  try {
13027
13021
  const value = await db.createNewConfig({ name: c.req.valid("json").name });
@@ -13125,7 +13119,7 @@ const app$9 = new hono.Hono().post("/", zv("json", zod_default.object({ name: zo
13125
13119
  return c.json(internalServerError("Failed to delete config", 500), 500);
13126
13120
  }
13127
13121
  });
13128
- var configs_default = app$9;
13122
+ var configs_default = app$10;
13129
13123
 
13130
13124
  //#endregion
13131
13125
  //#region src/server/handlers/environments/index.ts
@@ -13136,7 +13130,7 @@ var configs_default = app$9;
13136
13130
  const generateSecretKey$1 = (slug) => {
13137
13131
  return `sec_${slug.slice(0, 4).toLowerCase()}_${(0, __llmops_core.generateId)(24)}`;
13138
13132
  };
13139
- const app$8 = new hono.Hono().post("/", zv("json", zod_default.object({
13133
+ const app$9 = new hono.Hono().post("/", zv("json", zod_default.object({
13140
13134
  name: zod_default.string().min(1),
13141
13135
  slug: zod_default.string().min(1),
13142
13136
  isProd: zod_default.boolean().optional()
@@ -13221,7 +13215,7 @@ const app$8 = new hono.Hono().post("/", zv("json", zod_default.object({
13221
13215
  return c.json(internalServerError("Failed to fetch environment secrets", 500), 500);
13222
13216
  }
13223
13217
  });
13224
- var environments_default = app$8;
13218
+ var environments_default = app$9;
13225
13219
 
13226
13220
  //#endregion
13227
13221
  //#region src/server/handlers/providers/index.ts
@@ -13241,7 +13235,7 @@ async function fetchModelsDevData() {
13241
13235
  cacheTimestamp = now;
13242
13236
  return modelsCache;
13243
13237
  }
13244
- const app$7 = new hono.Hono().get("/", async (c) => {
13238
+ const app$8 = new hono.Hono().get("/", async (c) => {
13245
13239
  try {
13246
13240
  const data = await fetchModelsDevData();
13247
13241
  const providers = Object.values(data).map((provider) => ({
@@ -13349,11 +13343,11 @@ const app$7 = new hono.Hono().get("/", async (c) => {
13349
13343
  return c.json(internalServerError("Failed to fetch models", 500), 500);
13350
13344
  }
13351
13345
  });
13352
- var providers_default = app$7;
13346
+ var providers_default = app$8;
13353
13347
 
13354
13348
  //#endregion
13355
13349
  //#region src/server/handlers/targeting/index.ts
13356
- const app$6 = new hono.Hono().post("/", zv("json", zod_default.object({
13350
+ const app$7 = new hono.Hono().post("/", zv("json", zod_default.object({
13357
13351
  environmentId: zod_default.string().uuid(),
13358
13352
  configId: zod_default.string().uuid(),
13359
13353
  configVariantId: zod_default.string().uuid(),
@@ -13480,11 +13474,11 @@ const app$6 = new hono.Hono().post("/", zv("json", zod_default.object({
13480
13474
  return c.json(internalServerError("Failed to set targeting for environment", 500), 500);
13481
13475
  }
13482
13476
  });
13483
- var targeting_default = app$6;
13477
+ var targeting_default = app$7;
13484
13478
 
13485
13479
  //#endregion
13486
13480
  //#region src/server/handlers/variants.ts
13487
- const app$5 = new hono.Hono().get("/:id", zv("param", zod_default.object({ id: zod_default.string().uuid() })), async (c) => {
13481
+ const app$6 = new hono.Hono().get("/:id", zv("param", zod_default.object({ id: zod_default.string().uuid() })), async (c) => {
13488
13482
  const db = c.get("db");
13489
13483
  const { id } = c.req.valid("param");
13490
13484
  const versionParam = c.req.query("version");
@@ -13631,11 +13625,43 @@ const app$5 = new hono.Hono().get("/:id", zv("param", zod_default.object({ id: z
13631
13625
  return c.json(internalServerError("Failed to fetch variant version", 500), 500);
13632
13626
  }
13633
13627
  });
13634
- var variants_default = app$5;
13628
+ var variants_default = app$6;
13629
+
13630
+ //#endregion
13631
+ //#region src/server/middlewares/verifySession.ts
13632
+ let cachedSuperAdminId = void 0;
13633
+ /**
13634
+ * Middleware that verifies the user is the super admin.
13635
+ * Must be used after the auth client middleware has set user/session in context.
13636
+ *
13637
+ * SuperAdminId is cached in memory since it's set once during setup and never changes.
13638
+ *
13639
+ * @throws HTTPException 401 if no valid session exists
13640
+ * @throws HTTPException 403 if user is not the super admin
13641
+ */
13642
+ const verifySuperAdmin = async (c, next) => {
13643
+ const user = c.get("user");
13644
+ const session = c.get("session");
13645
+ if (!user || !session) throw new hono_http_exception.HTTPException(401, { message: "Unauthorized - valid session required" });
13646
+ if (cachedSuperAdminId === void 0) cachedSuperAdminId = await c.get("db").getSuperAdminId();
13647
+ if (!cachedSuperAdminId) {
13648
+ await next();
13649
+ return;
13650
+ }
13651
+ if (user.id !== cachedSuperAdminId) throw new hono_http_exception.HTTPException(403, { message: "Forbidden - only the super admin can access this resource" });
13652
+ await next();
13653
+ };
13654
+ /**
13655
+ * Clear the cached superAdminId.
13656
+ * Call this after setting the superAdminId during setup.
13657
+ */
13658
+ const clearSuperAdminCache = () => {
13659
+ cachedSuperAdminId = void 0;
13660
+ };
13635
13661
 
13636
13662
  //#endregion
13637
13663
  //#region src/server/handlers/workspace-settings/index.ts
13638
- const app$4 = new hono.Hono().get("/", async (c) => {
13664
+ const app$5 = new hono.Hono().get("/", async (c) => {
13639
13665
  const db = c.get("db");
13640
13666
  try {
13641
13667
  const settings = await db.getWorkspaceSettings();
@@ -13644,40 +13670,28 @@ const app$4 = new hono.Hono().get("/", async (c) => {
13644
13670
  console.error("Error fetching workspace settings:", error$45);
13645
13671
  return c.json(internalServerError("Failed to fetch workspace settings", 500), 500);
13646
13672
  }
13647
- }).patch("/", zv("json", zod_default.object({ name: zod_default.string().nullable().optional() })), async (c) => {
13673
+ }).patch("/", zv("json", zod_default.object({
13674
+ name: zod_default.string().nullable().optional(),
13675
+ setupComplete: zod_default.boolean().optional(),
13676
+ superAdminId: zod_default.string().nullable().optional()
13677
+ })), async (c) => {
13648
13678
  const db = c.get("db");
13649
13679
  const body = c.req.valid("json");
13650
13680
  try {
13651
13681
  const settings = await db.updateWorkspaceSettings(body);
13682
+ if (body.superAdminId !== void 0) clearSuperAdminCache();
13652
13683
  return c.json(successResponse(settings, 200));
13653
13684
  } catch (error$45) {
13654
13685
  console.error("Error updating workspace settings:", error$45);
13655
13686
  return c.json(internalServerError("Failed to update workspace settings", 500), 500);
13656
13687
  }
13657
13688
  });
13658
- var workspace_settings_default = app$4;
13689
+ var workspace_settings_default = app$5;
13659
13690
 
13660
13691
  //#endregion
13661
13692
  //#region src/server/handlers/v1.ts
13662
- /**
13663
- * Type guard to check if auth config is basic auth
13664
- */
13665
- function isBasicAuth(auth) {
13666
- return auth.type === "basic";
13667
- }
13668
- const app$3 = new hono.Hono().use("*", async (c, next) => {
13669
- if (c.get("authHandled")) return next();
13670
- const config$1 = c.get("llmopsConfig");
13671
- if (isBasicAuth(config$1.auth)) return (0, hono_basic_auth.basicAuth)({
13672
- username: config$1.auth.defaultUser,
13673
- password: config$1.auth.defaultPassword
13674
- })(c, next);
13675
- return c.json({
13676
- error: "Auth middleware not configured",
13677
- message: `Auth type "${config$1.auth.type}" requires @llmops/enterprise middleware. Either use basicAuth() from @llmops/sdk or install @llmops/enterprise and add the auth middleware.`
13678
- }, 501);
13679
- }).route("/analytics", analytics_default).route("/configs", configs_default).route("/environments", environments_default).route("/providers", providers_default).route("/targeting", targeting_default).route("/variants", variants_default).route("/workspace-settings", workspace_settings_default);
13680
- var v1_default = app$3;
13693
+ const app$4 = new hono.Hono().use("*", verifySuperAdmin).route("/analytics", analytics_default).route("/configs", configs_default).route("/environments", environments_default).route("/providers", providers_default).route("/targeting", targeting_default).route("/variants", variants_default).route("/workspace-settings", workspace_settings_default);
13694
+ var v1_default = app$4;
13681
13695
 
13682
13696
  //#endregion
13683
13697
  //#region src/server/handlers/genai/requestValidator.ts
@@ -14376,8 +14390,8 @@ async function processUsageAndLog(params) {
14376
14390
 
14377
14391
  //#endregion
14378
14392
  //#region src/server/handlers/genai/index.ts
14379
- const app$2 = new hono.Hono();
14380
- app$2.use("*", (0, hono_pretty_json.prettyJSON)()).get("/health", async (c) => {
14393
+ const app$3 = new hono.Hono();
14394
+ app$3.use("*", (0, hono_pretty_json.prettyJSON)()).get("/health", async (c) => {
14381
14395
  return c.json({ status: "healthy" });
14382
14396
  }).use("*", requestValidator).use("*", createRequestGuardMiddleware()).use("*", createCostTrackingMiddleware()).use("*", createGatewayAdapterMiddleware()).route("/", __llmops_gateway.default).notFound((c) => c.json({ error: {
14383
14397
  message: "Not Found",
@@ -14389,12 +14403,42 @@ app$2.use("*", (0, hono_pretty_json.prettyJSON)()).get("/health", async (c) => {
14389
14403
  type: "api_error"
14390
14404
  } }, 500);
14391
14405
  });
14392
- var genai_default = app$2;
14406
+ var genai_default = app$3;
14407
+
14408
+ //#endregion
14409
+ //#region src/server/handlers/auth/index.ts
14410
+ const app$2 = new hono.Hono().post("/complete-setup", async (c) => {
14411
+ const db = c.get("db");
14412
+ try {
14413
+ const settings = await db.markSetupComplete();
14414
+ return c.json(successResponse(settings, 200));
14415
+ } catch (error$45) {
14416
+ console.error("Error completing setup:", error$45);
14417
+ return c.json(internalServerError("Failed to complete setup", 500), 500);
14418
+ }
14419
+ });
14420
+ var auth_default = app$2;
14393
14421
 
14394
14422
  //#endregion
14395
14423
  //#region src/server/handlers/api.ts
14396
14424
  const app$1 = new hono.Hono();
14397
- const routes = app$1.route("/genai", genai_default).route("/v1", v1_default);
14425
+ const routes = app$1.post("/auth/sign-up/*", async (c, next) => {
14426
+ if (c.get("setupComplete")) throw new hono_http_exception.HTTPException(403, { message: "Registration is disabled. Only one user is allowed." });
14427
+ await next();
14428
+ }).on(["POST", "GET"], "/auth/*", (c) => {
14429
+ return c.get("authClient").handler(c.req.raw);
14430
+ }).route("/auth", auth_default).use("*", async (c, next) => {
14431
+ const session = await c.get("authClient").api.getSession({ headers: c.req.raw.headers });
14432
+ if (!session) {
14433
+ c.set("user", null);
14434
+ c.set("session", null);
14435
+ await next();
14436
+ return;
14437
+ }
14438
+ c.set("user", session.user);
14439
+ c.set("session", session.session);
14440
+ await next();
14441
+ }).route("/genai", genai_default).route("/v1", v1_default);
14398
14442
  var api_default = app$1;
14399
14443
 
14400
14444
  //#endregion
@@ -14411,11 +14455,13 @@ app.use("/assets/*", (0, hono_serve_static.serveStatic)({
14411
14455
  const basePath = c.var.llmopsConfig?.basePath || "";
14412
14456
  const llmProviders = c.var.llmProviders || [];
14413
14457
  const authType = c.var.llmopsConfig?.auth?.type || "basic";
14458
+ const setupComplete = c.var.setupComplete ?? false;
14414
14459
  return c.html(renderer({
14415
14460
  basePath,
14416
14461
  dev: node_process.env.LLMOPS_DEV === "true",
14417
14462
  llmProviders,
14418
- authType
14463
+ authType,
14464
+ setupComplete
14419
14465
  }));
14420
14466
  }
14421
14467
  await next();
@@ -14488,12 +14534,10 @@ const createSeedMiddleware = () => {
14488
14534
  //#endregion
14489
14535
  //#region src/server/middlewares/migration.ts
14490
14536
  /**
14491
- * Creates a middleware that handles auto-migration based on config
14537
+ * Creates a middleware that handles auto-migration on startup
14492
14538
  *
14493
- * This middleware runs once on application startup and handles:
14494
- * - autoMigrate: true - Always run migrations
14495
- * - autoMigrate: false - Never run migrations (default)
14496
- * - autoMigrate: 'development' - Only run when NODE_ENV is 'development'
14539
+ * This middleware runs once on application startup and automatically
14540
+ * runs database migrations if needed.
14497
14541
  *
14498
14542
  * IMPORTANT: This middleware should run BEFORE the seed middleware
14499
14543
  * but AFTER the database middleware creates the connection.
@@ -14502,16 +14546,15 @@ const createMigrationMiddleware = (config$1) => {
14502
14546
  let migrationComplete = false;
14503
14547
  let migrationPromise = null;
14504
14548
  return async (c, next) => {
14505
- const autoMigrate = config$1.autoMigrate ?? false;
14506
- if (migrationComplete || autoMigrate === false) {
14549
+ if (migrationComplete) {
14507
14550
  await next();
14508
14551
  return;
14509
14552
  }
14510
14553
  if (!migrationPromise) migrationPromise = (async () => {
14511
14554
  try {
14512
- const { detectDatabaseType, runAutoMigrations, createDatabaseFromConnection: createDatabaseFromConnection$1 } = await import("@llmops/core/db");
14555
+ const { detectDatabaseType: detectDatabaseType$1, runAutoMigrations, createDatabaseFromConnection: createDatabaseFromConnection$1 } = await import("@llmops/core/db");
14513
14556
  const rawConnection = config$1.database;
14514
- const dbType = detectDatabaseType(rawConnection);
14557
+ const dbType = detectDatabaseType$1(rawConnection);
14515
14558
  if (!dbType) {
14516
14559
  console.warn("[Migration] Could not detect database type, skipping auto-migration");
14517
14560
  return;
@@ -14522,7 +14565,10 @@ const createMigrationMiddleware = (config$1) => {
14522
14565
  console.warn("[Migration] Could not create database connection, skipping auto-migration");
14523
14566
  return;
14524
14567
  }
14525
- const result = await runAutoMigrations(db, dbType, autoMigrate, { schema });
14568
+ const result = await runAutoMigrations(db, dbType, {
14569
+ rawConnection,
14570
+ schema
14571
+ });
14526
14572
  if (result.ran) console.log(`[Migration] Auto-migration completed: ${result.tables.length} table(s) created, ${result.fields.length} field(s) added`);
14527
14573
  } catch (error$45) {
14528
14574
  console.error("[Migration] Auto-migration failed:", error$45);
@@ -14535,6 +14581,24 @@ const createMigrationMiddleware = (config$1) => {
14535
14581
  };
14536
14582
  };
14537
14583
 
14584
+ //#endregion
14585
+ //#region src/server/middlewares/auth.ts
14586
+ /**
14587
+ * Creates auth client middleware that uses the pre-configured Kysely instance
14588
+ * from context. This ensures Better Auth uses the same database connection
14589
+ * with the correct schema (search_path) configuration.
14590
+ */
14591
+ const createAuthClientMiddleware = () => {
14592
+ return async (c, next) => {
14593
+ const authClient = (0, better_auth.betterAuth)((0, __llmops_core.getAuthClientOptions)({
14594
+ db: c.get("kyselyDb"),
14595
+ type: c.get("dbType")
14596
+ }));
14597
+ c.set("authClient", authClient);
14598
+ await next();
14599
+ };
14600
+ };
14601
+
14538
14602
  //#endregion
14539
14603
  //#region src/index.ts
14540
14604
  const MODELS_DEV_LOGOS = "https://models.dev/logos";
@@ -14553,10 +14617,16 @@ const setConfigMiddleware = (config$1) => {
14553
14617
  };
14554
14618
  const createDatabaseMiddleware = (validatedConfig) => {
14555
14619
  return async (c, next) => {
14556
- const db = await (0, __llmops_core_db.createDatabaseFromConnection)(validatedConfig.database, { schema: validatedConfig.schema });
14557
- if (!db) throw new Error("Failed to create database connection");
14558
- const dataLayer = await (0, __llmops_core.createDataLayer)(db);
14620
+ const kyselyDb = await (0, __llmops_core_db.createDatabaseFromConnection)(validatedConfig.database, { schema: validatedConfig.schema });
14621
+ if (!kyselyDb) throw new Error("Failed to create database connection");
14622
+ const dbType = (0, __llmops_core_db.detectDatabaseType)(validatedConfig.database);
14623
+ if (!dbType) throw new Error("Failed to detect database type");
14624
+ const dataLayer = await (0, __llmops_core.createDataLayer)(kyselyDb);
14559
14625
  c.set("db", dataLayer);
14626
+ c.set("kyselyDb", kyselyDb);
14627
+ c.set("dbType", dbType);
14628
+ const setupComplete = await dataLayer.isSetupComplete();
14629
+ c.set("setupComplete", setupComplete);
14560
14630
  await next();
14561
14631
  };
14562
14632
  };
@@ -14578,7 +14648,7 @@ const createLLMProvidersMiddleware = (config$1) => {
14578
14648
  };
14579
14649
  const createApp = (config$1) => {
14580
14650
  const validatedConfig = (0, __llmops_core.validateLLMOpsConfig)(config$1);
14581
- return { app: new hono.Hono().use("*", createEnvValidatorMiddleware()).use("*", setConfigMiddleware(validatedConfig)).use("*", createMigrationMiddleware(validatedConfig)).use("*", createDatabaseMiddleware(validatedConfig)).use("*", createSeedMiddleware()).use("*", createLLMProvidersMiddleware(validatedConfig)).route("/", server_default).basePath(validatedConfig.basePath) };
14651
+ return { app: new hono.Hono().use("*", createEnvValidatorMiddleware()).use("*", setConfigMiddleware(validatedConfig)).use("*", createMigrationMiddleware(validatedConfig)).use("*", createDatabaseMiddleware(validatedConfig)).use("*", createSeedMiddleware()).use("*", createLLMProvidersMiddleware(validatedConfig)).use("*", createAuthClientMiddleware()).route("/", server_default).basePath(validatedConfig.basePath) };
14582
14652
  };
14583
14653
  var src_default = server_default;
14584
14654
 
package/dist/index.d.cts CHANGED
@@ -1,6 +1,8 @@
1
1
  import * as hono_types1 from "hono/types";
2
2
  import * as hono_hono_base0 from "hono/hono-base";
3
3
  import { LLMOpsConfig, ValidatedLLMOpsConfig, createDataLayer } from "@llmops/core";
4
+ import { DatabaseType } from "@llmops/core/db";
5
+ import { Auth, BetterAuthOptions } from "better-auth";
4
6
  import { Hono } from "hono";
5
7
 
6
8
  //#region src/server/types.d.ts
@@ -14,11 +16,12 @@ declare module 'hono' {
14
16
  llmopsConfig: ValidatedLLMOpsConfig;
15
17
  llmProviders: LLMProvider[];
16
18
  db: Awaited<ReturnType<typeof createDataLayer>>;
17
- /**
18
- * Set to true by enterprise auth middleware to skip basic auth.
19
- * Enterprise packages should set this after successful authentication.
20
- */
21
- authHandled: boolean;
19
+ /** Raw Kysely instance with correct schema configuration */
20
+ kyselyDb: any;
21
+ /** Database type (postgres, mysql, sqlite, mssql) */
22
+ dbType: DatabaseType;
23
+ authClient: Auth<BetterAuthOptions>;
24
+ setupComplete: boolean;
22
25
  }
23
26
  }
24
27
  //#endregion
package/dist/index.d.mts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { Hono } from "hono";
2
2
  import { LLMOpsConfig, ValidatedLLMOpsConfig, createDataLayer } from "@llmops/core";
3
+ import { DatabaseType } from "@llmops/core/db";
4
+ import { Auth, BetterAuthOptions } from "better-auth";
3
5
  import * as hono_types1 from "hono/types";
4
6
  import * as hono_hono_base0 from "hono/hono-base";
5
7
 
@@ -14,11 +16,12 @@ declare module 'hono' {
14
16
  llmopsConfig: ValidatedLLMOpsConfig;
15
17
  llmProviders: LLMProvider[];
16
18
  db: Awaited<ReturnType<typeof createDataLayer>>;
17
- /**
18
- * Set to true by enterprise auth middleware to skip basic auth.
19
- * Enterprise packages should set this after successful authentication.
20
- */
21
- authHandled: boolean;
19
+ /** Raw Kysely instance with correct schema configuration */
20
+ kyselyDb: any;
21
+ /** Database type (postgres, mysql, sqlite, mssql) */
22
+ dbType: DatabaseType;
23
+ authClient: Auth<BetterAuthOptions>;
24
+ setupComplete: boolean;
22
25
  }
23
26
  }
24
27
  //#endregion