sql-formatter icon indicating copy to clipboard operation
sql-formatter copied to clipboard

Feature Request: user defined formatter

Open verhovsky opened this issue 3 years ago • 3 comments

Describe the Feature I want to be able to define my own language which is a slight modification of an existing language. Something like this

import { format, Formatter, TrinoFormatter, register } from 'sql-formatter'

class MyFormatter extends Formatter {
  /* copy pasted code from TrinoFormatter */
}
// or
class MyFormatter extends TrinoFormatter {
  cfg.quotes.push({quote: "{{}}"})
}

const result = format('select {{blah}}\n\n\n from mytable', { formatter: MyFormatter })
// or
register('my-trino-dialect', MyFormatter)
const result = format('select {{blah}}\n\n\n from mytable', { language: 'my-trino-dialect' })

Why do you want this feature? We have a preprocessor/templating engine that puts stuff in our Trino queries, so for example the user writes

select {{col_name}} from mytable

and then we can have a web ui with a drop down for that value. We need to format this Trino+"{{}}}" dialect because it's what users write and format but it makes no sense to add this as its own language to sql-formatter. Currently, I have to fork this repo to do this.

verhovsky avatar Jul 12 '22 19:07 verhovsky

This has been asked before: #132

There are two reasons for not adding such a feature:

  • Currently the formatter is going through some major architectural changes. Exposing any of the current internal API would be unwise at this point, as it's all subject to change.
  • Integrating with a templating language is pretty much an unsolvable problem. This quotes hack probably works in many common cases, but there are bound to be cases where it'll be impossible for the formatter to correctly format it. So it's not really a good use-case for this feature.

That said, I actually like your proposal. I also sympathize with the pain of forking a project just for extending it a little. I'd be willing to add such a feature with the following caveats:

  • The API would be classified as experimental, with little to no documentation.
  • The API can and will break between any release (major, minor or patch).

nene avatar Jul 12 '22 20:07 nene

oops, #132 is my co-worker lol

verhovsky avatar Jul 13 '22 22:07 verhovsky

Regarding the proposed API for this. I think it would be best to use the existing language option, like so:

import { format, Formatter } from 'sql-formatter'

class CustomFormatter extends Formatter {
  /* custom implementation */
}

format('select * from mytable', { language: CustomFormatter });

This way the API surface for this would be minimal and there won't be any possibility for conflict (e.g. like when using { language: "sqlite", formatter: MyFormatter}).

nene avatar Aug 09 '22 19:08 nene

This is now released in 9.2.0.

nene avatar Aug 15 '22 16:08 nene

@nene is it possible to define a custom quote type? As I mentioned, I'd like to add

  // Handlebars expressions
  // https://handlebarsjs.com/guide/expressions.html#basic-usage
  '{{}}': String.raw`(?:\{\{[^\}]*\}\})`,

then use it like

        { quote: '{{}}', prefixes: [] },

Seems like I still need to fork the repo to add a custom quote?

PS could you please make prefixes an optional argument? My custom string type doesn't have any prefixes

verhovsky avatar Oct 19 '22 07:10 verhovsky

Not sure. Will have to think about it. Please open a new issue for that - otherwise I'll likely completely forget about it.

Regarding prefixes. If you don't need it, you can just write the value of quote field instead of the full object:

stringTypes: [ '""-qq' ]

nene avatar Oct 19 '22 07:10 nene