import { MastraError } from '../chunk-FJEVLHJT.js';
import { MastraBase } from '../chunk-WENZPAHS.js';
import { RegisteredLogger } from '../chunk-DBBWTK24.js';

// src/server/auth.ts
var MastraAuthProvider = class extends MastraBase {
  protected;
  public;
  constructor(options) {
    super({ component: "AUTH", name: options?.name });
    if (options?.authorizeUser) {
      this.authorizeUser = options.authorizeUser.bind(this);
    }
    this.protected = options?.protected;
    this.public = options?.public;
    this.mapUserToResourceId = options?.mapUserToResourceId;
  }
  registerOptions(opts) {
    if (opts?.authorizeUser) {
      this.authorizeUser = opts.authorizeUser.bind(this);
    }
    if (opts?.mapUserToResourceId) {
      this.mapUserToResourceId = opts.mapUserToResourceId;
    }
    if (opts?.protected) {
      this.protected = opts.protected;
    }
    if (opts?.public) {
      this.public = opts.public;
    }
  }
};

// src/server/composite-auth.ts
function isSSOProvider(p) {
  return p !== null && typeof p === "object" && "getLoginUrl" in p && "handleCallback" in p;
}
function isSessionProvider(p) {
  return p !== null && typeof p === "object" && "validateSession" in p && "createSession" in p;
}
function isUserProvider(p) {
  return p !== null && typeof p === "object" && "getCurrentUser" in p;
}
function isObjectLike(value) {
  return typeof value === "object" && value !== null || typeof value === "function";
}
var CompositeAuth = class extends MastraAuthProvider {
  providers;
  authenticatedProviderByObject = /* @__PURE__ */ new WeakMap();
  authenticatedProviderByPrimitive = /* @__PURE__ */ new Map();
  constructor(providers) {
    const combinedPublic = providers.flatMap((provider) => provider.public ?? []);
    const combinedProtected = providers.flatMap((provider) => provider.protected ?? []);
    super({
      public: combinedPublic,
      protected: combinedProtected
    });
    this.providers = providers;
    if (providers.some((provider) => typeof provider.mapUserToResourceId === "function")) {
      this.mapUserToResourceId = (user) => this.mapAuthenticatedUserToResourceId(user);
    }
  }
  // Find first provider implementing an interface
  findProvider(check) {
    return this.providers.find(check);
  }
  rememberAuthenticatedProvider(user, provider) {
    if (isObjectLike(user)) {
      this.authenticatedProviderByObject.set(user, provider);
      return;
    }
    this.authenticatedProviderByPrimitive.set(user, provider);
  }
  takeAuthenticatedProvider(user) {
    if (isObjectLike(user)) {
      const provider2 = this.authenticatedProviderByObject.get(user);
      this.authenticatedProviderByObject.delete(user);
      return provider2;
    }
    const primitiveUser = user;
    const provider = this.authenticatedProviderByPrimitive.get(primitiveUser);
    this.authenticatedProviderByPrimitive.delete(primitiveUser);
    return provider;
  }
  mapAuthenticatedUserToResourceId(user) {
    const provider = this.takeAuthenticatedProvider(user);
    return provider?.mapUserToResourceId?.(user);
  }
  // ============================================================================
  // License Exemption Markers
  // Expose these if any underlying provider has them
  // ============================================================================
  /**
   * True if any provider is MastraCloudAuth (exempt from license requirement).
   */
  get isMastraCloudAuth() {
    return this.providers.some(
      (p) => "isMastraCloudAuth" in p && p.isMastraCloudAuth === true
    );
  }
  /**
   * True if any provider is SimpleAuth (exempt from license requirement).
   */
  get isSimpleAuth() {
    return this.providers.some((p) => "isSimpleAuth" in p && p.isSimpleAuth === true);
  }
  // ============================================================================
  // MastraAuthProvider Implementation
  // ============================================================================
  async authenticateToken(token, request) {
    for (const provider of this.providers) {
      try {
        const user = await provider.authenticateToken(token, request);
        if (user) {
          this.rememberAuthenticatedProvider(user, provider);
          return user;
        }
      } catch {
      }
    }
    return null;
  }
  async authorizeUser(user, request) {
    for (const provider of this.providers) {
      const authorized = await provider.authorizeUser(user, request);
      if (authorized) {
        return true;
      }
    }
    return false;
  }
  // ============================================================================
  // ISSOProvider Implementation
  // ============================================================================
  /**
   * Forward cookie header to SSO provider for PKCE validation.
   * Called by auth handler before handleCallback().
   */
  setCallbackCookieHeader(cookieHeader) {
    const sso = this.findProvider(isSSOProvider);
    if (sso && typeof sso.setCallbackCookieHeader === "function") {
      sso.setCallbackCookieHeader(cookieHeader);
    }
  }
  getLoginUrl(redirectUri, state) {
    const sso = this.findProvider(isSSOProvider);
    if (!sso) throw new Error("No SSO provider configured in CompositeAuth");
    return sso.getLoginUrl(redirectUri, state);
  }
  getLoginCookies(redirectUri, state) {
    const sso = this.findProvider(isSSOProvider);
    return sso?.getLoginCookies?.(redirectUri, state);
  }
  async handleCallback(code, state) {
    const sso = this.findProvider(isSSOProvider);
    if (!sso) throw new Error("No SSO provider configured in CompositeAuth");
    return sso.handleCallback(code, state);
  }
  getLoginButtonConfig() {
    const sso = this.findProvider(isSSOProvider);
    if (!sso) return { provider: "unknown", text: "Sign in" };
    return sso.getLoginButtonConfig();
  }
  async getLogoutUrl(redirectUri, request) {
    for (const provider of this.providers) {
      if (isSSOProvider(provider) && provider.getLogoutUrl) {
        try {
          const url = await provider.getLogoutUrl(redirectUri, request);
          if (url) return url;
        } catch {
        }
      }
    }
    return null;
  }
  // ============================================================================
  // ISessionProvider Implementation
  // ============================================================================
  async createSession(userId, metadata) {
    const session = this.findProvider(isSessionProvider);
    if (!session) throw new Error("No session provider configured in CompositeAuth");
    return session.createSession(userId, metadata);
  }
  async validateSession(sessionId) {
    for (const provider of this.providers) {
      if (isSessionProvider(provider)) {
        try {
          const session = await provider.validateSession(sessionId);
          if (session) return session;
        } catch {
        }
      }
    }
    return null;
  }
  async destroySession(sessionId) {
    const destroyPromises = [];
    for (const provider of this.providers) {
      if (isSessionProvider(provider)) {
        destroyPromises.push(
          provider.destroySession(sessionId).catch(() => {
          })
        );
      }
    }
    await Promise.all(destroyPromises);
  }
  async refreshSession(sessionId) {
    for (const provider of this.providers) {
      if (isSessionProvider(provider)) {
        try {
          const session = await provider.refreshSession(sessionId);
          if (session) return session;
        } catch {
        }
      }
    }
    return null;
  }
  getSessionIdFromRequest(request) {
    for (const provider of this.providers) {
      if (isSessionProvider(provider)) {
        try {
          const sessionId = provider.getSessionIdFromRequest(request);
          if (sessionId) return sessionId;
        } catch {
        }
      }
    }
    return null;
  }
  getSessionHeaders(session) {
    const sessionProvider = this.findProvider(isSessionProvider);
    return sessionProvider?.getSessionHeaders(session) ?? {};
  }
  getClearSessionHeaders() {
    const headers = {};
    for (const provider of this.providers) {
      if (isSessionProvider(provider)) {
        try {
          const providerHeaders = provider.getClearSessionHeaders();
          Object.assign(headers, providerHeaders);
        } catch {
        }
      }
    }
    return headers;
  }
  // ============================================================================
  // IUserProvider Implementation
  // Try each provider until one returns a user (like authenticateToken)
  // ============================================================================
  async getCurrentUser(request) {
    for (const provider of this.providers) {
      if (isUserProvider(provider)) {
        try {
          const user = await provider.getCurrentUser(request);
          if (user) return user;
        } catch {
        }
      }
    }
    return null;
  }
  async getUser(userId) {
    for (const provider of this.providers) {
      if (isUserProvider(provider)) {
        try {
          const user = await provider.getUser(userId);
          if (user) return user;
        } catch {
        }
      }
    }
    return null;
  }
};

