const require_chunk = require('./chunk-CUT6urMc.cjs');
const require_config = require('./config-D3ORuiUs.cjs');
const node_fs = require_chunk.__toESM(require("node:fs"));
const node_path = require_chunk.__toESM(require("node:path"));
const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
const fast_glob = require_chunk.__toESM(require("fast-glob"));
const lodash_kebabcase = require_chunk.__toESM(require("lodash.kebabcase"));
const __geekmidas_constructs_endpoints = require_chunk.__toESM(require("@geekmidas/constructs/endpoints"));
const __geekmidas_schema_conversion = require_chunk.__toESM(require("@geekmidas/schema/conversion"));

//#region src/types.ts
function isPartitionedRoutes(routes) {
	return typeof routes === "object" && routes !== null && !Array.isArray(routes) && "paths" in routes;
}

//#endregion
//#region src/generators/Generator.ts
var ConstructGenerator = class {
	static async build(context, outputDir, generator, patterns, options) {
		const constructs = await generator.load(patterns);
		return generator.build(context, constructs, outputDir, options);
	}
	async load(patterns, cwd = process.cwd(), bustCache = false) {
		const logger = console;
		let globPatterns;
		let partitionFn;
		if (isPartitionedRoutes(patterns)) {
			globPatterns = Array.isArray(patterns.paths) ? patterns.paths : [patterns.paths];
			partitionFn = patterns.partition;
		} else globPatterns = Array.isArray(patterns) ? patterns : patterns ? [patterns] : [];
		const files = fast_glob.default.stream(globPatterns, {
			cwd,
			absolute: true
		});
		const constructs = [];
		for await (const f of files) try {
			const file = f.toString();
			const importPath = bustCache ? `${file}?t=${Date.now()}` : file;
			const module$1 = await import(importPath);
			const partition = partitionFn ? partitionFn(file) : void 0;
			for (const [key, construct] of Object.entries(module$1)) if (this.isConstruct(construct)) constructs.push({
				key,
				name: (0, lodash_kebabcase.default)(key),
				construct,
				path: {
					absolute: file,
					relative: (0, node_path.relative)(process.cwd(), file)
				},
				partition
			});
		} catch (error) {
			const err = error;
			logger.error(`Failed to load ${f}: ${err.message}`);
			if (err.stack) logger.error(err.stack);
			throw error;
		}
		return constructs;
	}
};

//#endregion
//#region src/build/endpoint-analyzer.ts
/**
* Analyze an endpoint to extract its features
*/
function analyzeEndpointFeatures(endpoint) {
	return {
		hasAuth: !!endpoint.authorizer,
		hasServices: endpoint.services.length > 0,
		hasDatabase: !!endpoint.databaseService,
		hasBodyValidation: !!endpoint.input?.body,
		hasQueryValidation: !!endpoint.input?.query,
		hasParamValidation: !!endpoint.input?.params,
		hasAudits: (endpoint.audits?.length ?? 0) > 0,
		hasEvents: (endpoint.events?.length ?? 0) > 0,
		hasRateLimit: !!endpoint.rateLimit,
		hasRls: !!endpoint.rlsConfig && !endpoint.rlsBypass,
		hasOutputValidation: !!endpoint.outputSchema
	};
}
/**
* Determine the optimization tier for an endpoint based on its features
*/
function determineEndpointTier(features) {
	const { hasAuth, hasServices, hasDatabase, hasAudits, hasEvents, hasRateLimit, hasRls } = features;
	if (!hasAuth && !hasServices && !hasDatabase && !hasAudits && !hasEvents && !hasRateLimit && !hasRls) return "minimal";
	if (hasAudits || hasRls || hasRateLimit) return "full";
	return "standard";
}
/**
* Perform complete analysis of an endpoint
*/
function analyzeEndpoint(endpoint, exportName) {
	const features = analyzeEndpointFeatures(endpoint);
	const tier = determineEndpointTier(features);
	return {
		route: endpoint.route,
		method: endpoint.method,
		exportName,
		features,
		tier,
		serviceNames: endpoint.services.map((s) => s.serviceName),
		databaseServiceName: endpoint.databaseService?.serviceName
	};
}
/**
* Generate a summary of endpoint analysis for logging
*/
function summarizeAnalysis(analyses) {
	const byTier = {
		minimal: 0,
		standard: 0,
		full: 0
	};
	const byFeature = {
		hasAuth: 0,
		hasServices: 0,
		hasDatabase: 0,
		hasBodyValidation: 0,
		hasQueryValidation: 0,
		hasParamValidation: 0,
		hasAudits: 0,
		hasEvents: 0,
		hasRateLimit: 0,
		hasRls: 0,
		hasOutputValidation: 0
	};
	for (const analysis of analyses) {
		byTier[analysis.tier]++;
		for (const [feature, enabled] of Object.entries(analysis.features)) if (enabled) byFeature[feature]++;
	}
	return {
		total: analyses.length,
		byTier,
		byFeature
	};
}

