export var ProjectType;
(function (ProjectType) {
    ProjectType["DEFAULT"] = "DEFAULT";
    ProjectType["PREVIEW"] = "PREVIEW";
})(ProjectType || (ProjectType = {}));
export var DbtProjectType;
(function (DbtProjectType) {
    DbtProjectType["DBT"] = "dbt";
    DbtProjectType["DBT_CLOUD_IDE"] = "dbt_cloud_ide";
    DbtProjectType["GITHUB"] = "github";
    DbtProjectType["GITLAB"] = "gitlab";
    DbtProjectType["BITBUCKET"] = "bitbucket";
    DbtProjectType["AZURE_DEVOPS"] = "azure_devops";
    DbtProjectType["NONE"] = "none";
    DbtProjectType["MANIFEST"] = "manifest";
})(DbtProjectType || (DbtProjectType = {}));
export var WarehouseTypes;
(function (WarehouseTypes) {
    WarehouseTypes["BIGQUERY"] = "bigquery";
    WarehouseTypes["POSTGRES"] = "postgres";
    WarehouseTypes["REDSHIFT"] = "redshift";
    WarehouseTypes["SNOWFLAKE"] = "snowflake";
    WarehouseTypes["DATABRICKS"] = "databricks";
    WarehouseTypes["TRINO"] = "trino";
    WarehouseTypes["CLICKHOUSE"] = "clickhouse";
    WarehouseTypes["ATHENA"] = "athena";
    WarehouseTypes["DUCKDB"] = "duckdb";
})(WarehouseTypes || (WarehouseTypes = {}));
export var DuckdbConnectionType;
(function (DuckdbConnectionType) {
    DuckdbConnectionType["MOTHERDUCK"] = "motherduck";
    DuckdbConnectionType["DUCKLAKE"] = "ducklake";
})(DuckdbConnectionType || (DuckdbConnectionType = {}));
export var BigqueryAuthenticationType;
(function (BigqueryAuthenticationType) {
    BigqueryAuthenticationType["SSO"] = "sso";
    BigqueryAuthenticationType["PRIVATE_KEY"] = "private_key";
    BigqueryAuthenticationType["ADC"] = "adc";
})(BigqueryAuthenticationType || (BigqueryAuthenticationType = {}));
export const sensitiveCredentialsFieldNames = [
    'user',
    'password',
    'keyfileContents',
    'personalAccessToken',
    'privateKey',
    'privateKeyPass',
    'sshTunnelPrivateKey',
    'sslcert',
    'sslkey',
    'sslrootcert',
    'token',
    'refreshToken',
    'oauthClientId',
    'oauthClientSecret',
    'accessKeyId',
    'secretAccessKey',
];
export var DatabricksAuthenticationType;
(function (DatabricksAuthenticationType) {
    DatabricksAuthenticationType["PERSONAL_ACCESS_TOKEN"] = "personal_access_token";
    DatabricksAuthenticationType["OAUTH_M2M"] = "oauth_m2m";
    DatabricksAuthenticationType["OAUTH_U2M"] = "oauth_u2m";
})(DatabricksAuthenticationType || (DatabricksAuthenticationType = {}));
export var AthenaAuthenticationType;
(function (AthenaAuthenticationType) {
    AthenaAuthenticationType["ACCESS_KEY"] = "access_key";
    AthenaAuthenticationType["IAM_ROLE"] = "iam_role";
})(AthenaAuthenticationType || (AthenaAuthenticationType = {}));
export var DucklakeCatalogType;
(function (DucklakeCatalogType) {
    DucklakeCatalogType["POSTGRES"] = "postgres";
    DucklakeCatalogType["SQLITE"] = "sqlite";
    DucklakeCatalogType["DUCKDB"] = "duckdb";
})(DucklakeCatalogType || (DucklakeCatalogType = {}));
export var DucklakeDataPathType;
(function (DucklakeDataPathType) {
    DucklakeDataPathType["S3"] = "s3";
    DucklakeDataPathType["GCS"] = "gcs";
    DucklakeDataPathType["AZURE"] = "azure";
    DucklakeDataPathType["LOCAL"] = "local";
})(DucklakeDataPathType || (DucklakeDataPathType = {}));
/**
 * Rows created before the connectionType field was introduced are
 * MotherDuck-shaped DuckDB credentials. Default the field at decrypt time
 * so the discriminated union narrows correctly without a data migration.
 */