// src/server/base.ts
var MastraServerBase = class extends MastraBase {
  #app;
  constructor({ app, name }) {
    super({ component: RegisteredLogger.SERVER, name: name ?? "Server" });
    this.#app = app;
  }
  /**
   * Get the app instance.
   *
   * Returns the server app that was passed to the constructor. This allows users
   * to access the underlying server framework's app for direct operations
   * like calling routes via app.fetch() (Hono) or using the app for testing.
   *
   * @template T - The expected type of the app (defaults to TApp)
   * @returns The app instance cast to T. Callers are responsible for ensuring T matches the actual app type.
   *
   * @example
   * ```typescript
   * const app = adapter.getApp<Hono>();
   * const response = await app.fetch(new Request('http://localhost/api/agents'));
   * ```
   */
  getApp() {
    return this.#app;
  }
  /**
   * Protected getter for subclasses to access the app.
   * This allows subclasses to use `this.app` naturally.
   */
  get app() {
    return this.#app;
  }
};

// src/server/simple-auth.ts
var DEFAULT_HEADERS = ["Authorization", "X-Playground-Access"];
var SimpleAuth = class extends MastraAuthProvider {
  /**
   * Marker to exempt SimpleAuth from EE license requirement.
   * SimpleAuth is for development/testing and should work without a license.
   */
  isSimpleAuth = true;
  tokens;
  headers;
  users;
  userById;
  constructor(options) {
    super(options);
    this.tokens = options.tokens;
    this.users = Object.values(this.tokens);
    this.headers = [...DEFAULT_HEADERS].concat(options.headers || []);
    this.userById = new Map(this.users.map((u) => [String(u?.id), u]));
  }
  async authenticateToken(token, request) {
    const requestTokens = this.getTokensFromHeaders(token, request);
    for (const requestToken of requestTokens) {
      const tokenToUser = this.tokens[requestToken];
      if (tokenToUser) {
        return tokenToUser;
      }
    }
    return this.getUserFromCookie(this.getRequestHeader(request, "Cookie"));
  }
  async authorizeUser(user, _request) {
    return this.users.includes(user);
  }
  /** Get current user from request headers or cookie. */
  async getCurrentUser(request) {
    for (const headerName of this.headers) {
      const headerValue = request.headers.get(headerName);
      if (headerValue) {
        const token = this.stripBearerPrefix(headerValue);
        const user = this.tokens[token];
        if (user) {
          return user;
        }
      }
    }
    return this.getUserFromCookie(request.headers.get("Cookie"));
  }
  getUserFromCookie(cookieHeader) {
    if (!cookieHeader) return null;
    const cookies = cookieHeader.split(";").map((c) => c.trim());
    for (const cookie of cookies) {
      if (cookie.startsWith("mastra-token=")) {
        const token = cookie.slice("mastra-token=".length);
        const user = this.tokens[token];
        if (user) {
          return user;
        }
      }
    }
    return null;
  }
  /** Get user by ID. */
  async getUser(userId) {
    return this.userById.get(userId) ?? null;
  }
  /**
   * Sign in with token (passed as password field).
   * The email field is ignored - only the token matters.
   */
  async signIn(_email, password, _request) {
    const token = password;
    const user = this.tokens[token];
    if (!user) {
      throw new Error("Invalid token");
    }
    const cookie = `mastra-token=${token}; Path=/; HttpOnly; SameSite=Lax; Max-Age=86400`;
    return {
      user,
      token,
      cookies: [cookie]
    };
  }
  async signUp() {
    throw new Error("Sign up is not supported with SimpleAuth. Use pre-configured tokens.");
  }
  isSignUpEnabled() {
    return false;
  }
  /**
   * Get headers to clear the session cookie on logout.
   * Partial ISessionProvider implementation for logout support.
   */
  getClearSessionHeaders() {
    return {
      "Set-Cookie": "mastra-token=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0"
    };
  }
  stripBearerPrefix(token) {
    return token.startsWith("Bearer ") ? token.slice(7) : token;
  }
  /**
   * Get a header value from either a HonoRequest or standard Request.
   * The auth middleware passes a raw Request (c.req.raw), not a HonoRequest,
   * so we need to handle both APIs.
   */
  getRequestHeader(request, name) {
    if (typeof request.header === "function") {
      return request.header(name);
    }
    return request.headers?.get(name) ?? void 0;
  }
  getTokensFromHeaders(token, request) {
    const tokens = [token];
    for (const headerName of this.headers) {
      const headerValue = this.getRequestHeader(request, headerName);
      if (headerValue) {
        tokens.push(this.stripBearerPrefix(headerValue));
      }
    }
    return tokens;
  }
};