//#endregion
//#region src/build/handler-templates.ts
/**
* Generate validator references for an endpoint
*/
function generateValidators(exportName, features) {
	const validators = [];
	if (features.hasBodyValidation) validators.push(`validateBody(${exportName})`);
	if (features.hasQueryValidation) validators.push(`validateQuery(${exportName})`);
	if (features.hasParamValidation) validators.push(`validateParams(${exportName})`);
	return validators.length > 0 ? `\n    ${validators.join(",\n    ")},` : "";
}
/**
* Generate a minimal handler (near-raw-Hono performance)
*
* Used for: Health checks, public endpoints with no services
*/
function generateMinimalHandler(analysis) {
	const { exportName, features } = analysis;
	const method = analysis.method.toLowerCase();
	const validators = generateValidators(exportName, features);
	const hasValidators = validators.length > 0;
	if (!hasValidators && !features.hasOutputValidation) return `
  // Minimal handler: ${analysis.route} (${analysis.method})
  app.${method}('${analysis.route}', async (c) => {
    const result = await ${exportName}.handler(
      {
        services: {},
        logger,
        body: undefined,
        query: undefined,
        params: undefined,
        session: undefined,
        header: Endpoint.createHeaders(c.req.header()),
        cookie: Endpoint.createCookies(c.req.header().cookie),
        auditor: undefined,
        db: undefined,
      } as any,
      { getMetadata: () => ({}) } as any,
    );
    return c.json(result, ${exportName}.status as any);
  });`;
	return `
  // Minimal handler with validation: ${analysis.route} (${analysis.method})
  app.${method}('${analysis.route}',${validators}
    async (c) => {
      const result = await ${exportName}.handler(
        {
          services: {},
          logger,
          body: ${features.hasBodyValidation ? "(c.req.valid as any)('json')" : "undefined"},
          query: ${features.hasQueryValidation ? "(c.req.valid as any)('query')" : "undefined"},
          params: ${features.hasParamValidation ? "(c.req.valid as any)('param')" : "undefined"},
          session: undefined,
          header: Endpoint.createHeaders(c.req.header()),
          cookie: Endpoint.createCookies(c.req.header().cookie),
          auditor: undefined,
          db: undefined,
        } as any,
        { getMetadata: () => ({}) } as any,
      );
      ${features.hasOutputValidation ? `const output = await ${exportName}.parseOutput(result);
      return c.json(output, ${exportName}.status as any);` : `return c.json(result, ${exportName}.status as any);`}
    }
  );`;
}
/**
* Generate a standard handler (auth and/or services)
*
* Used for: Authenticated endpoints, endpoints with services
*/
function generateStandardHandler(analysis) {
	const { exportName, features } = analysis;
	const method = analysis.method.toLowerCase();
	const validators = generateValidators(exportName, features);
	let serviceResolution = "";
	if (features.hasServices || features.hasDatabase) serviceResolution = `
      const services = await serviceDiscovery.register(${exportName}.services);
      ${features.hasDatabase ? `const db = ${exportName}.databaseService
        ? (await serviceDiscovery.register([${exportName}.databaseService]) as any)[${exportName}.databaseService.serviceName]
        : undefined;` : "const db = undefined;"}`;
	else serviceResolution = `
      const services = {};
      const db = undefined;`;
	let authCode = "";
	if (features.hasAuth) authCode = `
      // Authentication
      const session = await ${exportName}.getSession({
        services,
        logger,
        header,
        cookie,
        ...(db !== undefined && { db }),
      } as any);

      const isAuthorized = await ${exportName}.authorize({
        header,
        cookie,
        services,
        logger,
        session,
      } as any);

      if (!isAuthorized) {
        return c.json({ error: 'Unauthorized' }, 401);
      }`;
	let eventCode = "";
	if (features.hasEvents) eventCode = `
      // Publish events on success
      if (Endpoint.isSuccessStatus(${exportName}.status)) {
        await (publishConstructEvents as any)(
          ${exportName},
          result,
          serviceDiscovery,
          logger,
        );
      }`;
	return `
  // Standard handler: ${analysis.route} (${analysis.method})
  app.${method}('${analysis.route}',${validators}
    async (c) => {
      const headerValues = c.req.header();
      const header = Endpoint.createHeaders(headerValues);
      const cookie = Endpoint.createCookies(headerValues.cookie);
${serviceResolution}
${authCode}

      const responseBuilder = new ResponseBuilder();
      const result = await ${exportName}.handler(
        {
          services,
          logger,
          body: ${features.hasBodyValidation ? "(c.req.valid as any)('json')" : "undefined"},
          query: ${features.hasQueryValidation ? "(c.req.valid as any)('query')" : "undefined"},
          params: ${features.hasParamValidation ? "(c.req.valid as any)('param')" : "undefined"},
          session: ${features.hasAuth ? "session" : "undefined"},
          header,
          cookie,
          auditor: undefined,
          db,
        } as any,
        responseBuilder,
      );

      let data = result;
      let metadata = responseBuilder.getMetadata();

      if (Endpoint.hasMetadata(result)) {
        data = result.data;
        metadata = result.metadata;
      }

      ${features.hasOutputValidation ? `const output = ${exportName}.outputSchema
        ? await ${exportName}.parseOutput(data)
        : data;` : "const output = data;"}
${eventCode}

      const status = (metadata.status ?? ${exportName}.status) as any;
      return c.json(output, status);
    }
  );`;
}
/**
* Generate validators.ts - Shared validator middleware factories
*/
function generateValidatorsFile(analyses) {
	const needsBody = analyses.some((a) => a.features.hasBodyValidation);
	const needsQuery = analyses.some((a) => a.features.hasQueryValidation);
	const needsParams = analyses.some((a) => a.features.hasParamValidation);
	if (!needsBody && !needsQuery && !needsParams) return `// No validators needed for this build\nexport {};\n`;
	const exports$1 = [];
	const factories = [];
	if (needsBody) {
		exports$1.push("validateBody");
		factories.push(`
export const validateBody = (endpoint: any) =>
  validator('json', async (value, c) => {
    if (!endpoint.input?.body) return undefined;
    const parsed = await Endpoint.validate(endpoint.input.body, value);
    if (parsed.issues) return c.json(parsed.issues, 422);
    return parsed.value;
  });`);
	}
	if (needsQuery) {
		exports$1.push("validateQuery");
		factories.push(`
export const validateQuery = (endpoint: any) =>
  validator('query', async (_, c) => {
    if (!endpoint.input?.query) return undefined;
    const rawQuery = Object.fromEntries(new URL(c.req.url).searchParams);
    const parsed = await Endpoint.validate(endpoint.input.query, rawQuery);
    if (parsed.issues) return c.json(parsed.issues, 422);
    return parsed.value;
  });`);
	}
	if (needsParams) {
		exports$1.push("validateParams");
		factories.push(`
export const validateParams = (endpoint: any) =>
  validator('param', async (params, c) => {
    if (!endpoint.input?.params) return undefined;
    const parsed = await Endpoint.validate(endpoint.input.params, params);
    if (parsed.issues) return c.json(parsed.issues, 422);
    return parsed.value;
  });`);
	}
	return `/**
 * Generated validator middleware factories
 * Shared across all endpoint tiers that need validation
 */
import { validator } from 'hono/validator';
import { Endpoint } from '@geekmidas/constructs/endpoints';
${factories.join("\n")}
`;
}
/**
* Generate a standalone minimal endpoint file
*/
function generateMinimalEndpointFile(analysis, endpointImport) {
	const { exportName, features } = analysis;
	const needsValidators = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation;
	const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
	const handler = generateMinimalHandler(analysis);
	return `/**
 * Minimal endpoint: ${analysis.route} (${analysis.method})
 * Near-raw-Hono performance
 */
import type { Hono } from 'hono';
import type { Logger } from '@geekmidas/logger';
import { Endpoint } from '@geekmidas/constructs/endpoints';
${validatorImport}
import { ${exportName} } from '${endpointImport.importPath}';

export function setup${capitalize(exportName)}(
  app: Hono,
  logger: Logger,
): void {
${handler}
}
`;
}
/**
* Generate a standalone standard endpoint file
*/
function generateStandardEndpointFile(analysis, endpointImport) {
	const { exportName, features } = analysis;
	const needsValidators = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation;
	const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
	const eventsImport = features.hasEvents ? `import { publishConstructEvents } from '@geekmidas/constructs/endpoints';` : "";
	const handler = generateStandardHandler(analysis);
	return `/**
 * Standard endpoint: ${analysis.route} (${analysis.method})
 * Auth and/or services enabled
 */
import type { Hono } from 'hono';
import type { Logger } from '@geekmidas/logger';
import type { ServiceDiscovery } from '@geekmidas/services';
import { Endpoint, ResponseBuilder } from '@geekmidas/constructs/endpoints';
${eventsImport}
${validatorImport}
import { ${exportName} } from '${endpointImport.importPath}';

export function setup${capitalize(exportName)}(
  app: Hono,
  serviceDiscovery: ServiceDiscovery<any, any>,
  logger: Logger,
): void {
${handler}
}
`;
}
/**
* Generate a standalone full endpoint file
*/
function generateFullEndpointFile(analysis, endpointImport) {
	const { exportName } = analysis;
	return `/**
 * Full endpoint: ${analysis.route} (${analysis.method})
 * Complex features: audits, RLS, rate limiting
 */
import type { Hono } from 'hono';
import type { ServiceDiscovery } from '@geekmidas/services';
import { HonoEndpoint } from '@geekmidas/constructs/hono';
import { ${exportName} } from '${endpointImport.importPath}';

export function setup${capitalize(exportName)}(
  app: Hono,
  serviceDiscovery: ServiceDiscovery<any, any>,
  openApiOptions: any,
): void {
  HonoEndpoint.addRoutes([${exportName}] as any, serviceDiscovery, app, openApiOptions);
}
`;
}
/**
* Generate tier index file that imports and calls all endpoint setup functions
*/
function generateTierIndexFile(tier, analyses) {
	const tierEndpoints = analyses.filter((a) => a.tier === tier);
	if (tierEndpoints.length === 0) {
		if (tier === "minimal") return `// No minimal-tier endpoints in this build
import type { Hono } from 'hono';
import type { Logger } from '@geekmidas/logger';

export function setupMinimalEndpoints(
  _app: Hono,
  _logger: Logger,
): void {
  // No minimal endpoints
}
`;
		if (tier === "standard") return `// No standard-tier endpoints in this build
import type { Hono } from 'hono';
import type { Logger } from '@geekmidas/logger';
import type { ServiceDiscovery } from '@geekmidas/services';

export function setupStandardEndpoints(
  _app: Hono,
  _serviceDiscovery: ServiceDiscovery<any, any>,
  _logger: Logger,
): void {
  // No standard endpoints
}
`;
		return `// No full-tier endpoints in this build
import type { Hono } from 'hono';
import type { ServiceDiscovery } from '@geekmidas/services';

export function setupFullEndpoints(
  _app: Hono,
  _serviceDiscovery: ServiceDiscovery<any, any>,
  _enableOpenApi: boolean,
): void {
  // No full endpoints
}
`;
	}
	const imports = tierEndpoints.map((a) => `import { setup${capitalize(a.exportName)} } from './${a.exportName}.js';`).join("\n");
	if (tier === "minimal") {
		const calls$1 = tierEndpoints.map((a) => `  setup${capitalize(a.exportName)}(app, logger);`).join("\n");
		return `/**
 * Minimal-tier endpoint index (${tierEndpoints.length} endpoints)
 * Near-raw-Hono performance
 */
import type { Hono } from 'hono';
import type { Logger } from '@geekmidas/logger';
${imports}

export function setupMinimalEndpoints(
  app: Hono,
  logger: Logger,
): void {
${calls$1}
}
`;
	}
	if (tier === "standard") {
		const calls$1 = tierEndpoints.map((a) => `  setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
		return `/**
 * Standard-tier endpoint index (${tierEndpoints.length} endpoints)
 * Auth and/or services enabled
 */
import type { Hono } from 'hono';
import type { Logger } from '@geekmidas/logger';
import type { ServiceDiscovery } from '@geekmidas/services';
${imports}

export function setupStandardEndpoints(
  app: Hono,
  serviceDiscovery: ServiceDiscovery<any, any>,
  logger: Logger,
): void {
${calls$1}
}
`;
	}
	const calls = tierEndpoints.map((a) => `  setup${capitalize(a.exportName)}(app, serviceDiscovery, openApiOptions);`).join("\n");
	return `/**
 * Full-tier endpoint index (${tierEndpoints.length} endpoints)
 * Complex features: audits, RLS, rate limiting
 */
import type { Hono } from 'hono';
import type { ServiceDiscovery } from '@geekmidas/services';
${imports}

export function setupFullEndpoints(
  app: Hono,
  serviceDiscovery: ServiceDiscovery<any, any>,
  enableOpenApi: boolean,
): void {
  const openApiOptions: any = enableOpenApi ? {
    docsPath: '/__docs',
    openApiOptions: {
      title: 'API Documentation',
      version: '1.0.0',
      description: 'Generated API documentation'
    }
  } : { docsPath: false };

${calls}
}
`;
}
/**
* Generate validator imports for a single endpoint
*/
function generateValidatorImportsForEndpoint(analysis) {
	const imports = [];
	if (analysis.features.hasBodyValidation) imports.push("validateBody");
	if (analysis.features.hasQueryValidation) imports.push("validateQuery");
	if (analysis.features.hasParamValidation) imports.push("validateParams");
	if (imports.length === 0) return "";
	return `import { ${imports.join(", ")} } from '../validators.js';`;
}
/**
* Capitalize first letter
*/
function capitalize(str) {
	return str.charAt(0).toUpperCase() + str.slice(1);
}
/**
* Generate all endpoint files with nested folder structure (per-endpoint files)
*/
function generateEndpointFilesNested(analyses, endpointImports) {
	const files = {
		"validators.ts": generateValidatorsFile(analyses),
		"minimal/index.ts": generateTierIndexFile("minimal", analyses),
		"standard/index.ts": generateTierIndexFile("standard", analyses),
		"full/index.ts": generateTierIndexFile("full", analyses),
		"index.ts": generateNestedIndexFile(analyses)
	};
	for (const analysis of analyses) {
		const endpointImport = endpointImports.find((i) => i.exportName === analysis.exportName);
		if (!endpointImport) continue;
		const fileName = `${analysis.tier}/${analysis.exportName}.ts`;
		switch (analysis.tier) {
			case "minimal":
				files[fileName] = generateMinimalEndpointFile(analysis, endpointImport);
				break;
			case "standard":
				files[fileName] = generateStandardEndpointFile(analysis, endpointImport);
				break;
			case "full":
				files[fileName] = generateFullEndpointFile(analysis, endpointImport);
				break;
		}
	}
	return files;
}
/**
* Generate index.ts for nested structure
*/
function generateNestedIndexFile(analyses) {
	const minimalCount = analyses.filter((a) => a.tier === "minimal").length;
	const standardCount = analyses.filter((a) => a.tier === "standard").length;
	const fullCount = analyses.filter((a) => a.tier === "full").length;
	return `/**
 * Generated optimized endpoints
 *
 * Build-time optimization tiers:
 * - minimal: ${minimalCount} endpoints (near-raw-Hono)
 * - standard: ${standardCount} endpoints (auth/services)
 * - full: ${fullCount} endpoints (audits/rls/rate-limit)
 */
import type { EnvironmentParser } from '@geekmidas/envkit';
import type { Logger } from '@geekmidas/logger';
import type { Hono } from 'hono';
import { ServiceDiscovery } from '@geekmidas/services';
import { setupMinimalEndpoints } from './minimal/index.js';
import { setupStandardEndpoints } from './standard/index.js';
import { setupFullEndpoints } from './full/index.js';

export async function setupEndpoints(
  app: Hono,
  envParser: EnvironmentParser<any>,
  logger: Logger,
  enableOpenApi: boolean = false,
): Promise<void> {
  const serviceDiscovery = ServiceDiscovery.getInstance(envParser);

  // Minimal handlers (${minimalCount} endpoints) - near-raw-Hono performance
  setupMinimalEndpoints(app, logger);

  // Standard handlers (${standardCount} endpoints) - auth/services
  setupStandardEndpoints(app, serviceDiscovery, logger);

  // Full handlers (${fullCount} endpoints) - audits/rls/rate-limit
  setupFullEndpoints(app, serviceDiscovery, enableOpenApi);

  // Add Swagger UI if OpenAPI is enabled
  if (enableOpenApi) {
    try {
      const { swaggerUI } = await import('@hono/swagger-ui');
      app.get('/__docs/ui', swaggerUI({ url: '/__docs' }));
    } catch {
      // @hono/swagger-ui not installed, skip Swagger UI
    }
  }
}
`;
}

//#endregion
//#region src/generators/EndpointGenerator.ts
var EndpointGenerator = class extends ConstructGenerator {
	isConstruct(value) {
		return __geekmidas_constructs_endpoints.Endpoint.isEndpoint(value);
	}
	async build(context, constructs, outputDir, options) {
		const provider = options?.provider || "aws-apigatewayv2";
		const enableOpenApi = options?.enableOpenApi || false;
		const logger = console;
		const routes = [];
		if (constructs.length === 0) return routes;
		if (provider === "server") {
			await this.generateEndpointsFile(outputDir, constructs, context);
			const appFile = await this.generateAppFile(outputDir, context);
			routes.push({
				path: "*",
				method: "ALL",
				handler: (0, node_path.relative)(process.cwd(), appFile),
				authorizer: "none"
			});
			logger.log(`Generated server with ${constructs.length} endpoints${enableOpenApi ? " (OpenAPI enabled)" : ""}`);
		} else if (provider === "aws-lambda") {
			const routesDir = (0, node_path.join)(outputDir, "routes");
			await (0, node_fs_promises.mkdir)(routesDir, { recursive: true });
			for (const { key, construct, path } of constructs) {
				const handlerFile = await this.generateHandlerFile(routesDir, path.relative, key, "aws-apigatewayv2", construct, context);
				const routeInfo = {
					path: construct._path,
					method: construct.method,
					handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
					timeout: construct.timeout,
					memorySize: construct.memorySize,
					environment: await construct.getEnvironment(),
					authorizer: construct.authorizer?.name ?? "none"
				};
				routes.push(routeInfo);
				logger.log(`Generated handler for ${routeInfo.method} ${routeInfo.path}`);
			}
		} else for (const { key, construct, path } of constructs) {
			const handlerFile = await this.generateHandlerFile(outputDir, path.relative, key, provider, construct, context);
			const routeInfo = {
				path: construct._path,
				method: construct.method,
				handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
				timeout: construct.timeout,
				memorySize: construct.memorySize,
				environment: await construct.getEnvironment(),
				authorizer: construct.authorizer?.name ?? "none"
			};
			routes.push(routeInfo);
			logger.log(`Generated handler for ${routeInfo.method} ${routeInfo.path}`);
		}
		return routes;
	}
	async generateHandlerFile(outputDir, sourceFile, exportName, provider, _endpoint, context) {
		const handlerFileName = `${exportName}.ts`;
		const handlerPath = (0, node_path.join)(outputDir, handlerFileName);
		const relativePath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), sourceFile);
		const importPath = relativePath.replace(/\.ts$/, ".js");
		const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), context.envParserPath);
		let content;
		switch (provider) {
			case "aws-apigatewayv1":
				content = this.generateAWSApiGatewayV1Handler(importPath, exportName, relativeEnvParserPath, context.envParserImportPattern);
				break;
			case "aws-apigatewayv2":
				content = this.generateAWSApiGatewayV2Handler(importPath, exportName, relativeEnvParserPath, context.envParserImportPattern);
				break;
			case "server":
				content = this.generateServerHandler(importPath, exportName);
				break;
			default: throw new Error(`Unsupported provider: ${provider}`);
		}
		await (0, node_fs_promises.writeFile)(handlerPath, content);
		return handlerPath;
	}
	async generateEndpointsFile(outputDir, endpoints, context) {
		const endpointsFileName = "endpoints.ts";
		const endpointsPath = (0, node_path.join)(outputDir, endpointsFileName);
		const importsByFile = /* @__PURE__ */ new Map();
		for (const { path, key } of endpoints) {
			const relativePath = (0, node_path.relative)((0, node_path.dirname)(endpointsPath), path.relative);
			const importPath = relativePath.replace(/\.ts$/, ".js");
			if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
			importsByFile.get(importPath)?.push(key);
		}
		const endpointImports = Array.from(importsByFile.entries()).map(([importPath, exports$1]) => `import { ${exports$1.join(", ")} } from '${importPath}';`).join("\n");
		const allExportNames = endpoints.map(({ key }) => key);
		if (context.production?.enabled && context.production.optimizedHandlers) return this.generateOptimizedEndpointsFile(endpointsPath, endpoints, endpointImports, allExportNames);
		const content = `import type { EnvironmentParser } from '@geekmidas/envkit';
import type { Logger } from '@geekmidas/logger';
import { HonoEndpoint } from '@geekmidas/constructs/hono';
import { Endpoint } from '@geekmidas/constructs/endpoints';
import { ServiceDiscovery } from '@geekmidas/services';
import type { Hono } from 'hono';
${endpointImports}

const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any, any, any>[] = [
  ${allExportNames.join(",\n  ")}
];

export async function setupEndpoints(
  app: Hono,
  envParser: EnvironmentParser<any>,
  logger: Logger,
  enableOpenApi: boolean = true,
): Promise<void> {
  const serviceDiscovery = ServiceDiscovery.getInstance(envParser);

  // Configure OpenAPI options based on enableOpenApi flag
  const openApiOptions: any = enableOpenApi ? {
    docsPath: '/__docs',
    openApiOptions: {
      title: 'API Documentation',
      version: '1.0.0',
      description: 'Generated API documentation'
    }
  } : { docsPath: false };

  HonoEndpoint.addRoutes(endpoints, serviceDiscovery, app, openApiOptions);

  // Add Swagger UI if OpenAPI is enabled
  if (enableOpenApi) {
    try {
      const { swaggerUI } = await import('@hono/swagger-ui');
      app.get('/__docs/ui', swaggerUI({ url: '/__docs' }));
    } catch {
      // @hono/swagger-ui not installed, skip Swagger UI
    }
  }
}
`;
		await (0, node_fs_promises.writeFile)(endpointsPath, content);
		return endpointsPath;
	}
	/**
	* Generate optimized endpoints files with nested folder structure (per-endpoint files)
	*/
	async generateOptimizedEndpointsFile(endpointsPath, endpoints, _endpointImports, _allExportNames) {
		const logger = console;
		const outputDir = (0, node_path.dirname)(endpointsPath);
		const endpointsDir = (0, node_path.join)(outputDir, "endpoints");
		await (0, node_fs_promises.mkdir)((0, node_path.join)(endpointsDir, "minimal"), { recursive: true });
		await (0, node_fs_promises.mkdir)((0, node_path.join)(endpointsDir, "standard"), { recursive: true });
		await (0, node_fs_promises.mkdir)((0, node_path.join)(endpointsDir, "full"), { recursive: true });
		const analyses = endpoints.map(({ key, construct }) => analyzeEndpoint(construct, key));
		const endpointImports = endpoints.map(({ key, path }) => {
			const tierDir = (0, node_path.join)(endpointsDir, "standard");
			const relativePath = (0, node_path.relative)(tierDir, path.relative);
			const importPath = relativePath.replace(/\.ts$/, ".js");
			return {
				exportName: key,
				importPath
			};
		});
		const summary = summarizeAnalysis(analyses);
		logger.log(`\n📊 Endpoint Analysis:`);
		logger.log(`   Total: ${summary.total} endpoints`);
		logger.log(`   - Minimal (near-raw-Hono): ${summary.byTier.minimal} endpoints`);
		logger.log(`   - Standard (auth/services): ${summary.byTier.standard} endpoints`);
		logger.log(`   - Full (audits/rls/rate-limit): ${summary.byTier.full} endpoints`);
		const files = generateEndpointFilesNested(analyses, endpointImports);
		for (const [filename, content] of Object.entries(files)) {
			const filePath = (0, node_path.join)(endpointsDir, filename);
			await (0, node_fs_promises.mkdir)((0, node_path.dirname)(filePath), { recursive: true });
			await (0, node_fs_promises.writeFile)(filePath, content);
		}
		const endpointFiles = Object.keys(files).filter((f) => !f.endsWith("index.ts") && !f.endsWith("validators.ts")).length;
		const indexFiles = Object.keys(files).filter((f) => f.endsWith("index.ts")).length;
		logger.log(`   Generated ${endpointFiles} endpoint files + ${indexFiles} index files + validators.ts`);
		return (0, node_path.join)(endpointsDir, "index.ts");
	}
	async generateAppFile(outputDir, context) {
		if (context.production?.enabled) return this.generateProductionAppFile(outputDir, context);
		const appFileName = "app.ts";
		const appPath = (0, node_path.join)(outputDir, appFileName);
		const relativeLoggerPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.loggerPath);
		const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.envParserPath);
		const telescopeEnabled = context.telescope?.enabled;
		const telescopeWebSocketEnabled = context.telescope?.websocket;
		const usesExternalTelescope = !!context.telescope?.telescopePath;
		const studioEnabled = context.studio?.enabled;
		const usesExternalStudio = !!context.studio?.studioPath;
		let telescopeImports = "";
		if (telescopeEnabled) if (usesExternalTelescope) {
			const relativeTelescopePath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.telescope?.telescopePath);
			telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
		} else telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
		let studioImports = "";
		if (studioEnabled) if (usesExternalStudio) {
			const relativeStudioPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.studio?.studioPath);
			studioImports = `import ${context.studio?.studioImportPattern} from '${relativeStudioPath}';
import { createStudioApp } from '@geekmidas/studio/server/hono';`;
		} else studioImports = `// Studio requires a configured instance - use studio config path
// import { createStudioApp } from '@geekmidas/studio/server/hono';`;
		let hooksImports = "";
		let beforeSetupCall = "";
		let afterSetupCall = "";
		if (context.hooks?.serverHooksPath) {
			const relativeHooksPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath);
			hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
			beforeSetupCall = `
  // Call beforeSetup hook if defined
  if (typeof serverHooks.beforeSetup === 'function') {
    await serverHooks.beforeSetup(honoApp, { envParser, logger });
  }
`;
			afterSetupCall = `
  // Call afterSetup hook if defined
  if (typeof serverHooks.afterSetup === 'function') {
    await serverHooks.afterSetup(honoApp, { envParser, logger });
  }
`;
		}
		const telescopeWebSocketSetupCode = telescopeWebSocketEnabled ? `
  // Setup WebSocket for real-time telescope updates
  try {
    const { createNodeWebSocket } = await import('@hono/node-ws');
    const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app: honoApp });
    // Add WebSocket route directly to main app (sub-app routes don't support WS upgrade)
    honoApp.get('${context.telescope?.path}/ws', upgradeWebSocket(() => ({
      onOpen: (_event: Event, ws: any) => {
        telescope.addWsClient(ws);
      },
      onClose: (_event: Event, ws: any) => {
        telescope.removeWsClient(ws);
      },
      onMessage: (event: MessageEvent, ws: any) => {
        try {
          const data = JSON.parse(event.data);
          if (data.type === 'ping') {
            ws.send(JSON.stringify({ type: 'pong' }));
          }
        } catch {
          // Ignore invalid messages
        }
      },
    })));
    // Store injectWebSocket for server entry to call after serve()
    (honoApp as any).__injectWebSocket = injectWebSocket;
    logger.info('Telescope WebSocket enabled');
  } catch (e) {
    logger.warn({ error: e }, 'WebSocket support not available - install @hono/node-ws for real-time updates');
  }
` : "";
		let telescopeSetup = "";
		if (telescopeEnabled) if (usesExternalTelescope) telescopeSetup = `
${telescopeWebSocketSetupCode}
  // Add telescope middleware (before endpoints to capture all requests)
  honoApp.use('*', createMiddleware(telescope));

  // Mount telescope UI
  const telescopeUI = createUI(telescope);
  honoApp.route('${context.telescope?.path}', telescopeUI);
`;
		else telescopeSetup = `
  // Setup Telescope for debugging/monitoring
  const telescopeStorage = new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} });
  const telescope = new Telescope({
    enabled: true,
    path: '${context.telescope?.path}',
    ignorePatterns: ${JSON.stringify(context.telescope?.ignore)},
    recordBody: ${context.telescope?.recordBody},
    storage: telescopeStorage,
  });
${telescopeWebSocketSetupCode}
  // Add telescope middleware (before endpoints to capture all requests)
  honoApp.use('*', createMiddleware(telescope));

  // Mount telescope UI
  const telescopeUI = createUI(telescope);
  honoApp.route('${context.telescope?.path}', telescopeUI);
`;
		let studioSetup = "";
		if (studioEnabled && usesExternalStudio) studioSetup = `
  // Mount Studio data browser UI
  const studioApp = createStudioApp(studio);
  honoApp.route('${context.studio?.path}', studioApp);
`;
		const content = `/**
 * Generated server application
 *
 * ⚠️  WARNING: This is for LOCAL DEVELOPMENT ONLY
 * The subscriber polling mechanism is not production-ready.
 * For production, use AWS Lambda with SQS/SNS event sources.
 */
import { Hono } from 'hono';
import type { Hono as HonoType } from 'hono';
import { setupEndpoints } from './endpoints.js';
import { setupSubscribers } from './subscribers.js';
import ${context.envParserImportPattern} from '${relativeEnvParserPath}';
import ${context.loggerImportPattern} from '${relativeLoggerPath}';
${telescopeImports}
${studioImports}
${hooksImports}

export interface ServerApp {
  app: HonoType;
  start: (options?: {
    port?: number;
    serve: (app: HonoType, port: number) => void | Promise<void>;
  }) => Promise<void>;
}

/**
 * Create and configure the Hono application
 *
 * @param app - Optional Hono app instance to configure (creates new one if not provided)
 * @param enableOpenApi - Enable OpenAPI documentation (default: true)
 * @returns Server app with configured Hono app and start function
 *
 * @example
 * // With Bun
 * import { createApp } from './.gkm/server/app.js';
 *
 * const { app, start } = await createApp();
 *
 * await start({
 *   port: 3000,
 *   serve: (app, port) => {
 *     Bun.serve({ port, fetch: app.fetch });
 *   }
 * });
 *
 * @example
 * // With Node.js (using @hono/node-server)
 * import { serve } from '@hono/node-server';
 * import { createApp } from './.gkm/server/app.js';
 *
 * const { app, start } = await createApp();
 *
 * await start({
 *   port: 3000,
 *   serve: (app, port) => {
 *     serve({ fetch: app.fetch, port });
 *   }
 * });
 */
export async function createApp(app?: HonoType, enableOpenApi: boolean = true): Promise<ServerApp> {
  const honoApp = app || new Hono();
${telescopeSetup}${beforeSetupCall}${studioSetup}
  // Setup HTTP endpoints
  await setupEndpoints(honoApp, envParser, logger, enableOpenApi);
${afterSetupCall}

  return {
    app: honoApp,
    async start(options) {
      if (!options?.serve) {
        throw new Error(
          'serve function is required. Pass a serve function for your runtime:\\n' +
          '  - Bun: (app, port) => Bun.serve({ port, fetch: app.fetch })\\n' +
          '  - Node: (app, port) => serve({ fetch: app.fetch, port })'
        );
      }

      const port = options.port ?? 3000;

      // Start subscribers in background (non-blocking, local development only)
      await setupSubscribers(envParser, logger).catch((error) => {
        logger.error({ error }, 'Failed to start subscribers');
      });

      logger.info({ port }, 'Starting server');

      // Start HTTP server using provided serve function
      await options.serve(honoApp, port);

      logger.info({ port }, 'Server started');
    }
  };
}

// Default export for convenience
export default createApp;
`;
		await (0, node_fs_promises.writeFile)(appPath, content);
		return appPath;
	}
	generateAWSApiGatewayV1Handler(importPath, exportName, envParserPath, envParserImportPattern) {
		return `import { AmazonApiGatewayV1Endpoint } from '@geekmidas/constructs/aws';
import { ${exportName} } from '${importPath}';
import ${envParserImportPattern} from '${envParserPath}';

const adapter = new AmazonApiGatewayV1Endpoint(envParser, ${exportName});

export const handler = adapter.handler;
`;
	}
	generateAWSApiGatewayV2Handler(importPath, exportName, envParserPath, envParserImportPattern) {
		return `import { AmazonApiGatewayV2Endpoint } from '@geekmidas/constructs/aws';
import { ${exportName} } from '${importPath}';
import ${envParserImportPattern} from '${envParserPath}';

const adapter = new AmazonApiGatewayV2Endpoint(envParser, ${exportName});

export const handler = adapter.handler;
`;
	}
	generateServerHandler(importPath, exportName) {
		return `import { ${exportName} } from '${importPath}';

// Server handler - implement based on your server framework
export const handler = ${exportName};
`;
	}
	/**
	* Generate a production-optimized app.ts file
	* No dev tools (Telescope, Studio, WebSocket), includes health checks and graceful shutdown
	*/
	async generateProductionAppFile(outputDir, context) {
		const appFileName = "app.ts";
		const appPath = (0, node_path.join)(outputDir, appFileName);
		const relativeLoggerPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.loggerPath);
		const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.envParserPath);
		const production = context.production;
		const healthCheckPath = production.healthCheck;
		const enableGracefulShutdown = production.gracefulShutdown;
		const enableOpenApi = production.openapi;
		const includeSubscribers = production.subscribers === "include";
		let hooksImports = "";
		let beforeSetupCall = "";
		let afterSetupCall = "";
		if (context.hooks?.serverHooksPath) {
			const relativeHooksPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath);
			hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
			beforeSetupCall = `
  // Call beforeSetup hook if defined
  if (typeof serverHooks.beforeSetup === 'function') {
    await serverHooks.beforeSetup(honoApp, { envParser, logger });
  }
`;
			afterSetupCall = `
  // Call afterSetup hook if defined
  if (typeof serverHooks.afterSetup === 'function') {
    await serverHooks.afterSetup(honoApp, { envParser, logger });
  }
`;
		}
		const subscriberSetup = includeSubscribers ? `
      // Start subscribers in background
      await setupSubscribers(envParser, logger).catch((error) => {
        logger.error({ error }, 'Failed to start subscribers');
      });
` : "";
		const subscriberImport = includeSubscribers ? `import { setupSubscribers } from './subscribers.js';` : "";
		const gracefulShutdownCode = enableGracefulShutdown ? `
  // Graceful shutdown handling
  let isShuttingDown = false;

  const shutdown = async () => {
    if (isShuttingDown) return;
    isShuttingDown = true;
    logger.info('Graceful shutdown initiated');
    // Allow in-flight requests to complete (30s timeout)
    setTimeout(() => process.exit(0), 30000);
  };

  process.on('SIGTERM', shutdown);
  process.on('SIGINT', shutdown);
` : "";
		const endpointsImportPath = production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js";
		const content = `/**
 * Generated production server application
 *
 * This is a production-optimized build without dev tools.
 * - No Telescope debugging dashboard
 * - No Studio database browser
 * - No WebSocket updates
 * - Includes health checks and graceful shutdown
 */
import { Hono } from 'hono';
import type { Hono as HonoType } from 'hono';
import { setupEndpoints } from '${endpointsImportPath}';
${subscriberImport}
import ${context.envParserImportPattern} from '${relativeEnvParserPath}';
import ${context.loggerImportPattern} from '${relativeLoggerPath}';
${hooksImports}

export interface ServerApp {
  app: HonoType;
  start: (options?: {
    port?: number;
    serve: (app: HonoType, port: number) => void | Promise<void>;
  }) => Promise<void>;
}

/**
 * Create and configure the production Hono application
 */
export async function createApp(app?: HonoType): Promise<ServerApp> {
  const honoApp = app || new Hono();

  // Health check endpoint (always first)
  honoApp.get('${healthCheckPath}', (c) => c.json({ status: 'ok', timestamp: Date.now() }));
  honoApp.get('/ready', (c) => c.json({ ready: true }));
${beforeSetupCall}
  // Setup HTTP endpoints (OpenAPI: ${enableOpenApi})
  await setupEndpoints(honoApp, envParser, logger, ${enableOpenApi});
${afterSetupCall}
  return {
    app: honoApp,
    async start(options) {
      if (!options?.serve) {
        throw new Error(
          'serve function is required. Pass a serve function for your runtime:\\n' +
          '  - Bun: (app, port) => Bun.serve({ port, fetch: app.fetch })\\n' +
          '  - Node: (app, port) => serve({ fetch: app.fetch, port })'
        );
      }

      const port = options.port ?? Number(process.env.PORT) ?? 3000;
${gracefulShutdownCode}${subscriberSetup}
      logger.info({ port }, 'Starting production server');

      // Start HTTP server using provided serve function
      await options.serve(honoApp, port);

      logger.info({ port }, 'Production server started');
    }
  };
}

// Default export for convenience
export default createApp;
`;
		await (0, node_fs_promises.writeFile)(appPath, content);
		await this.generateProductionServerEntry(outputDir);
		return appPath;
	}
	/**
	* Generate production server.ts entry point
	*/
	async generateProductionServerEntry(outputDir) {
		const serverPath = (0, node_path.join)(outputDir, "server.ts");
		const content = `#!/usr/bin/env node
/**
 * Production server entry point
 * Generated by 'gkm build --provider server --production'
 */
import { serve } from '@hono/node-server';
import { createApp } from './app.js';

const port = Number(process.env.PORT) || 3000;

const { start } = await createApp();

await start({
  port,
  serve: (app, port) => { serve({ fetch: app.fetch, port }); },
});
`;
		await (0, node_fs_promises.writeFile)(serverPath, content);
	}
};