export const normalizeWarehouseCredentials = (credentials) => {
    if (credentials.type === WarehouseTypes.DUCKDB &&
        credentials
            .connectionType === undefined) {
        return {
            ...credentials,
            connectionType: DuckdbConnectionType.MOTHERDUCK,
        };
    }
    return credentials;
};
/**
 * Top-level sensitive-field stripping does not reach into the nested
 * catalog/dataPath objects, so call this after the generic strip to
 * scrub nested credentials from a CreateDuckdbDucklakeCredentials.
 */
export const stripDucklakeNestedSensitive = (credentials) => {
    const stripCatalog = (catalog) => {
        switch (catalog.type) {
            case DucklakeCatalogType.POSTGRES: {
                const { user, password, ...rest } = catalog;
                return rest;
            }
            case DucklakeCatalogType.SQLITE:
            case DucklakeCatalogType.DUCKDB:
                return catalog;
            default:
                return catalog;
        }
    };
    const stripDataPath = (dataPath) => {
        switch (dataPath.type) {
            case DucklakeDataPathType.S3: {
                const { accessKeyId, secretAccessKey, ...rest } = dataPath;
                return rest;
            }
            case DucklakeDataPathType.GCS: {
                const { hmacKeyId, hmacSecret, ...rest } = dataPath;
                return rest;
            }
            case DucklakeDataPathType.AZURE: {
                const { connectionString, accountKey, ...rest } = dataPath;
                return rest;
            }
            case DucklakeDataPathType.LOCAL:
                return dataPath;
            default:
                return dataPath;
        }
    };
    return {
        ...credentials,
        catalog: stripCatalog(credentials.catalog),
        dataPath: stripDataPath(credentials.dataPath),
    };
};
// TODO use enum instead
export var SnowflakeAuthenticationType;
(function (SnowflakeAuthenticationType) {
    SnowflakeAuthenticationType["PASSWORD"] = "password";
    SnowflakeAuthenticationType["PRIVATE_KEY"] = "private_key";
    SnowflakeAuthenticationType["SSO"] = "sso";
    SnowflakeAuthenticationType["EXTERNAL_BROWSER"] = "external_browser";
    SnowflakeAuthenticationType["NONE"] = "none";
})(SnowflakeAuthenticationType || (SnowflakeAuthenticationType = {}));
// Returns the timezone the column data is in when the query runs.
// Snowflake's dbt translator wraps timestamps with CONVERT_TIMEZONE('UTC', col),
// so columns are UTC unless `disableTimestampConversion` opts out of that wrap.
export const getColumnTimezone = (credentials) => {
    if (credentials.type === WarehouseTypes.SNOWFLAKE &&
        !credentials.disableTimestampConversion) {
        return 'UTC';
    }
    return credentials.dataTimezone ?? 'UTC';
};
export const maybeOverrideWarehouseConnection = (connection, overrides) => {
    const isBigquery = connection.type === WarehouseTypes.BIGQUERY;
    const overridesSchema = isBigquery
        ? { dataset: overrides.schema }
        : { schema: overrides.schema };
    return {
        ...connection,
        ...(overrides.schema ? overridesSchema : undefined),
    };
};
/**
 * Merges new warehouse credentials with base credentials, preserving advanced settings
 * like requireUserCredentials from the base credentials.
 *
 * This is useful when creating preview projects where we want to use new connection details
 * (like from dbt profiles) but preserve advanced configuration from the parent project.
 */
