@llmops/app 0.1.8 → 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 -59
  69. package/dist/index.d.cts +8 -5
  70. package/dist/index.d.mts +8 -5
  71. package/dist/index.mjs +138 -61
  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(),
@@ -13010,11 +13011,11 @@ const app$10 = new hono.Hono().get("/requests", zv("query", zod_default.object({
13010
13011
  return c.json(internalServerError("Failed to fetch tags", 500), 500);
13011
13012
  }
13012
13013
  });
13013
- var analytics_default = app$10;
13014
+ var analytics_default = app$11;
13014
13015
 
13015
13016
  //#endregion
13016
13017
  //#region src/server/handlers/configs/index.ts
13017
- 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) => {
13018
13019
  const db = c.get("db");
13019
13020
  try {
13020
13021
  const value = await db.createNewConfig({ name: c.req.valid("json").name });
@@ -13118,7 +13119,7 @@ const app$9 = new hono.Hono().post("/", zv("json", zod_default.object({ name: zo
13118
13119
  return c.json(internalServerError("Failed to delete config", 500), 500);
13119
13120
  }
13120
13121
  });
13121
- var configs_default = app$9;
13122
+ var configs_default = app$10;
13122
13123
 
13123
13124
  //#endregion
13124
13125
  //#region src/server/handlers/environments/index.ts
@@ -13129,7 +13130,7 @@ var configs_default = app$9;
13129
13130
  const generateSecretKey$1 = (slug) => {
13130
13131
  return `sec_${slug.slice(0, 4).toLowerCase()}_${(0, __llmops_core.generateId)(24)}`;
13131
13132
  };
13132
- 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({
13133
13134
  name: zod_default.string().min(1),
13134
13135
  slug: zod_default.string().min(1),
13135
13136
  isProd: zod_default.boolean().optional()
@@ -13214,7 +13215,7 @@ const app$8 = new hono.Hono().post("/", zv("json", zod_default.object({
13214
13215
  return c.json(internalServerError("Failed to fetch environment secrets", 500), 500);
13215
13216
  }
13216
13217
  });
13217
- var environments_default = app$8;
13218
+ var environments_default = app$9;
13218
13219
 
13219
13220
  //#endregion
13220
13221
  //#region src/server/handlers/providers/index.ts
@@ -13234,7 +13235,7 @@ async function fetchModelsDevData() {
13234
13235
  cacheTimestamp = now;
13235
13236
  return modelsCache;
13236
13237
  }
13237
- const app$7 = new hono.Hono().get("/", async (c) => {
13238
+ const app$8 = new hono.Hono().get("/", async (c) => {
13238
13239
  try {
13239
13240
  const data = await fetchModelsDevData();
13240
13241
  const providers = Object.values(data).map((provider) => ({
@@ -13342,11 +13343,11 @@ const app$7 = new hono.Hono().get("/", async (c) => {
13342
13343
  return c.json(internalServerError("Failed to fetch models", 500), 500);
13343
13344
  }
13344
13345
  });
13345
- var providers_default = app$7;
13346
+ var providers_default = app$8;
13346
13347
 
13347
13348
  //#endregion
13348
13349
  //#region src/server/handlers/targeting/index.ts
13349
- 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({
13350
13351
  environmentId: zod_default.string().uuid(),
13351
13352
  configId: zod_default.string().uuid(),
13352
13353
  configVariantId: zod_default.string().uuid(),
@@ -13473,11 +13474,11 @@ const app$6 = new hono.Hono().post("/", zv("json", zod_default.object({
13473
13474
  return c.json(internalServerError("Failed to set targeting for environment", 500), 500);
13474
13475
  }
13475
13476
  });
13476
- var targeting_default = app$6;
13477
+ var targeting_default = app$7;
13477
13478
 
13478
13479
  //#endregion
13479
13480
  //#region src/server/handlers/variants.ts
13480
- 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) => {
13481
13482
  const db = c.get("db");
13482
13483
  const { id } = c.req.valid("param");
13483
13484
  const versionParam = c.req.query("version");
@@ -13624,11 +13625,43 @@ const app$5 = new hono.Hono().get("/:id", zv("param", zod_default.object({ id: z
13624
13625
  return c.json(internalServerError("Failed to fetch variant version", 500), 500);
13625
13626
  }
13626
13627
  });
13627
- 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
+ };
13628
13661
 
13629
13662
  //#endregion
13630
13663
  //#region src/server/handlers/workspace-settings/index.ts
13631
- const app$4 = new hono.Hono().get("/", async (c) => {
13664
+ const app$5 = new hono.Hono().get("/", async (c) => {
13632
13665
  const db = c.get("db");
13633
13666
  try {
13634
13667
  const settings = await db.getWorkspaceSettings();
@@ -13637,40 +13670,28 @@ const app$4 = new hono.Hono().get("/", async (c) => {
13637
13670
  console.error("Error fetching workspace settings:", error$45);
13638
13671
  return c.json(internalServerError("Failed to fetch workspace settings", 500), 500);
13639
13672
  }
13640
- }).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) => {
13641
13678
  const db = c.get("db");
13642
13679
  const body = c.req.valid("json");
13643
13680
  try {
13644
13681
  const settings = await db.updateWorkspaceSettings(body);
13682
+ if (body.superAdminId !== void 0) clearSuperAdminCache();
13645
13683
  return c.json(successResponse(settings, 200));
13646
13684
  } catch (error$45) {
13647
13685
  console.error("Error updating workspace settings:", error$45);
13648
13686
  return c.json(internalServerError("Failed to update workspace settings", 500), 500);
13649
13687
  }
13650
13688
  });
13651
- var workspace_settings_default = app$4;
13689
+ var workspace_settings_default = app$5;
13652
13690
 
13653
13691
  //#endregion
13654
13692
  //#region src/server/handlers/v1.ts
13655
- /**
13656
- * Type guard to check if auth config is basic auth
13657
- */
13658
- function isBasicAuth(auth) {
13659
- return auth.type === "basic";
13660
- }
13661
- const app$3 = new hono.Hono().use("*", async (c, next) => {
13662
- if (c.get("authHandled")) return next();
13663
- const config$1 = c.get("llmopsConfig");
13664
- if (isBasicAuth(config$1.auth)) return (0, hono_basic_auth.basicAuth)({
13665
- username: config$1.auth.defaultUser,
13666
- password: config$1.auth.defaultPassword
13667
- })(c, next);
13668
- return c.json({
13669
- error: "Auth middleware not configured",
13670
- 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.`
13671
- }, 501);
13672
- }).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);
13673
- 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;
13674
13695
 
13675
13696
  //#endregion
13676
13697
  //#region src/server/handlers/genai/requestValidator.ts
@@ -14369,8 +14390,8 @@ async function processUsageAndLog(params) {
14369
14390
 
14370
14391
  //#endregion
14371
14392
  //#region src/server/handlers/genai/index.ts
14372
- const app$2 = new hono.Hono();
14373
- 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) => {
14374
14395
  return c.json({ status: "healthy" });
14375
14396
  }).use("*", requestValidator).use("*", createRequestGuardMiddleware()).use("*", createCostTrackingMiddleware()).use("*", createGatewayAdapterMiddleware()).route("/", __llmops_gateway.default).notFound((c) => c.json({ error: {
14376
14397
  message: "Not Found",
@@ -14382,12 +14403,42 @@ app$2.use("*", (0, hono_pretty_json.prettyJSON)()).get("/health", async (c) => {
14382
14403
  type: "api_error"
14383
14404
  } }, 500);
14384
14405
  });
14385
- 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;
14386
14421
 
14387
14422
  //#endregion
14388
14423
  //#region src/server/handlers/api.ts
14389
14424
  const app$1 = new hono.Hono();
14390
- 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);
14391
14442
  var api_default = app$1;
14392
14443
 
14393
14444
  //#endregion
@@ -14404,11 +14455,13 @@ app.use("/assets/*", (0, hono_serve_static.serveStatic)({
14404
14455
  const basePath = c.var.llmopsConfig?.basePath || "";
14405
14456
  const llmProviders = c.var.llmProviders || [];
14406
14457
  const authType = c.var.llmopsConfig?.auth?.type || "basic";
14458
+ const setupComplete = c.var.setupComplete ?? false;
14407
14459
  return c.html(renderer({
14408
14460
  basePath,
14409
14461
  dev: node_process.env.LLMOPS_DEV === "true",
14410
14462
  llmProviders,
14411
- authType
14463
+ authType,
14464
+ setupComplete
14412
14465
  }));
14413
14466
  }
14414
14467
  await next();
@@ -14481,12 +14534,10 @@ const createSeedMiddleware = () => {
14481
14534
  //#endregion
14482
14535
  //#region src/server/middlewares/migration.ts
14483
14536
  /**
14484
- * Creates a middleware that handles auto-migration based on config
14537
+ * Creates a middleware that handles auto-migration on startup
14485
14538
  *
14486
- * This middleware runs once on application startup and handles:
14487
- * - autoMigrate: true - Always run migrations
14488
- * - autoMigrate: false - Never run migrations (default)
14489
- * - 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.
14490
14541
  *
14491
14542
  * IMPORTANT: This middleware should run BEFORE the seed middleware
14492
14543
  * but AFTER the database middleware creates the connection.
@@ -14495,16 +14546,15 @@ const createMigrationMiddleware = (config$1) => {
14495
14546
  let migrationComplete = false;
14496
14547
  let migrationPromise = null;
14497
14548
  return async (c, next) => {
14498
- const autoMigrate = config$1.autoMigrate ?? false;
14499
- if (migrationComplete || autoMigrate === false) {
14549
+ if (migrationComplete) {
14500
14550
  await next();
14501
14551
  return;
14502
14552
  }
14503
14553
  if (!migrationPromise) migrationPromise = (async () => {
14504
14554
  try {
14505
- 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");
14506
14556
  const rawConnection = config$1.database;
14507
- const dbType = detectDatabaseType(rawConnection);
14557
+ const dbType = detectDatabaseType$1(rawConnection);
14508
14558
  if (!dbType) {
14509
14559
  console.warn("[Migration] Could not detect database type, skipping auto-migration");
14510
14560
  return;
@@ -14515,7 +14565,10 @@ const createMigrationMiddleware = (config$1) => {
14515
14565
  console.warn("[Migration] Could not create database connection, skipping auto-migration");
14516
14566
  return;
14517
14567
  }
14518
- const result = await runAutoMigrations(db, dbType, autoMigrate, { schema });
14568
+ const result = await runAutoMigrations(db, dbType, {
14569
+ rawConnection,
14570
+ schema
14571
+ });
14519
14572
  if (result.ran) console.log(`[Migration] Auto-migration completed: ${result.tables.length} table(s) created, ${result.fields.length} field(s) added`);
14520
14573
  } catch (error$45) {
14521
14574
  console.error("[Migration] Auto-migration failed:", error$45);
@@ -14528,6 +14581,24 @@ const createMigrationMiddleware = (config$1) => {
14528
14581
  };
14529
14582
  };
14530
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
+
14531
14602
  //#endregion
14532
14603
  //#region src/index.ts
14533
14604
  const MODELS_DEV_LOGOS = "https://models.dev/logos";
@@ -14546,10 +14617,16 @@ const setConfigMiddleware = (config$1) => {
14546
14617
  };
14547
14618
  const createDatabaseMiddleware = (validatedConfig) => {
14548
14619
  return async (c, next) => {
14549
- const db = await (0, __llmops_core_db.createDatabaseFromConnection)(validatedConfig.database, { schema: validatedConfig.schema });
14550
- if (!db) throw new Error("Failed to create database connection");
14551
- 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);
14552
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);
14553
14630
  await next();
14554
14631
  };
14555
14632
  };
@@ -14571,7 +14648,7 @@ const createLLMProvidersMiddleware = (config$1) => {
14571
14648
  };
14572
14649
  const createApp = (config$1) => {
14573
14650
  const validatedConfig = (0, __llmops_core.validateLLMOpsConfig)(config$1);
14574
- 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) };
14575
14652
  };
14576
14653
  var src_default = server_default;
14577
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