import { z } from 'zod';
import { cosmiconfigSync } from 'cosmiconfig';
import { LogError, LogStatus } from '@memberjunction/core';
const explorer = cosmiconfigSync('mj', { searchStrategy: 'global' });
const userHandlingInfoSchema = z.object({
    autoCreateNewUsers: z.boolean().optional().default(false),
    newUserLimitedToAuthorizedDomains: z.boolean().optional().default(false),
    newUserAuthorizedDomains: z.array(z.string()).optional().default([]),
    newUserRoles: z.array(z.string()).optional().default([]),
    updateCacheWhenNotFound: z.boolean().optional().default(false),
    updateCacheWhenNotFoundDelay: z.number().optional().default(30000),
    contextUserForNewUserCreation: z.string().optional().default(''),
    CreateUserApplicationRecords: z.boolean().optional().default(false),
    UserApplications: z.array(z.string()).optional().default([]),
});
const databaseSettingsInfoSchema = z.object({
    connectionTimeout: z.number(),
    requestTimeout: z.number(),
    metadataCacheRefreshInterval: z.number(),
    dbReadOnlyUsername: z.string().optional(),
    dbReadOnlyPassword: z.string().optional(),
    connectionPool: z.object({
        max: z.number().optional().default(50),
        min: z.number().optional().default(5),
        idleTimeoutMillis: z.number().optional().default(30000),
        acquireTimeoutMillis: z.number().optional().default(30000),
    }).optional().default({}),
});
const viewingSystemInfoSchema = z.object({
    enableSmartFilters: z.boolean().optional(),
});
const restApiOptionsSchema = z.object({
    enabled: z.boolean().default(true),
    includeEntities: z.array(z.string()).optional(),
    excludeEntities: z.array(z.string()).optional(),
    includeSchemas: z.array(z.string()).optional(),
    excludeSchemas: z.array(z.string()).optional(),
});
const zodBooleanWithTransforms = () => {
    return z
        .union([z.boolean(), z.string(), z.number()])
        .optional()
        .default(false)
        .transform((v) => {
        if (typeof v === 'string') {
            return v === '1' || v.toLowerCase() === 'true';
        }
        else if (typeof v === 'number') {
            return v === 1;
        }
        else if (typeof v === 'boolean') {
            return v;
        }
        else {
            return false;
        }
    });
};
const askSkipInfoSchema = z.object({
    url: z.string().optional(),
    apiKey: z.string().optional(),
    orgID: z.string().optional(),
    organizationInfo: z.string().optional(),
    entitiesToSend: z
        .object({
        excludeSchemas: z.array(z.string()).optional(),
        includeEntitiesFromExcludedSchemas: z.array(z.string()).optional(),
    })
        .optional(),
    chatURL: z.string().optional(),
    learningCycleRunUponStartup: zodBooleanWithTransforms(),
    learningCycleEnabled: zodBooleanWithTransforms(),
    learningCycleURL: z.string().optional(),
    learningCycleIntervalInMinutes: z.coerce.number().optional(),
});
const sqlLoggingOptionsSchema = z.object({
    formatAsMigration: z.boolean().optional().default(false),
    statementTypes: z.enum(['queries', 'mutations', 'both']).optional().default('both'),
    batchSeparator: z.string().optional().default('GO'),
    prettyPrint: z.boolean().optional().default(true),
    logRecordChangeMetadata: z.boolean().optional().default(false),
    retainEmptyLogFiles: z.boolean().optional().default(false),
});
const sqlLoggingSchema = z.object({
    enabled: z.boolean().optional().default(false),
    defaultOptions: sqlLoggingOptionsSchema.optional().default({}),
    allowedLogDirectory: z.string().optional().default('./logs/sql'),
    maxActiveSessions: z.number().optional().default(5),
    autoCleanupEmptyFiles: z.boolean().optional().default(true),
    sessionTimeout: z.number().optional().default(3600000),
});
const authProviderSchema = z.object({
    name: z.string(),
    type: z.string(),
    issuer: z.string(),
    audience: z.string(),
    jwksUri: z.string(),
    clientId: z.string().optional(),
    clientSecret: z.string().optional(),
    tenantId: z.string().optional(),
    domain: z.string().optional(),
}).passthrough();
const componentRegistrySchema = z.object({
    id: z.string().optional(),
    name: z.string().optional(),
    apiKey: z.string().optional(),
    cache: z.boolean().optional().default(true),
    timeout: z.number().optional(),
    retryPolicy: z.object({
        maxRetries: z.number().optional(),
        initialDelay: z.number().optional(),
        maxDelay: z.number().optional(),
        backoffMultiplier: z.number().optional(),
    }).optional(),
    headers: z.record(z.string()).optional(),
}).passthrough();
const scheduledJobsSchema = z.object({
    enabled: z.boolean().optional().default(false),
    systemUserEmail: z.string().optional().default('system@memberjunction.org'),
    maxConcurrentJobs: z.number().optional().default(5),
    defaultLockTimeout: z.number().optional().default(600000),
    staleLockCleanupInterval: z.number().optional().default(300000),
});
const telemetrySchema = z.object({
    enabled: zodBooleanWithTransforms().default(process.env.MJ_TELEMETRY_ENABLED !== 'false'),
    level: z.enum(['minimal', 'standard', 'verbose', 'debug']).optional().default('standard'),
});
const configInfoSchema = z.object({
    userHandling: userHandlingInfoSchema,
    databaseSettings: databaseSettingsInfoSchema,
    viewingSystem: viewingSystemInfoSchema.optional(),
    restApiOptions: restApiOptionsSchema.optional().default({}),
    askSkip: askSkipInfoSchema.optional(),
    sqlLogging: sqlLoggingSchema.optional(),
    authProviders: z.array(authProviderSchema).optional(),
    componentRegistries: z.array(componentRegistrySchema).optional(),
    scheduledJobs: scheduledJobsSchema.optional().default({}),
    telemetry: telemetrySchema.optional().default({}),
    apiKey: z.string().optional(),
    baseUrl: z.string().default('http://localhost'),
    publicUrl: z.string().optional().default(process.env.MJAPI_PUBLIC_URL || ''),
    dbHost: z.string().default('localhost'),
    dbDatabase: z.string(),
    dbPort: z.number({ coerce: true }).default(1433),
    dbUsername: z.string(),
    dbPassword: z.string(),
    dbReadOnlyUsername: z.string().optional(),
    dbReadOnlyPassword: z.string().optional(),
    dbTrustServerCertificate: z.coerce
        .boolean()
        .default(false)
        .transform((v) => (v ? 'Y' : 'N')),
    dbInstanceName: z.string().optional(),
    graphqlPort: z.coerce.number().default(4000),
    ___codeGenAPIURL: z.string().optional(),
    ___codeGenAPIPort: z.coerce.number().optional().default(3999),
    ___codeGenAPISubmissionDelay: z.coerce.number().optional().default(5000),
    graphqlRootPath: z.string().optional().default('/'),
    enableIntrospection: z.coerce.boolean().optional().default(false),
    websiteRunFromPackage: z.coerce.number().optional(),
    userEmailMap: z
        .string()
        .transform((val) => z.record(z.string()).parse(JSON.parse(val)))
        .optional(),
    mjCoreSchema: z.string(),
});
export const configInfo = loadConfig();
export const { dbUsername, dbPassword, dbHost, dbDatabase, dbPort, dbTrustServerCertificate, dbInstanceName, graphqlPort, ___codeGenAPIURL, ___codeGenAPIPort, ___codeGenAPISubmissionDelay, graphqlRootPath, enableIntrospection, websiteRunFromPackage, userEmailMap, apiKey, baseUrl, publicUrl, mjCoreSchema: mj_core_schema, dbReadOnlyUsername, dbReadOnlyPassword, restApiOptions: RESTApiOptions, } = configInfo;
export function loadConfig() {
    const configSearchResult = explorer.search(process.cwd());
    if (configSearchResult.isEmpty) {
        throw new Error(`Config file ${configSearchResult.filepath} is empty or does not exist.`);
    }
    LogStatus(`Config file found at ${configSearchResult.filepath}`);
    const configParsing = configInfoSchema.safeParse(configSearchResult.config);
    if (!configParsing.success) {
        LogError('Error parsing config file', null, JSON.stringify(configParsing.error.issues, null, 2));
    }
    return configParsing.data;
}
//# sourceMappingURL=config.js.map