diff --git a/src/index.ts b/src/index.ts index d0d3f6376e..59725952d5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,23 @@ -export * from './sqlFormatter'; +export { + format, + formatBigQuery, + formatDb2, + formatHive, + formatMariaDb, + formatMySql, + formatN1ql, + formatPlSql, + formatPostgreSql, + formatRedshift, + formatSpark, + formatSqlite, + formatStandardSQL, + formatTrino, + formatTransactSql, + formatSingleStoreDb, + formatSnowflake, +} from './sqlFormatter'; +export type { SqlLanguage, FormatFn } from './sqlFormatter'; export type { IndentStyle, KeywordCase, diff --git a/src/sqlFormatter.ts b/src/sqlFormatter.ts index 45b0409849..89aa8d6686 100644 --- a/src/sqlFormatter.ts +++ b/src/sqlFormatter.ts @@ -15,10 +15,11 @@ import TransactSqlFormatter from 'src/languages/transactsql/transactsql.formatte import SingleStoreDbFormatter from './languages/singlestoredb/singlestoredb.formatter'; import SnowflakeFormatter from './languages/snowflake/snowflake.formatter'; +import Formatter from './formatter/Formatter'; import { FormatOptions } from './FormatOptions'; -import { ParamItems } from './formatter/Params'; +import { ConfigError, validateConfig, validateQuery } from './validateConfigs'; -export const formatters = { +const formatters = { bigquery: BigQueryFormatter, db2: Db2Formatter, hive: HiveFormatter, @@ -62,9 +63,11 @@ const defaultOptions: FormatOptions = { * @param {FormatOptions} cfg Configuration options (see docs in README) * @return {string} formatted query */ -export const format = (query: string, cfg: Partial = {}): string => { - if (typeof query !== 'string') { - throw new Error('Invalid query argument. Expected string, instead got ' + typeof query); +export const format = (query: string, cfg: Partial = defaultOptions): string => { + validateQuery(query); + + if (typeof cfg.language === 'string' && !supportedDialects.includes(cfg.language)) { + throw new ConfigError(`Unsupported SQL dialect: ${cfg.language}`); } const options = validateConfig({ @@ -78,49 +81,32 @@ export const format = (query: string, cfg: Partial = {}): string return new FormatterCls(options).format(query); }; -export class ConfigError extends Error {} - -function validateConfig(cfg: FormatOptions): FormatOptions { - if (typeof cfg.language === 'string' && !supportedDialects.includes(cfg.language)) { - throw new ConfigError(`Unsupported SQL dialect: ${cfg.language}`); - } - - if ('multilineLists' in cfg) { - throw new ConfigError('multilineLists config is no more supported.'); - } - if ('newlineBeforeOpenParen' in cfg) { - throw new ConfigError('newlineBeforeOpenParen config is no more supported.'); - } - if ('newlineBeforeCloseParen' in cfg) { - throw new ConfigError('newlineBeforeCloseParen config is no more supported.'); - } - if ('aliasAs' in cfg) { - throw new ConfigError('aliasAs config is no more supported.'); - } - - if (cfg.expressionWidth <= 0) { - throw new ConfigError( - `expressionWidth config must be positive number. Received ${cfg.expressionWidth} instead.` - ); - } - - if (cfg.commaPosition === 'before' && cfg.useTabs) { - throw new ConfigError( - 'commaPosition: before does not work when tabs are used for indentation.' - ); - } - - if (cfg.params && !validateParams(cfg.params)) { - // eslint-disable-next-line no-console - console.warn('WARNING: All "params" option values should be strings.'); - } - - return cfg; -} - -function validateParams(params: ParamItems | string[]): boolean { - const paramValues = params instanceof Array ? params : Object.values(params); - return paramValues.every(p => typeof p === 'string'); -} +const languageFormat = + (FormatterCls: Lang) => + (query: string, cfg: Partial> = {}) => { + validateQuery(query); + const options = validateConfig({ + ...defaultOptions, + ...cfg, + }); + return new FormatterCls(options).format(query); + }; export type FormatFn = typeof format; + +export const formatBigQuery: FormatFn = languageFormat(BigQueryFormatter); +export const formatDb2: FormatFn = languageFormat(Db2Formatter); +export const formatHive: FormatFn = languageFormat(HiveFormatter); +export const formatMariaDb: FormatFn = languageFormat(MariaDbFormatter); +export const formatMySql: FormatFn = languageFormat(MySqlFormatter); +export const formatN1ql: FormatFn = languageFormat(N1qlFormatter); +export const formatPlSql: FormatFn = languageFormat(PlSqlFormatter); +export const formatPostgreSql: FormatFn = languageFormat(PostgreSqlFormatter); +export const formatRedshift: FormatFn = languageFormat(RedshiftFormatter); +export const formatSpark: FormatFn = languageFormat(SparkFormatter); +export const formatSqlite: FormatFn = languageFormat(SqliteFormatter); +export const formatStandardSQL: FormatFn = languageFormat(SqlFormatter); +export const formatTrino: FormatFn = languageFormat(TrinoFormatter); +export const formatTransactSql: FormatFn = languageFormat(TransactSqlFormatter); +export const formatSingleStoreDb: FormatFn = languageFormat(SingleStoreDbFormatter); +export const formatSnowflake: FormatFn = languageFormat(SnowflakeFormatter); diff --git a/src/validateConfigs.ts b/src/validateConfigs.ts new file mode 100644 index 0000000000..52284731e0 --- /dev/null +++ b/src/validateConfigs.ts @@ -0,0 +1,49 @@ +import { FormatOptions } from './FormatOptions'; +import { ParamItems } from './formatter/Params'; + +export class ConfigError extends Error {} + +export const validateQuery = (query: string) => { + if (typeof query !== 'string') { + throw new Error('Invalid query argument. Expected string, instead got ' + typeof query); + } +}; + +export const validateConfig = (cfg: FormatOptions): FormatOptions => { + if ('multilineLists' in cfg) { + throw new ConfigError('multilineLists config is no more supported.'); + } + if ('newlineBeforeOpenParen' in cfg) { + throw new ConfigError('newlineBeforeOpenParen config is no more supported.'); + } + if ('newlineBeforeCloseParen' in cfg) { + throw new ConfigError('newlineBeforeCloseParen config is no more supported.'); + } + if ('aliasAs' in cfg) { + throw new ConfigError('aliasAs config is no more supported.'); + } + + if (cfg.expressionWidth <= 0) { + throw new ConfigError( + `expressionWidth config must be positive number. Received ${cfg.expressionWidth} instead.` + ); + } + + if (cfg.commaPosition === 'before' && cfg.useTabs) { + throw new ConfigError( + 'commaPosition: before does not work when tabs are used for indentation.' + ); + } + + if (cfg.params && !validateParams(cfg.params)) { + // eslint-disable-next-line no-console + console.warn('WARNING: All "params" option values should be strings.'); + } + + return cfg; +}; + +const validateParams = (params: ParamItems | string[]): boolean => { + const paramValues = params instanceof Array ? params : Object.values(params); + return paramValues.every(p => typeof p === 'string'); +};