//#endregion
//#region src/generators/OpenApiTsGenerator.ts
/**
* Generates TypeScript OpenAPI module from endpoints.
* Outputs:
* - securitySchemes: typed security scheme definitions
* - endpointAuth: runtime map of endpoints to auth requirements
* - paths: TypeScript interface for type-safe fetcher
* - schema interfaces: reusable TypeScript types from Zod/Valibot schemas
*/
var OpenApiTsGenerator = class {
	async generate(endpoints, options = {}) {
		const { title = "API", version = "1.0.0", description } = options;
		const endpointInfos = await this.extractEndpointInfos(endpoints);
		const securitySchemes = this.collectSecuritySchemes(endpointInfos);
		const endpointAuth = this.buildEndpointAuthMap(endpointInfos);
		const schemaInterfaces = await this.generateSchemaInterfaces(endpointInfos);
		const pathsInterface = await this.generatePathsInterface(endpointInfos);
		return this.buildModule({
			title,
			version,
			description,
			securitySchemes,
			endpointAuth,
			schemaInterfaces,
			pathsInterface
		});
	}
	async extractEndpointInfos(endpoints) {
		return endpoints.map((ep) => {
			const route = ep.route.replace(/:(\w+)/g, "{$1}");
			const method = ep.method.toUpperCase();
			const securityScheme = ep.authorizer?.securityScheme;
			return {
				endpoint: `${method} ${route}`,
				route,
				method,
				authorizerName: ep.authorizer?.name ?? null,
				authorizerType: ep.authorizer?.type ?? null,
				securityScheme: securityScheme ?? null,
				input: ep.input,
				output: ep.outputSchema,
				description: ep.description,
				tags: ep.tags,
				operationId: ep.operationId
			};
		});
	}
	collectSecuritySchemes(endpointInfos) {
		const schemes = /* @__PURE__ */ new Map();
		for (const info of endpointInfos) if (info.authorizerName && !schemes.has(info.authorizerName)) {
			const scheme = info.securityScheme ?? (info.authorizerType ? this.mapAuthorizerToSecurityScheme(info.authorizerType, info.authorizerName) : null);
			if (scheme) schemes.set(info.authorizerName, {
				name: info.authorizerName,
				type: scheme.type,
				scheme
			});
		}
		return Array.from(schemes.values());
	}
	mapAuthorizerToSecurityScheme(type, _name) {
		switch (type.toLowerCase()) {
			case "jwt":
			case "bearer": return {
				type: "http",
				scheme: "bearer",
				bearerFormat: "JWT"
			};
			case "iam":
			case "aws-sigv4":
			case "sigv4": return {
				type: "apiKey",
				in: "header",
				name: "Authorization",
				"x-amazon-apigateway-authtype": "awsSigv4"
			};
			case "apikey":
			case "api-key": return {
				type: "apiKey",
				in: "header",
				name: "X-API-Key"
			};
			case "oauth2": return {
				type: "oauth2",
				flows: {}
			};
			case "oidc":
			case "openidconnect": return {
				type: "openIdConnect",
				openIdConnectUrl: ""
			};
			default: return {
				type: "http",
				scheme: "bearer"
			};
		}
	}
	buildEndpointAuthMap(endpointInfos) {
		const authMap = {};
		for (const info of endpointInfos) authMap[info.endpoint] = info.authorizerName;
		return authMap;
	}
	async generateSchemaInterfaces(endpointInfos) {
		const interfaces = [];
		const generatedNames = /* @__PURE__ */ new Set();
		const collectedDefs = /* @__PURE__ */ new Map();
		for (const info of endpointInfos) {
			const baseName = this.getSchemaBaseName(info);
			if (info.input?.body) {
				const name = await this.getSchemaName(info.input.body, `${baseName}Input`);
				if (!generatedNames.has(name)) {
					const schema = await this.schemaToInterfaceWithDefs(info.input.body, name, collectedDefs);
					if (schema) {
						interfaces.push(schema);
						generatedNames.add(name);
					}
				}
			}
			if (info.input?.params) {
				const name = await this.getSchemaName(info.input.params, `${baseName}Params`);
				if (!generatedNames.has(name)) {
					const schema = await this.schemaToInterfaceWithDefs(info.input.params, name, collectedDefs);
					if (schema) {
						interfaces.push(schema);
						generatedNames.add(name);
					}
				}
			}
			if (info.input?.query) {
				const name = await this.getSchemaName(info.input.query, `${baseName}Query`);
				if (!generatedNames.has(name)) {
					const schema = await this.schemaToInterfaceWithDefs(info.input.query, name, collectedDefs);
					if (schema) {
						interfaces.push(schema);
						generatedNames.add(name);
					}
				}
			}
			if (info.output) {
				const name = await this.getSchemaName(info.output, `${baseName}Output`);
				if (!generatedNames.has(name)) {
					const schema = await this.schemaToInterfaceWithDefs(info.output, name, collectedDefs);
					if (schema) {
						interfaces.push(schema);
						generatedNames.add(name);
					}
				}
			}
		}
		for (const [defName, defSchema] of collectedDefs) if (!generatedNames.has(defName)) {
			const interfaceStr = this.jsonSchemaToInterface(defSchema, defName);
			interfaces.push(interfaceStr);
			generatedNames.add(defName);
		}
		return interfaces.join("\n\n");
	}
	/**
	* Get the name for a schema, using metadata `id` if available,
	* otherwise falling back to the provided default name.
	*/
	async getSchemaName(schema, defaultName) {
		try {
			const metadata = await (0, __geekmidas_schema_conversion.getSchemaMetadata)(schema);
			if (metadata?.id) return this.pascalCase(metadata.id);
		} catch {}
		return defaultName;
	}
	getSchemaBaseName(info) {
		if (info.operationId) return this.pascalCase(info.operationId);
		const routeParts = info.route.replace(/[{}]/g, "").split("/").filter(Boolean).map((part) => this.pascalCase(part));
		return `${this.pascalCase(info.method.toLowerCase())}${routeParts.join("")}`;
	}
	pascalCase(str) {
		return str.replace(/[-_](.)/g, (_, c) => c.toUpperCase()).replace(/^./, (c) => c.toUpperCase());
	}
	/**
	* Convert schema to interface while collecting $defs for nested schemas
	* with .meta({ id: 'X' }).
	*/
	async schemaToInterfaceWithDefs(schema, name, collectedDefs) {
		try {
			const vendor = schema["~standard"]?.vendor;
			if (!vendor || !(vendor in __geekmidas_schema_conversion.StandardSchemaJsonSchema)) return null;
			const toJsonSchema = __geekmidas_schema_conversion.StandardSchemaJsonSchema[vendor];
			const jsonSchema = await toJsonSchema(schema);
			if (!jsonSchema) return null;
			if (jsonSchema.$defs && typeof jsonSchema.$defs === "object") {
				for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) if (!collectedDefs.has(defName)) {
					const { id,...schemaWithoutId } = defSchema;
					collectedDefs.set(defName, schemaWithoutId);
				}
			}
			const { $defs,...schemaWithoutDefs } = jsonSchema;
			return this.jsonSchemaToInterface(schemaWithoutDefs, name);
		} catch {
			return null;
		}
	}
	jsonSchemaToInterface(schema, name) {
		if (schema.type !== "object" || !schema.properties) {
			const typeStr = this.jsonSchemaTypeToTs(schema);
			return `export type ${name} = ${typeStr};`;
		}
		const props = [];
		const required = new Set(schema.required || []);
		for (const [propName, propSchema] of Object.entries(schema.properties)) {
			const isRequired = required.has(propName);
			const typeStr = this.jsonSchemaTypeToTs(propSchema);
			const optionalMark = isRequired ? "" : "?";
			props.push(`  ${propName}${optionalMark}: ${typeStr};`);
		}
		return `export interface ${name} {\n${props.join("\n")}\n}`;
	}
	jsonSchemaTypeToTs(schema) {
		if (!schema) return "unknown";
		if (schema.$ref) {
			const refName = schema.$ref.split("/").pop() || "unknown";
			return refName;
		}
		if (schema.anyOf) return schema.anyOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
		if (schema.oneOf) return schema.oneOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
		if (schema.allOf) return schema.allOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" & ");
		switch (schema.type) {
			case "string":
				if (schema.enum) return schema.enum.map((e) => `'${e}'`).join(" | ");
				return "string";
			case "number":
			case "integer": return "number";
			case "boolean": return "boolean";
			case "null": return "null";
			case "array":
				if (schema.items) return `Array<${this.jsonSchemaTypeToTs(schema.items)}>`;
				return "Array<unknown>";
			case "object":
				if (schema.properties) {
					const props = [];
					const required = new Set(schema.required || []);
					for (const [propName, propSchema] of Object.entries(schema.properties)) {
						const isRequired = required.has(propName);
						const typeStr = this.jsonSchemaTypeToTs(propSchema);
						const optionalMark = isRequired ? "" : "?";
						props.push(`${propName}${optionalMark}: ${typeStr}`);
					}
					return `{ ${props.join("; ")} }`;
				}
				if (schema.additionalProperties) {
					const valueType = this.jsonSchemaTypeToTs(schema.additionalProperties);
					return `Record<string, ${valueType}>`;
				}
				return "Record<string, unknown>";
			default: return "unknown";
		}
	}
	async generatePathsInterface(endpointInfos) {
		const pathGroups = /* @__PURE__ */ new Map();
		for (const info of endpointInfos) {
			const existing = pathGroups.get(info.route) || [];
			existing.push(info);
			pathGroups.set(info.route, existing);
		}
		const pathEntries = [];
		for (const [route, infos] of pathGroups) {
			const methodEntries = [];
			for (const info of infos) {
				const methodDef = await this.generateMethodDefinition(info);
				methodEntries.push(`    ${info.method.toLowerCase()}: ${methodDef};`);
			}
			const firstWithParams = infos.find((i) => i.input?.params);
			let paramsEntry = "";
			if (firstWithParams?.input?.params) {
				const paramsName = await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`);
				paramsEntry = `\n    parameters: {\n      path: ${paramsName};\n    };`;
			}
			pathEntries.push(`  '${route}': {${paramsEntry}\n${methodEntries.join("\n")}\n  };`);
		}
		return `export interface paths {\n${pathEntries.join("\n")}\n}`;
	}
	async generateMethodDefinition(info) {
		const parts = [];
		const baseName = this.getSchemaBaseName(info);
		if (info.input?.body) {
			const bodyName = await this.getSchemaName(info.input.body, `${baseName}Input`);
			parts.push(`requestBody: {
        content: {
          'application/json': ${bodyName};
        };
      }`);
		}
		if (info.input?.query) {
			const queryName = await this.getSchemaName(info.input.query, `${baseName}Query`);
			parts.push(`parameters: {
        query: ${queryName};
      }`);
		}
		const outputName = info.output ? await this.getSchemaName(info.output, `${baseName}Output`) : "unknown";
		parts.push(`responses: {
        200: {
          content: {
            'application/json': ${outputName};
          };
        };
      }`);
		return `{\n      ${parts.join(";\n      ")};\n    }`;
	}
	buildModule(params) {
		const { title, version, description, securitySchemes, endpointAuth, schemaInterfaces, pathsInterface } = params;
		const securitySchemesObj = securitySchemes.reduce((acc, s) => {
			acc[s.name] = s.scheme;
			return acc;
		}, {});
		const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(" | ");
		const hasSecuritySchemes = schemeNames.length > 0;
		const createApiSection = hasSecuritySchemes ? `
// ============================================================
// API Client Factory
// ============================================================

import {
  createAuthAwareFetcher,
  type AuthStrategy,
} from '@geekmidas/client/auth-fetcher';
import { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';
import type { QueryClient } from '@tanstack/react-query';

/**
 * Options for creating the API client.
 */
export interface CreateApiOptions {
  /** Base URL for all API requests (required) */
  baseURL: string;
  /** Auth strategies for each security scheme used in this API */
  authStrategies: Record<SecuritySchemeId, AuthStrategy>;
  /** Optional React Query client instance */
  queryClient?: QueryClient;
  /** Optional request interceptor */
  onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;
}

/**
 * Create a type-safe API client with authentication and React Query hooks.
 *
 * @example
 * \`\`\`typescript
 * const api = createApi({
 *   baseURL: 'https://api.example.com',
 *   authStrategies: {
 *     jwt: { type: 'bearer', tokenProvider },
 *   },
 * });
 *
 * // Imperative fetch
 * const user = await api('GET /users/{id}', { params: { id: '123' } });
 *
 * // React Query hooks
 * const { data } = api.useQuery('GET /users/{id}', { params: { id: '123' } });
 * const mutation = api.useMutation('POST /users');
 * \`\`\`
 */
export function createApi(options: CreateApiOptions) {
  const fetcher = createAuthAwareFetcher<paths, typeof endpointAuth, typeof securitySchemes>({
    baseURL: options.baseURL,
    endpointAuth,
    securitySchemes,
    authStrategies: options.authStrategies,
    onRequest: options.onRequest,
  });

  const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });

  return Object.assign(fetcher, hooks);
}
` : `
// ============================================================
// API Client Factory
// ============================================================

import { createTypedFetcher, type FetcherOptions } from '@geekmidas/client/fetcher';
import { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';
import type { QueryClient } from '@tanstack/react-query';

/**
 * Options for creating the API client.
 */
export interface CreateApiOptions extends Omit<FetcherOptions, 'baseURL'> {
  /** Base URL for all API requests (required) */
  baseURL: string;
  /** Optional React Query client instance */
  queryClient?: QueryClient;
}

/**
 * Create a type-safe API client with React Query hooks.
 *
 * @example
 * \`\`\`typescript
 * const api = createApi({
 *   baseURL: 'https://api.example.com',
 * });
 *
 * // Imperative fetch
 * const data = await api('GET /health');
 *
 * // React Query hooks
 * const { data } = api.useQuery('GET /health');
 * \`\`\`
 */
export function createApi(options: CreateApiOptions) {
  const { queryClient, ...fetcherOptions } = options;
  const request = createTypedFetcher<paths>(fetcherOptions);

  const hooks = createEndpointHooks<paths>(request, { queryClient });

  return Object.assign(request, hooks);
}
`;
		return `// Auto-generated by @geekmidas/cli - DO NOT EDIT

// ============================================================
// Security Scheme Type
// ============================================================

interface SecuritySchemeObject {
  type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';
  description?: string;
  name?: string;
  in?: 'query' | 'header' | 'cookie';
  scheme?: string;
  bearerFormat?: string;
  flows?: Record<string, unknown>;
  openIdConnectUrl?: string;
  [key: string]: unknown;
}

// ============================================================
// API Info
// ============================================================

export const apiInfo = {
  title: '${title}',
  version: '${version}',${description ? `\n  description: '${description.replace(/'/g, "\\'")}',` : ""}
} as const;

// ============================================================
// Security Schemes
// ============================================================

/**
 * Available security schemes for this API.
 * Maps authorizer names to OpenAPI security scheme definitions.
 */
export const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/"([a-zA-Z_$][a-zA-Z0-9_$]*)":/g, "$1:")} as const satisfies Record<string, SecuritySchemeObject>;

export type SecuritySchemeId = ${schemeNames || "never"};

// ============================================================
// Endpoint Authentication Map
// ============================================================

/**
 * Runtime map of endpoints to their required authentication scheme.
 * \`null\` indicates a public endpoint (no auth required).
 */
export const endpointAuth = ${JSON.stringify(endpointAuth, null, 2).replace(/"([^"]+)":/g, "'$1':")} as const satisfies Record<string, SecuritySchemeId | null>;

export type EndpointString = keyof typeof endpointAuth;

export type AuthenticatedEndpoint = {
  [K in EndpointString]: typeof endpointAuth[K] extends null ? never : K;
}[EndpointString];

export type PublicEndpoint = {
  [K in EndpointString]: typeof endpointAuth[K] extends null ? K : never;
}[EndpointString];

// ============================================================
// Schema Definitions
// ============================================================

${schemaInterfaces}

// ============================================================
// OpenAPI Paths
// ============================================================

${pathsInterface}
${createApiSection}
`;
	}
};

//#endregion
//#region src/workspace/client-generator.ts
/**
* Normalize routes to an array of patterns.
* Handles string, string[], and PartitionedRoutes (extracts paths).
* @internal Exported for use in dev command
*/
function normalizeRoutes(routes) {
	if (!routes) return [];
	if (isPartitionedRoutes(routes)) return Array.isArray(routes.paths) ? routes.paths : [routes.paths];
	return Array.isArray(routes) ? routes : [routes];
}

//#endregion
//#region src/openapi.ts
/**
* Default output path for generated OpenAPI client (used for single-app configs)
*/
const OPENAPI_OUTPUT_PATH = "./.gkm/openapi.ts";
/**
* Resolve OpenAPI config from GkmConfig
*/
function resolveOpenApiConfig(config) {
	if (config.openapi === false) return { enabled: false };
	if (config.openapi === true || config.openapi === void 0) return {
		enabled: true,
		title: "API Documentation",
		version: "1.0.0",
		description: "Auto-generated API documentation from endpoints"
	};
	return {
		enabled: config.openapi.enabled !== false,
		title: config.openapi.title || "API Documentation",
		version: config.openapi.version || "1.0.0",
		description: config.openapi.description || "Auto-generated API documentation from endpoints"
	};
}
/**
* Generate OpenAPI spec from endpoints
* @returns Object with output path and endpoint count, or null if disabled
*/
async function generateOpenApi(config, options = {}) {
	const logger = options.silent ? { log: () => {} } : console;
	const openApiConfig = resolveOpenApiConfig(config);
	if (!openApiConfig.enabled) return null;
	const endpointGenerator = new EndpointGenerator();
	const loadedEndpoints = await endpointGenerator.load(config.routes, void 0, options.bustCache);
	if (loadedEndpoints.length === 0) {
		logger.log("No valid endpoints found for OpenAPI generation");
		return null;
	}
	const endpoints = loadedEndpoints.map(({ construct }) => construct);
	const outputPath = (0, node_path.join)(process.cwd(), OPENAPI_OUTPUT_PATH);
	await (0, node_fs_promises.mkdir)((0, node_path.dirname)(outputPath), { recursive: true });
	const tsGenerator = new OpenApiTsGenerator();
	const tsContent = await tsGenerator.generate(endpoints, {
		title: openApiConfig.title,
		version: openApiConfig.version,
		description: openApiConfig.description
	});
	await (0, node_fs_promises.writeFile)(outputPath, tsContent);
	logger.log(`📄 OpenAPI client generated: ${OPENAPI_OUTPUT_PATH}`);
	return {
		outputPath,
		endpointCount: loadedEndpoints.length
	};
}
async function openapiCommand(options = {}) {
	const logger = console;
	try {
		const loadedConfig = await require_config.loadWorkspaceConfig(options.cwd);
		if (loadedConfig.type === "single") {
			const config = loadedConfig.raw;
			if (!config.openapi) config.openapi = { enabled: true };
			const result = await generateOpenApi(config);
			if (result) logger.log(`Found ${result.endpointCount} endpoints`);
		} else {
			const { workspace } = loadedConfig;
			const workspaceRoot = options.cwd || process.cwd();
			const backendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "backend" && (app.openapi === true || typeof app.openapi === "object" && app.openapi.enabled !== false));
			if (backendApps.length === 0) {
				logger.log("No backend apps with OpenAPI enabled found");
				return;
			}
			const frontendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "frontend" && app.client?.output);
			for (const [appName, app] of backendApps) {
				if (app.type !== "backend" || !app.routes) continue;
				const appPath = (0, node_path.join)(workspaceRoot, app.path);
				const routes = normalizeRoutes(app.routes);
				const routesGlob = routes.map((r) => (0, node_path.join)(appPath, r));
				const gkmConfig = {
					routes: routesGlob,
					envParser: app.envParser || "",
					logger: app.logger || "",
					openapi: app.openapi
				};
				const originalCwd = process.cwd();
				process.chdir(appPath);
				const result = await generateOpenApi(gkmConfig, { silent: true });
				process.chdir(originalCwd);
				if (result) {
					logger.log(`📄 [${appName}] Generated OpenAPI (${result.endpointCount} endpoints)`);
					for (const [frontendName, frontendApp] of frontendApps) {
						if (frontendApp.type !== "frontend") continue;
						const dependsOnBackend = !frontendApp.dependencies || frontendApp.dependencies.includes(appName);
						if (dependsOnBackend && frontendApp.client?.output) {
							const frontendPath = (0, node_path.join)(workspaceRoot, frontendApp.path);
							const clientOutputPath = (0, node_path.join)(frontendPath, frontendApp.client.output, "openapi.ts");
							await (0, node_fs_promises.mkdir)((0, node_path.dirname)(clientOutputPath), { recursive: true });
							const { readFile: readFile$1 } = await import("node:fs/promises");
							const content = await readFile$1(result.outputPath, "utf-8");
							await (0, node_fs_promises.writeFile)(clientOutputPath, content);
							logger.log(`   → [${frontendName}] ${frontendApp.client.output}/openapi.ts`);
						}
					}
				}
			}
		}
	} catch (error) {
		throw new Error(`OpenAPI generation failed: ${error.message}`);
	}
}

//#endregion
Object.defineProperty(exports, 'ConstructGenerator', {
  enumerable: true,
  get: function () {
    return ConstructGenerator;
  }
});
Object.defineProperty(exports, 'EndpointGenerator', {
  enumerable: true,
  get: function () {
    return EndpointGenerator;
  }
});
Object.defineProperty(exports, 'OPENAPI_OUTPUT_PATH', {
  enumerable: true,
  get: function () {
    return OPENAPI_OUTPUT_PATH;
  }
});
Object.defineProperty(exports, 'generateOpenApi', {
  enumerable: true,
  get: function () {
    return generateOpenApi;
  }
});
Object.defineProperty(exports, 'isPartitionedRoutes', {
  enumerable: true,
  get: function () {
    return isPartitionedRoutes;
  }
});
Object.defineProperty(exports, 'normalizeRoutes', {
  enumerable: true,
  get: function () {
    return normalizeRoutes;
  }
});
Object.defineProperty(exports, 'openapiCommand', {
  enumerable: true,
  get: function () {
    return openapiCommand;
  }
});
Object.defineProperty(exports, 'resolveOpenApiConfig', {
  enumerable: true,
  get: function () {
    return resolveOpenApiConfig;
  }
});
//# sourceMappingURL=openapi-CBU4TEi-.cjs.map