"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateMain = generateMain;
function generateMain({ backend: { modules }, schema }) {
    return /*ts*/ `

import fastifyCookie from '@fastify/cookie'
import cors from '@fastify/cors'
import helmet from '@fastify/helmet'
import { Logger, NestApplicationOptions } from '@nestjs/common'
import { NestFactory } from '@nestjs/core'
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'

import { yellow } from 'colors/safe'
import { fromError } from 'zod-validation-error'

import { checkPortAvailability,removeSecrets } from '@postxl/utils'
  

${modules
        .filter((m) => m.bootStrap)
        .map((m) => m.bootStrap.import)
        .join('\n')}

import { zApiConfigSchema } from './api.config'
import { ApiModule } from './api.module'
import { CompactConsoleLogger } from './console.logger'

//const isTest = process.env.NODE_ENV === 'test'

export async function bootstrap({ port, isTest, enableLog }: { port?: number; isTest?: boolean; enableLog: boolean }) {
  const logger = new Logger('Main')
  // Copy env so we do not accidentally change the global env in this instance
  const env = { ...process.env }
  if (port) {
    env.API_PORT = port.toString()
  }
  if (isTest) {
    env.NODE_ENV = 'test'
  }

  const config = zApiConfigSchema.safeParse(env)
  if (!config.success) {
    logger.error('Failed to parse API config', fromError(config.error).toString())
    process.exit(1)
  }

  if (enableLog) {
    logger.log('Starting API with config:', removeSecrets(config.data))
  }


  const portAvailable = await checkPortAvailability(config.data.port)
  if (!portAvailable) {
    logger.error(\`Port \${config.data.port} is already in use!\`)
    process.exit(1)
  }

  const logOptions: NestApplicationOptions = enableLog ? { bufferLogs: false } : { bufferLogs: true, logger: ['error'] }

  const app = await NestFactory.create<NestFastifyApplication>(
    ApiModule.forRoot({
      config: config.data,
    }),
    new FastifyAdapter({ logger: false }),
    logOptions,
  )

  if (enableLog) {
    app.useLogger(new CompactConsoleLogger(config.data.port))
  }

  app.setGlobalPrefix(config.data.urlPrefix)

  await app.register(fastifyCookie, { secret: config.data.appSecret })
  await app.register(helmet, {})

  await app.register(cors, {
    origin: (origin, callback) => {
      // Header value may be "null"
      // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin#syntax

      if (!origin || origin === 'null') {
        callback(null, true)
        return
      }

      if (process.env.NODE_ENV !== 'production') {
        callback(null, origin)
        return
      }

      if (config.data.allowOrigin === '*' || config.data.allowOrigin === '') {
        callback(null, origin)
        return
      }

      if (config.data.allowOrigin.includes(',')) {
        for (const allowedOrigin of config.data.allowOrigin.split(',')) {
          if (allowedOrigin.endsWith(origin)) {
            callback(null, origin)
            return
          }
        }
      } else if (origin.endsWith(config.data.allowOrigin)) {
        callback(null, origin)
        return
      }

      callback(new Error('Not allowed'), false)
    },
    methods: 'GET,HEAD,PUT,POST,DELETE',
    preflightContinue: false,
    credentials: true,
    optionsSuccessStatus: 204,
  })

  ${modules
        .filter((m) => m.bootStrap)
        .map((m) => m.bootStrap.code)
        .join('\n\n')}

  const server = await app.listen(config.data.port, '0.0.0.0')
  logger.log(\`${schema.name} API is running on \${yellow(config.data.port.toString())}\`)

  // handling shutdown signal, used in E2E testing
  process.on('SIGTERM', () => {
    logger.log('SIGTERM signal received: closing HTTP server')
    app.close().catch((err) => {
      logger.error(err)
      process.exit(1)
    })
    server.close(() => {
      logger.log('HTTP server closed')
      process.exit(0)
    })
    setTimeout(() => {
      logger.warn('Forcing process exit after timeout')
      process.exit(1)
    }, 10000).unref()
  })

  return app
}

// Start

// We prevent the app from being started other than by the main module - see https://chanind.github.io/2020/08/27/node-scripts-best-practices.html
if (require.main === module) {
  void bootstrap({ enableLog: true }) // NOSONAR - we will switch to top-level await later
}`;
}
//# sourceMappingURL=main.generator.js.map