export const mergeWarehouseCredentials = (baseCredentials, newCredentials) => {
    // If types don't match, return newCredentials as-is (can't merge different warehouse types)
    if (baseCredentials.type !== newCredentials.type) {
        // eslint-disable-next-line no-console
        console.info(`Skipping merge of warehouse credentials due to differing types: ${baseCredentials.type} and ${newCredentials.type}`);
        return newCredentials;
    }
    // Edge case: if the warehouse is snowflake but with a different warehouse, return newCredentials as-is
    // This is to avoid enforcing requireUserCredentials on a different snowflake warehouse that might not have SSO enabled or different roles
    if (baseCredentials.type === WarehouseTypes.SNOWFLAKE &&
        newCredentials.type === WarehouseTypes.SNOWFLAKE &&
        baseCredentials.warehouse.toLowerCase().trim() !==
            newCredentials.warehouse.toLowerCase().trim()) {
        // eslint-disable-next-line no-console
        console.info(`Skipping merge of Snowflake credentials due to differing warehouse names: ${baseCredentials.warehouse} and ${newCredentials.warehouse}`);
        return newCredentials;
    }
    // Only add non sensitive fields from base credentials to avoid conflicts with authentication methods
    const keysToExclude = [
        ...sensitiveCredentialsFieldNames,
        'authenticationType',
    ];
    const filteredBaseCredentials = Object.fromEntries(Object.entries(baseCredentials).filter(([key]) => !keysToExclude.includes(key)));
    // We will use new credentials for connection, this might contain new authentication method
    // do not include all baseCredentials here, to avoid conflicts on authentication (that will cause a mix of serviceaccounts/sso/passwords)
    const merged = {
        ...filteredBaseCredentials, // We copy most of the base config from the parent project, including advanced settings
        ...newCredentials,
        // Keep requireUserCredentials from base credentials, since this is a security setting and should not be overridden
        requireUserCredentials: baseCredentials.requireUserCredentials ||
            newCredentials.requireUserCredentials,
    };
    return merged;
};
const DBT_ENVIRONMENT_VARIABLE_KEY_REGEX = /^DBT_[A-Z0-9_]*$/;
const LIGHTDASH_DBT_PROFILE_ENVIRONMENT_VARIABLE_KEY_REGEX = /^LIGHTDASH_DBT_PROFILE_VAR_[A-Z0-9_]+$/;
export const isAllowedDbtEnvironmentVariableKey = (key) => key.length === 0 || DBT_ENVIRONMENT_VARIABLE_KEY_REGEX.test(key);
const isAllowedDbtProcessEnvironmentVariableKey = (key) => DBT_ENVIRONMENT_VARIABLE_KEY_REGEX.test(key) ||
    LIGHTDASH_DBT_PROFILE_ENVIRONMENT_VARIABLE_KEY_REGEX.test(key);
export const getInvalidDbtEnvironmentVariableKeys = (environment) => (environment ?? [])
    .map(({ key }) => key)
    .filter((key) => !isAllowedDbtEnvironmentVariableKey(key));
export const filterDbtEnvironment = (environment) => Object.fromEntries(Object.entries(environment ?? {}).filter(([key]) => key.length > 0 &&
    isAllowedDbtProcessEnvironmentVariableKey(key)));
export var SupportedDbtVersions;
(function (SupportedDbtVersions) {
    SupportedDbtVersions["V1_4"] = "v1.4";
    SupportedDbtVersions["V1_5"] = "v1.5";
    SupportedDbtVersions["V1_6"] = "v1.6";
    SupportedDbtVersions["V1_7"] = "v1.7";
    SupportedDbtVersions["V1_8"] = "v1.8";
    SupportedDbtVersions["V1_9"] = "v1.9";
    SupportedDbtVersions["V1_10"] = "v1.10";
    SupportedDbtVersions["V1_11"] = "v1.11";
})(SupportedDbtVersions || (SupportedDbtVersions = {}));
// Make it an enum to avoid TSOA errors
export var DbtVersionOptionLatest;
(function (DbtVersionOptionLatest) {
    DbtVersionOptionLatest["LATEST"] = "latest";
})(DbtVersionOptionLatest || (DbtVersionOptionLatest = {}));
export function isDbtVersion110OrHigher(version) {
    if (!version) {
        return false;
    }
    // Get all enum values as an array in order
    const versions = Object.values(SupportedDbtVersions);
    const v110Index = versions.indexOf(SupportedDbtVersions.V1_10);
    const currentIndex = versions.indexOf(version);
    // If the current version is at or after v1.10 in the enum order
    return currentIndex >= v110Index;
}
export const getLatestSupportDbtVersion = () => {
    const versions = Object.values(SupportedDbtVersions);
    return versions[versions.length - 1];
};
export const DefaultSupportedDbtVersion = DbtVersionOptionLatest.LATEST;
export const isGitProjectType = (connection) => [
    DbtProjectType.GITHUB,
    DbtProjectType.GITLAB,
    DbtProjectType.BITBUCKET,
].includes(connection.type);
const isRemoteType = (connection) => [DbtProjectType.DBT, DbtProjectType.DBT_CLOUD_IDE].includes(connection.type);
export const maybeOverrideDbtConnection = (connection, overrides) => {
    // If manifest is provided, create a MANIFEST connection type
    if (overrides.manifest) {
        return {
            type: DbtProjectType.MANIFEST,
            manifest: overrides.manifest,
            hideRefreshButton: true,
        };
    }
    return {
        ...connection,
        ...(isGitProjectType(connection) && overrides.branch
            ? { branch: overrides.branch }
            : undefined),
        ...(!isRemoteType(connection) &&
            overrides.environment &&
            overrides.environment.length > 0
            ? { environment: overrides.environment }
            : undefined),
    };
};
//# sourceMappingURL=projects.js.map