// src/server/index.ts
function validateOptions(path, options) {
  const opts = options;
  if (opts.method === void 0) {
    throw new MastraError({
      id: "MASTRA_SERVER_API_INVALID_ROUTE_OPTIONS",
      text: `Invalid options for route "${path}", missing "method" property`,
      domain: "MASTRA_SERVER" /* MASTRA_SERVER */,
      category: "USER" /* USER */
    });
  }
  if (opts.handler === void 0 && opts.createHandler === void 0) {
    throw new MastraError({
      id: "MASTRA_SERVER_API_INVALID_ROUTE_OPTIONS",
      text: `Invalid options for route "${path}", you must define a "handler" or "createHandler" property`,
      domain: "MASTRA_SERVER" /* MASTRA_SERVER */,
      category: "USER" /* USER */
    });
  }
  if (opts.handler !== void 0 && opts.createHandler !== void 0) {
    throw new MastraError({
      id: "MASTRA_SERVER_API_INVALID_ROUTE_OPTIONS",
      text: `Invalid options for route "${path}", you can only define one of the following properties: "handler" or "createHandler"`,
      domain: "MASTRA_SERVER" /* MASTRA_SERVER */,
      category: "USER" /* USER */
    });
  }
}
function registerApiRoute(path, options) {
  if (path.startsWith("/api/")) {
    throw new MastraError({
      id: "MASTRA_SERVER_API_PATH_RESERVED",
      text: `Path must not start with "/api", it's reserved for internal API routes`,
      domain: "MASTRA_SERVER" /* MASTRA_SERVER */,
      category: "USER" /* USER */
    });
  }
  validateOptions(path, options);
  return {
    path,
    method: options.method,
    handler: options.handler,
    createHandler: options.createHandler,
    openapi: options.openapi,
    middleware: options.middleware,
    requiresAuth: options.requiresAuth
  };
}
function defineAuth(config) {
  return config;
}

export { CompositeAuth, MastraAuthProvider, MastraServerBase, SimpleAuth, defineAuth, registerApiRoute };
//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map