Repository: sql-formatter-org/sql-formatter
Pull request #487 (2022-10-02 21:52:05)

Use `NodeNext` for `Typescript` module resolution
Fixes https://github.com/sql-formatter-org/sql-formatter/issues/486

@nene  This is an extensive fix to upgrade the codebase to fully embrace ESM (i.e. specifying extensions in exports). This will make `sql-formatter` naturally work with Typescript projects which use `module = Node16/NodeNext`. Otherwise, we will have to find some other way to tweak `package.json` to make things work. 

For example, `uuid`

https://github.com/uuidjs/uuid/blob/main/package.json

doesn't use the field `type: module` and fully specify `exports` but I personally think it's just makeshift, we might as well move to adopt `ESM` fully.

---

I have run `yarn build` and `yarn test` locally to make sure things work.
One thing you might not like is I don't think we could use alias like `src` anymore so I resolved all imports to use relative paths, sorry about that 🙏 



Patch:
diff --git a/.eslintrc b/.eslintrc
index 3c531e5a..72910350 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -31,6 +31,7 @@
     "prefer-template": "off",
     "default-case": "off",
     "import/prefer-default-export": "off",
+    "import/extensions": ["error", "always"],
     "prettier/prettier": ["error"],
     "@typescript-eslint/no-use-before-define": "off",
     "@typescript-eslint/comma-dangle": "off",
diff --git a/package.json b/package.json
index f402bafe..ff35dd96 100644
--- a/package.json
+++ b/package.json
@@ -154,7 +154,7 @@
     "ts-loader": "^9.3.1",
     "ttypescript": "^1.5.13",
     "typescript": "^4.7.4",
-    "webpack": "^5.64.1",
+    "webpack": "^5.74.0",
     "webpack-cli": "^4.9.1",
     "webpack-merge": "^5.8.0"
   },
@@ -168,7 +168,7 @@
       "src/**/*.ts"
     ],
     "moduleNameMapper": {
-      "src/(.*)": "<rootDir>/src/$1"
+      "^\\.(.+)\\.js": ".$1"
     }
   }
 }
diff --git a/src/FormatOptions.ts b/src/FormatOptions.ts
index cc293b7c..dec52428 100644
--- a/src/FormatOptions.ts
+++ b/src/FormatOptions.ts
@@ -1,8 +1,8 @@
 // import only type to avoid ESLint no-cycle rule producing an error
-import type { SqlLanguage } from './sqlFormatter';
-import { ParamItems } from './formatter/Params';
-import Formatter from './formatter/Formatter';
-import { ParamTypes } from './lexer/TokenizerOptions';
+import type { SqlLanguage } from './sqlFormatter.js';
+import { ParamItems } from './formatter/Params.js';
+import Formatter from './formatter/Formatter.js';
+import { ParamTypes } from './lexer/TokenizerOptions.js';
 
 export type IndentStyle = 'standard' | 'tabularLeft' | 'tabularRight';
 
diff --git a/src/formatter/ExpressionFormatter.ts b/src/formatter/ExpressionFormatter.ts
index 35a7bbcc..610d38b6 100644
--- a/src/formatter/ExpressionFormatter.ts
+++ b/src/formatter/ExpressionFormatter.ts
@@ -1,9 +1,9 @@
-import { FormatOptions } from 'src/FormatOptions';
-import { equalizeWhitespace, isMultiline } from 'src/utils';
+import { FormatOptions } from '../FormatOptions.js';
+import { equalizeWhitespace, isMultiline } from '../utils.js';
 
-import Params from 'src/formatter/Params';
-import { isTabularStyle } from 'src/formatter/config';
-import { TokenType } from 'src/lexer/token';
+import Params from './Params.js';
+import { isTabularStyle } from './config.js';
+import { TokenType } from '../lexer/token.js';
 import {
   AllColumnsAsteriskNode,
   ArraySubscriptNode,
@@ -28,11 +28,11 @@ import {
   CaseExpressionNode,
   CaseWhenNode,
   CaseElseNode,
-} from 'src/parser/ast';
+} from '../parser/ast.js';
 
-import Layout, { WS } from './Layout';
-import toTabularFormat, { isTabularToken } from './tabularStyle';
-import InlineLayout, { InlineLayoutError } from './InlineLayout';
+import Layout, { WS } from './Layout.js';
+import toTabularFormat, { isTabularToken } from './tabularStyle.js';
+import InlineLayout, { InlineLayoutError } from './InlineLayout.js';
 
 interface ExpressionFormatterParams {
   cfg: FormatOptions;
diff --git a/src/formatter/Formatter.ts b/src/formatter/Formatter.ts
index 78bb54c3..0c24a66c 100644
--- a/src/formatter/Formatter.ts
+++ b/src/formatter/Formatter.ts
@@ -1,16 +1,16 @@
-import { FormatOptions } from 'src/FormatOptions';
-import { indentString } from 'src/formatter/config';
-import Params from 'src/formatter/Params';
-import Tokenizer from 'src/lexer/Tokenizer';
+import { FormatOptions } from '../FormatOptions.js';
+import { indentString } from './config.js';
+import Params from './Params.js';
+import Tokenizer from '../lexer/Tokenizer.js';
 
-import { createParser } from 'src/parser/createParser';
-import { StatementNode } from 'src/parser/ast';
+import { createParser } from '../parser/createParser.js';
+import { StatementNode } from '../parser/ast.js';
 
-import formatCommaPositions from './formatCommaPositions';
-import formatAliasPositions from './formatAliasPositions';
-import ExpressionFormatter, { DialectFormatOptions } from './ExpressionFormatter';
-import Layout, { WS } from './Layout';
-import Indentation from './Indentation';
+import formatCommaPositions from './formatCommaPositions.js';
+import formatAliasPositions from './formatAliasPositions.js';
+import ExpressionFormatter, { DialectFormatOptions } from './ExpressionFormatter.js';
+import Layout, { WS } from './Layout.js';
+import Indentation from './Indentation.js';
 
 /** Main formatter class that produces a final output string from list of tokens */
 export default class Formatter {
diff --git a/src/formatter/Indentation.ts b/src/formatter/Indentation.ts
index c47c7e01..4eaf0758 100644
--- a/src/formatter/Indentation.ts
+++ b/src/formatter/Indentation.ts
@@ -1,4 +1,4 @@
-import { last } from 'src/utils';
+import { last } from '../utils.js';
 
 const INDENT_TYPE_TOP_LEVEL = 'top-level';
 const INDENT_TYPE_BLOCK_LEVEL = 'block-level';
diff --git a/src/formatter/InlineLayout.ts b/src/formatter/InlineLayout.ts
index fcb1b4a0..e4fc2ab0 100644
--- a/src/formatter/InlineLayout.ts
+++ b/src/formatter/InlineLayout.ts
@@ -1,6 +1,6 @@
 // eslint-disable-next-line max-classes-per-file
-import Indentation from './Indentation';
-import Layout, { WS } from './Layout';
+import Indentation from './Indentation.js';
+import Layout, { WS } from './Layout.js';
 
 /**
  * Like Layout, but only formats single-line expressions.
diff --git a/src/formatter/Layout.ts b/src/formatter/Layout.ts
index f7a4d0d7..37b38f6d 100644
--- a/src/formatter/Layout.ts
+++ b/src/formatter/Layout.ts
@@ -1,6 +1,6 @@
-import { last } from 'src/utils';
+import { last } from '../utils.js';
 
-import Indentation from './Indentation';
+import Indentation from './Indentation.js';
 
 /** Whitespace modifiers to be used with add() method */
 export enum WS {
diff --git a/src/formatter/config.ts b/src/formatter/config.ts
index 363e6784..3141e4c1 100644
--- a/src/formatter/config.ts
+++ b/src/formatter/config.ts
@@ -1,4 +1,4 @@
-import { FormatOptions } from 'src/FormatOptions';
+import { FormatOptions } from '../FormatOptions.js';
 
 // Utility functions for config options
 
diff --git a/src/formatter/formatAliasPositions.ts b/src/formatter/formatAliasPositions.ts
index 205c3681..552b5770 100644
--- a/src/formatter/formatAliasPositions.ts
+++ b/src/formatter/formatAliasPositions.ts
@@ -1,4 +1,4 @@
-import { maxLength } from 'src/utils';
+import { maxLength } from '../utils.js';
 
 /**
  * Handles select alias placement - tabulates if enabled
diff --git a/src/formatter/formatCommaPositions.ts b/src/formatter/formatCommaPositions.ts
index 47a68094..a12cd2e3 100644
--- a/src/formatter/formatCommaPositions.ts
+++ b/src/formatter/formatCommaPositions.ts
@@ -1,5 +1,5 @@
-import { CommaPosition } from 'src/FormatOptions';
-import { maxLength } from 'src/utils';
+import { CommaPosition } from '../FormatOptions.js';
+import { maxLength } from '../utils.js';
 
 const PRECEDING_WHITESPACE_REGEX = /^\s+/u;
 
diff --git a/src/formatter/tabularStyle.ts b/src/formatter/tabularStyle.ts
index 8b940b66..3ff01228 100644
--- a/src/formatter/tabularStyle.ts
+++ b/src/formatter/tabularStyle.ts
@@ -1,5 +1,5 @@
-import { IndentStyle } from 'src/FormatOptions';
-import { isLogicalOperator, TokenType } from 'src/lexer/token';
+import { IndentStyle } from '../FormatOptions.js';
+import { isLogicalOperator, TokenType } from '../lexer/token.js';
 
 /**
  * When tabular style enabled,
diff --git a/src/index.ts b/src/index.ts
index d0d3f637..9a9a64b3 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,11 +1,11 @@
-export * from './sqlFormatter';
+export * from './sqlFormatter.js';
 export type {
   IndentStyle,
   KeywordCase,
   CommaPosition,
   LogicalOperatorNewline,
   FormatOptions,
-} from './FormatOptions';
-export { default as Formatter } from './formatter/Formatter';
-export { default as Tokenizer } from './lexer/Tokenizer';
-export { expandPhrases } from './expandPhrases';
+} from './FormatOptions.js';
+export { default as Formatter } from './formatter/Formatter.js';
+export { default as Tokenizer } from './lexer/Tokenizer.js';
+export { expandPhrases } from './expandPhrases.js';
diff --git a/src/languages/bigquery/bigquery.formatter.ts b/src/languages/bigquery/bigquery.formatter.ts
index a7cadd6d..5aa93c36 100644
--- a/src/languages/bigquery/bigquery.formatter.ts
+++ b/src/languages/bigquery/bigquery.formatter.ts
@@ -1,9 +1,9 @@
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { EOF_TOKEN, isToken, TokenType, Token } from 'src/lexer/token';
-import { expandPhrases } from 'src/expandPhrases';
-import { keywords } from './bigquery.keywords';
-import { functions } from './bigquery.functions';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { EOF_TOKEN, isToken, TokenType, Token } from '../../lexer/token.js';
+import { expandPhrases } from '../../expandPhrases.js';
+import { keywords } from './bigquery.keywords.js';
+import { functions } from './bigquery.functions.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT] [AS STRUCT | AS VALUE]']);
 
diff --git a/src/languages/bigquery/bigquery.functions.ts b/src/languages/bigquery/bigquery.functions.ts
index 369ef761..c3b43d9b 100644
--- a/src/languages/bigquery/bigquery.functions.ts
+++ b/src/languages/bigquery/bigquery.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://cloud.google.com/bigquery/docs/reference/standard-sql/aead_encryption_functions
diff --git a/src/languages/bigquery/bigquery.keywords.ts b/src/languages/bigquery/bigquery.keywords.ts
index e086fc63..b776a24a 100644
--- a/src/languages/bigquery/bigquery.keywords.ts
+++ b/src/languages/bigquery/bigquery.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#reserved_keywords
diff --git a/src/languages/db2/db2.formatter.ts b/src/languages/db2/db2.formatter.ts
index 1cec0603..4a6480c7 100644
--- a/src/languages/db2/db2.formatter.ts
+++ b/src/languages/db2/db2.formatter.ts
@@ -1,8 +1,8 @@
-import { expandPhrases } from 'src/expandPhrases';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { functions } from './db2.functions';
-import { keywords } from './db2.keywords';
+import { expandPhrases } from '../../expandPhrases.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { functions } from './db2.functions.js';
+import { keywords } from './db2.keywords.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT]']);
 
diff --git a/src/languages/db2/db2.functions.ts b/src/languages/db2/db2.functions.ts
index d3c8faef..23d43a50 100644
--- a/src/languages/db2/db2.functions.ts
+++ b/src/languages/db2/db2.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://www.ibm.com/docs/en/db2-for-zos/11?topic=functions-aggregate
diff --git a/src/languages/db2/db2.keywords.ts b/src/languages/db2/db2.keywords.ts
index d649c53c..bc7a1b45 100644
--- a/src/languages/db2/db2.keywords.ts
+++ b/src/languages/db2/db2.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://www.ibm.com/docs/en/db2-for-zos/11?topic=words-reserved#db2z_reservedwords__newresword
diff --git a/src/languages/hive/hive.formatter.ts b/src/languages/hive/hive.formatter.ts
index 6fc8a2a0..44e247fa 100644
--- a/src/languages/hive/hive.formatter.ts
+++ b/src/languages/hive/hive.formatter.ts
@@ -1,8 +1,8 @@
-import { expandPhrases } from 'src/expandPhrases';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { functions } from './hive.functions';
-import { keywords } from './hive.keywords';
+import { expandPhrases } from '../../expandPhrases.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { functions } from './hive.functions.js';
+import { keywords } from './hive.keywords.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT]']);
 
diff --git a/src/languages/hive/hive.functions.ts b/src/languages/hive/hive.functions.ts
index f8efca6f..c67f0a7d 100644
--- a/src/languages/hive/hive.functions.ts
+++ b/src/languages/hive/hive.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
diff --git a/src/languages/hive/hive.keywords.ts b/src/languages/hive/hive.keywords.ts
index fe7e03ad..4bc8e317 100644
--- a/src/languages/hive/hive.keywords.ts
+++ b/src/languages/hive/hive.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl
diff --git a/src/languages/mariadb/mariadb.formatter.ts b/src/languages/mariadb/mariadb.formatter.ts
index 308d7198..0de9e7d7 100644
--- a/src/languages/mariadb/mariadb.formatter.ts
+++ b/src/languages/mariadb/mariadb.formatter.ts
@@ -1,9 +1,9 @@
-import { expandPhrases } from 'src/expandPhrases';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { EOF_TOKEN, isToken, Token, TokenType } from 'src/lexer/token';
-import { keywords } from './mariadb.keywords';
-import { functions } from './mariadb.functions';
+import { expandPhrases } from '../../expandPhrases.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { EOF_TOKEN, isToken, Token, TokenType } from '../../lexer/token.js';
+import { keywords } from './mariadb.keywords.js';
+import { functions } from './mariadb.functions.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT | DISTINCTROW]']);
 
diff --git a/src/languages/mariadb/mariadb.functions.ts b/src/languages/mariadb/mariadb.functions.ts
index acf9ef9f..3a1f7fd8 100644
--- a/src/languages/mariadb/mariadb.functions.ts
+++ b/src/languages/mariadb/mariadb.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://mariadb.com/kb/en/information-schema-sql_functions-table/
diff --git a/src/languages/mariadb/mariadb.keywords.ts b/src/languages/mariadb/mariadb.keywords.ts
index e067d5da..58a2890a 100644
--- a/src/languages/mariadb/mariadb.keywords.ts
+++ b/src/languages/mariadb/mariadb.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://mariadb.com/kb/en/information-schema-keywords-table/
diff --git a/src/languages/mysql/mysql.formatter.ts b/src/languages/mysql/mysql.formatter.ts
index 5914ba62..b9f6d833 100644
--- a/src/languages/mysql/mysql.formatter.ts
+++ b/src/languages/mysql/mysql.formatter.ts
@@ -1,9 +1,9 @@
-import { expandPhrases } from 'src/expandPhrases';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { EOF_TOKEN, isToken, Token, TokenType } from 'src/lexer/token';
-import { keywords } from './mysql.keywords';
-import { functions } from './mysql.functions';
+import { expandPhrases } from '../../expandPhrases.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { EOF_TOKEN, isToken, Token, TokenType } from '../../lexer/token.js';
+import { keywords } from './mysql.keywords.js';
+import { functions } from './mysql.functions.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT | DISTINCTROW]']);
 
diff --git a/src/languages/mysql/mysql.functions.ts b/src/languages/mysql/mysql.functions.ts
index 7b760a8c..67ed2fbe 100644
--- a/src/languages/mysql/mysql.functions.ts
+++ b/src/languages/mysql/mysql.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://dev.mysql.com/doc/refman/8.0/en/built-in-function-reference.html
diff --git a/src/languages/mysql/mysql.keywords.ts b/src/languages/mysql/mysql.keywords.ts
index c27177e6..8945e9ee 100644
--- a/src/languages/mysql/mysql.keywords.ts
+++ b/src/languages/mysql/mysql.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://dev.mysql.com/doc/refman/8.0/en/keywords.html
diff --git a/src/languages/n1ql/n1ql.formatter.ts b/src/languages/n1ql/n1ql.formatter.ts
index 64438eea..05a6a8fc 100644
--- a/src/languages/n1ql/n1ql.formatter.ts
+++ b/src/languages/n1ql/n1ql.formatter.ts
@@ -1,8 +1,8 @@
-import { expandPhrases } from 'src/expandPhrases';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { functions } from './n1ql.functions';
-import { keywords } from './n1ql.keywords';
+import { expandPhrases } from '../../expandPhrases.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { functions } from './n1ql.functions.js';
+import { keywords } from './n1ql.keywords.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT]']);
 
diff --git a/src/languages/n1ql/n1ql.functions.ts b/src/languages/n1ql/n1ql.functions.ts
index a905e412..80e85d73 100644
--- a/src/languages/n1ql/n1ql.functions.ts
+++ b/src/languages/n1ql/n1ql.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://docs.couchbase.com/server/current/n1ql/n1ql-language-reference/functions.html
diff --git a/src/languages/n1ql/n1ql.keywords.ts b/src/languages/n1ql/n1ql.keywords.ts
index a6d9e728..31ae3111 100644
--- a/src/languages/n1ql/n1ql.keywords.ts
+++ b/src/languages/n1ql/n1ql.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://docs.couchbase.com/server/current/n1ql/n1ql-language-reference/reservedwords.html
diff --git a/src/languages/plsql/plsql.formatter.ts b/src/languages/plsql/plsql.formatter.ts
index 7ccbe317..2e8b5b24 100644
--- a/src/languages/plsql/plsql.formatter.ts
+++ b/src/languages/plsql/plsql.formatter.ts
@@ -1,10 +1,10 @@
-import { expandPhrases } from 'src/expandPhrases';
-import Formatter from 'src/formatter/Formatter';
-import { DialectFormatOptions } from 'src/formatter/ExpressionFormatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { EOF_TOKEN, isReserved, isToken, Token, TokenType } from 'src/lexer/token';
-import { keywords } from './plsql.keywords';
-import { functions } from './plsql.functions';
+import { expandPhrases } from '../../expandPhrases.js';
+import Formatter from '../../formatter/Formatter.js';
+import { DialectFormatOptions } from '../../formatter/ExpressionFormatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { EOF_TOKEN, isReserved, isToken, Token, TokenType } from '../../lexer/token.js';
+import { keywords } from './plsql.keywords.js';
+import { functions } from './plsql.functions.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT | UNIQUE]']);
 
diff --git a/src/languages/plsql/plsql.functions.ts b/src/languages/plsql/plsql.functions.ts
index 0693f0e7..6284040a 100644
--- a/src/languages/plsql/plsql.functions.ts
+++ b/src/languages/plsql/plsql.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions001.htm
diff --git a/src/languages/plsql/plsql.keywords.ts b/src/languages/plsql/plsql.keywords.ts
index 6d889b3f..feac7cb7 100644
--- a/src/languages/plsql/plsql.keywords.ts
+++ b/src/languages/plsql/plsql.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/reservewords.htm
diff --git a/src/languages/postgresql/postgresql.formatter.ts b/src/languages/postgresql/postgresql.formatter.ts
index 0dd413ac..7c3d8a6c 100644
--- a/src/languages/postgresql/postgresql.formatter.ts
+++ b/src/languages/postgresql/postgresql.formatter.ts
@@ -1,9 +1,9 @@
-import { expandPhrases } from 'src/expandPhrases';
-import { DialectFormatOptions } from 'src/formatter/ExpressionFormatter';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { functions } from './postgresql.functions';
-import { keywords } from './postgresql.keywords';
+import { expandPhrases } from '../../expandPhrases.js';
+import { DialectFormatOptions } from '../../formatter/ExpressionFormatter.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { functions } from './postgresql.functions.js';
+import { keywords } from './postgresql.keywords.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT]']);
 
diff --git a/src/languages/postgresql/postgresql.functions.ts b/src/languages/postgresql/postgresql.functions.ts
index 145f5202..81e3f094 100644
--- a/src/languages/postgresql/postgresql.functions.ts
+++ b/src/languages/postgresql/postgresql.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://www.postgresql.org/docs/14/functions.html
diff --git a/src/languages/postgresql/postgresql.keywords.ts b/src/languages/postgresql/postgresql.keywords.ts
index 7962a4e5..743d3dae 100644
--- a/src/languages/postgresql/postgresql.keywords.ts
+++ b/src/languages/postgresql/postgresql.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://www.postgresql.org/docs/14/sql-keywords-appendix.html
diff --git a/src/languages/redshift/redshift.formatter.ts b/src/languages/redshift/redshift.formatter.ts
index a3ad3a15..21e29b49 100644
--- a/src/languages/redshift/redshift.formatter.ts
+++ b/src/languages/redshift/redshift.formatter.ts
@@ -1,9 +1,9 @@
-import { expandPhrases } from 'src/expandPhrases';
-import { DialectFormatOptions } from 'src/formatter/ExpressionFormatter';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { functions } from './redshift.functions';
-import { keywords } from './redshift.keywords';
+import { expandPhrases } from '../../expandPhrases.js';
+import { DialectFormatOptions } from '../../formatter/ExpressionFormatter.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { functions } from './redshift.functions.js';
+import { keywords } from './redshift.keywords.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT]']);
 
diff --git a/src/languages/redshift/redshift.functions.ts b/src/languages/redshift/redshift.functions.ts
index 1da9478c..46dbdab7 100644
--- a/src/languages/redshift/redshift.functions.ts
+++ b/src/languages/redshift/redshift.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://docs.aws.amazon.com/redshift/latest/dg/c_Aggregate_Functions.html
diff --git a/src/languages/redshift/redshift.keywords.ts b/src/languages/redshift/redshift.keywords.ts
index 6a7f3d69..15eee264 100644
--- a/src/languages/redshift/redshift.keywords.ts
+++ b/src/languages/redshift/redshift.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://docs.aws.amazon.com/redshift/latest/dg/r_pg_keywords.html
diff --git a/src/languages/singlestoredb/singlestoredb.formatter.ts b/src/languages/singlestoredb/singlestoredb.formatter.ts
index 2adf7a18..173893a5 100644
--- a/src/languages/singlestoredb/singlestoredb.formatter.ts
+++ b/src/languages/singlestoredb/singlestoredb.formatter.ts
@@ -1,9 +1,9 @@
-import { expandPhrases } from 'src/expandPhrases';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { EOF_TOKEN, isToken, Token, TokenType } from 'src/lexer/token';
-import { keywords } from './singlestoredb.keywords';
-import { functions } from './singlestoredb.functions';
+import { expandPhrases } from '../../expandPhrases.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { EOF_TOKEN, isToken, Token, TokenType } from '../../lexer/token.js';
+import { keywords } from './singlestoredb.keywords.js';
+import { functions } from './singlestoredb.functions.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT | DISTINCTROW]']);
 
diff --git a/src/languages/singlestoredb/singlestoredb.functions.ts b/src/languages/singlestoredb/singlestoredb.functions.ts
index 5bfcd5ec..a064b98b 100644
--- a/src/languages/singlestoredb/singlestoredb.functions.ts
+++ b/src/languages/singlestoredb/singlestoredb.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://docs.singlestore.com/managed-service/en/reference/sql-reference/vector-functions/vector-functions.html
diff --git a/src/languages/singlestoredb/singlestoredb.keywords.ts b/src/languages/singlestoredb/singlestoredb.keywords.ts
index bd69032c..5e4cfe72 100644
--- a/src/languages/singlestoredb/singlestoredb.keywords.ts
+++ b/src/languages/singlestoredb/singlestoredb.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://docs.singlestore.com/managed-service/en/reference/sql-reference.html
diff --git a/src/languages/snowflake/snowflake.formatter.ts b/src/languages/snowflake/snowflake.formatter.ts
index d65ef06f..a5e12517 100644
--- a/src/languages/snowflake/snowflake.formatter.ts
+++ b/src/languages/snowflake/snowflake.formatter.ts
@@ -1,9 +1,9 @@
-import { expandPhrases } from 'src/expandPhrases';
-import { DialectFormatOptions } from 'src/formatter/ExpressionFormatter';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { functions } from './snowflake.functions';
-import { keywords } from './snowflake.keywords';
+import { expandPhrases } from '../../expandPhrases.js';
+import { DialectFormatOptions } from '../../formatter/ExpressionFormatter.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { functions } from './snowflake.functions.js';
+import { keywords } from './snowflake.keywords.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT]']);
 
diff --git a/src/languages/snowflake/snowflake.functions.ts b/src/languages/snowflake/snowflake.functions.ts
index 3616d4d8..d81de487 100644
--- a/src/languages/snowflake/snowflake.functions.ts
+++ b/src/languages/snowflake/snowflake.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://docs.snowflake.com/en/sql-reference-functions.html
diff --git a/src/languages/snowflake/snowflake.keywords.ts b/src/languages/snowflake/snowflake.keywords.ts
index cf1e6aad..85b9d64f 100644
--- a/src/languages/snowflake/snowflake.keywords.ts
+++ b/src/languages/snowflake/snowflake.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://docs.snowflake.com/en/sql-reference/reserved-keywords.html
diff --git a/src/languages/spark/spark.formatter.ts b/src/languages/spark/spark.formatter.ts
index 2577277e..4daebf88 100644
--- a/src/languages/spark/spark.formatter.ts
+++ b/src/languages/spark/spark.formatter.ts
@@ -1,9 +1,9 @@
-import { expandPhrases } from 'src/expandPhrases';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { EOF_TOKEN, isToken, Token, TokenType } from 'src/lexer/token';
-import { keywords } from './spark.keywords';
-import { functions } from './spark.functions';
+import { expandPhrases } from '../../expandPhrases.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { EOF_TOKEN, isToken, Token, TokenType } from '../../lexer/token.js';
+import { keywords } from './spark.keywords.js';
+import { functions } from './spark.functions.js';
 
 // http://spark.apache.org/docs/latest/sql-ref-syntax.html
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT]']);
diff --git a/src/languages/spark/spark.functions.ts b/src/languages/spark/spark.functions.ts
index 556ba07d..e0cb5280 100644
--- a/src/languages/spark/spark.functions.ts
+++ b/src/languages/spark/spark.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // http://spark.apache.org/docs/latest/sql-ref-functions.html
diff --git a/src/languages/spark/spark.keywords.ts b/src/languages/spark/spark.keywords.ts
index dfdad5d1..b7248679 100644
--- a/src/languages/spark/spark.keywords.ts
+++ b/src/languages/spark/spark.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://deepkb.com/CO_000013/en/kb/IMPORT-fbfa59f0-2bf1-31fe-bb7b-0f9efe9932c6/spark-sql-keywords
diff --git a/src/languages/sql/sql.formatter.ts b/src/languages/sql/sql.formatter.ts
index 19b1dbd6..92b4d709 100644
--- a/src/languages/sql/sql.formatter.ts
+++ b/src/languages/sql/sql.formatter.ts
@@ -1,8 +1,8 @@
-import { expandPhrases } from 'src/expandPhrases';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { functions } from './sql.functions';
-import { keywords } from './sql.keywords';
+import { expandPhrases } from '../../expandPhrases.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { functions } from './sql.functions.js';
+import { keywords } from './sql.keywords.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT]']);
 
diff --git a/src/languages/sql/sql.functions.ts b/src/languages/sql/sql.functions.ts
index 34a73659..b47ba77e 100644
--- a/src/languages/sql/sql.functions.ts
+++ b/src/languages/sql/sql.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://jakewheat.github.io/sql-overview/sql-2008-foundation-grammar.html#_6_9_set_function_specification
diff --git a/src/languages/sql/sql.keywords.ts b/src/languages/sql/sql.keywords.ts
index a94a6919..9cd887ce 100644
--- a/src/languages/sql/sql.keywords.ts
+++ b/src/languages/sql/sql.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://jakewheat.github.io/sql-overview/sql-2008-foundation-grammar.html#reserved-word
diff --git a/src/languages/sqlite/sqlite.formatter.ts b/src/languages/sqlite/sqlite.formatter.ts
index a4acecee..1bd94847 100644
--- a/src/languages/sqlite/sqlite.formatter.ts
+++ b/src/languages/sqlite/sqlite.formatter.ts
@@ -1,8 +1,8 @@
-import { expandPhrases } from 'src/expandPhrases';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { functions } from './sqlite.functions';
-import { keywords } from './sqlite.keywords';
+import { expandPhrases } from '../../expandPhrases.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { functions } from './sqlite.functions.js';
+import { keywords } from './sqlite.keywords.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT]']);
 
diff --git a/src/languages/sqlite/sqlite.functions.ts b/src/languages/sqlite/sqlite.functions.ts
index 07864d4f..54a807ce 100644
--- a/src/languages/sqlite/sqlite.functions.ts
+++ b/src/languages/sqlite/sqlite.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://www.sqlite.org/lang_corefunc.html
diff --git a/src/languages/sqlite/sqlite.keywords.ts b/src/languages/sqlite/sqlite.keywords.ts
index 67c96fb9..25274e10 100644
--- a/src/languages/sqlite/sqlite.keywords.ts
+++ b/src/languages/sqlite/sqlite.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://www.sqlite.org/lang_keywords.html
diff --git a/src/languages/transactsql/transactsql.formatter.ts b/src/languages/transactsql/transactsql.formatter.ts
index 38453c45..60926736 100644
--- a/src/languages/transactsql/transactsql.formatter.ts
+++ b/src/languages/transactsql/transactsql.formatter.ts
@@ -1,9 +1,9 @@
-import { expandPhrases } from 'src/expandPhrases';
-import { DialectFormatOptions } from 'src/formatter/ExpressionFormatter';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { functions } from './transactsql.functions';
-import { keywords } from './transactsql.keywords';
+import { expandPhrases } from '../../expandPhrases.js';
+import { DialectFormatOptions } from '../../formatter/ExpressionFormatter.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { functions } from './transactsql.functions.js';
+import { keywords } from './transactsql.keywords.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT]']);
 
diff --git a/src/languages/transactsql/transactsql.functions.ts b/src/languages/transactsql/transactsql.functions.ts
index 2a71a000..21549573 100644
--- a/src/languages/transactsql/transactsql.functions.ts
+++ b/src/languages/transactsql/transactsql.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://docs.microsoft.com/en-us/sql/t-sql/functions/functions?view=sql-server-ver15
diff --git a/src/languages/transactsql/transactsql.keywords.ts b/src/languages/transactsql/transactsql.keywords.ts
index 1b057a41..ac235032 100644
--- a/src/languages/transactsql/transactsql.keywords.ts
+++ b/src/languages/transactsql/transactsql.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/reserved-keywords-transact-sql?view=sql-server-ver15
diff --git a/src/languages/trino/trino.formatter.ts b/src/languages/trino/trino.formatter.ts
index 6671dae9..2b0b7765 100644
--- a/src/languages/trino/trino.formatter.ts
+++ b/src/languages/trino/trino.formatter.ts
@@ -1,8 +1,8 @@
-import { expandPhrases } from 'src/expandPhrases';
-import Formatter from 'src/formatter/Formatter';
-import Tokenizer from 'src/lexer/Tokenizer';
-import { functions } from './trino.functions';
-import { keywords } from './trino.keywords';
+import { expandPhrases } from '../../expandPhrases.js';
+import Formatter from '../../formatter/Formatter.js';
+import Tokenizer from '../../lexer/Tokenizer.js';
+import { functions } from './trino.functions.js';
+import { keywords } from './trino.keywords.js';
 
 const reservedSelect = expandPhrases(['SELECT [ALL | DISTINCT]']);
 
diff --git a/src/languages/trino/trino.functions.ts b/src/languages/trino/trino.functions.ts
index cb848a69..5f969642 100644
--- a/src/languages/trino/trino.functions.ts
+++ b/src/languages/trino/trino.functions.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const functions = flatKeywordList({
   // https://github.com/trinodb/trino/tree/432d2897bdef99388c1a47188743a061c4ac1f34/docs/src/main/sphinx/functions
diff --git a/src/languages/trino/trino.keywords.ts b/src/languages/trino/trino.keywords.ts
index f3962b80..4a71cdd3 100644
--- a/src/languages/trino/trino.keywords.ts
+++ b/src/languages/trino/trino.keywords.ts
@@ -1,4 +1,4 @@
-import { flatKeywordList } from '../../utils';
+import { flatKeywordList } from '../../utils.js';
 
 export const keywords = flatKeywordList({
   // https://github.com/trinodb/trino/blob/432d2897bdef99388c1a47188743a061c4ac1f34/core/trino-parser/src/main/antlr4/io/trino/sql/parser/SqlBase.g4#L858-L1128
diff --git a/src/lexer/NestedComment.ts b/src/lexer/NestedComment.ts
index 93d5b2af..983f0e3f 100644
--- a/src/lexer/NestedComment.ts
+++ b/src/lexer/NestedComment.ts
@@ -1,5 +1,5 @@
 /* eslint-disable no-cond-assign */
-import { RegExpLike } from 'src/lexer/TokenizerEngine';
+import { RegExpLike } from './TokenizerEngine.js';
 
 const START = /\/\*/uy; // matches: /*
 const MIDDLE = /([^/*]|\*[^/]|\/[^*])+/uy; // matches text NOT containing /* or */
diff --git a/src/lexer/Tokenizer.ts b/src/lexer/Tokenizer.ts
index 814dade9..7a80d30f 100644
--- a/src/lexer/Tokenizer.ts
+++ b/src/lexer/Tokenizer.ts
@@ -1,10 +1,10 @@
-import { Token, TokenType } from 'src/lexer/token';
-import * as regex from 'src/lexer/regexFactory';
-import { ParamTypes, TokenizerOptions } from 'src/lexer/TokenizerOptions';
-import TokenizerEngine, { TokenRule } from 'src/lexer/TokenizerEngine';
-import { escapeRegExp } from 'src/lexer/regexUtil';
-import { equalizeWhitespace, Optional } from 'src/utils';
-import { NestedComment } from './NestedComment';
+import { Token, TokenType } from './token.js';
+import * as regex from './regexFactory.js';
+import { ParamTypes, TokenizerOptions } from './TokenizerOptions.js';
+import TokenizerEngine, { TokenRule } from './TokenizerEngine.js';
+import { escapeRegExp } from './regexUtil.js';
+import { equalizeWhitespace, Optional } from '../utils.js';
+import { NestedComment } from './NestedComment.js';
 
 type OptionalTokenRule = Optional<TokenRule, 'regex'>;
 
diff --git a/src/lexer/TokenizerEngine.ts b/src/lexer/TokenizerEngine.ts
index f6234b65..d10ad718 100644
--- a/src/lexer/TokenizerEngine.ts
+++ b/src/lexer/TokenizerEngine.ts
@@ -1,6 +1,6 @@
-import { Token, TokenType } from 'src/lexer/token';
-import { lineColFromIndex } from './lineColFromIndex';
-import { WHITESPACE_REGEX } from './regexUtil';
+import { Token, TokenType } from './token.js';
+import { lineColFromIndex } from './lineColFromIndex.js';
+import { WHITESPACE_REGEX } from './regexUtil.js';
 
 export interface RegExpLike {
   lastIndex: number;
diff --git a/src/lexer/TokenizerOptions.ts b/src/lexer/TokenizerOptions.ts
index ed12f597..35e0f605 100644
--- a/src/lexer/TokenizerOptions.ts
+++ b/src/lexer/TokenizerOptions.ts
@@ -1,5 +1,5 @@
-import { quotePatterns } from 'src/lexer/regexFactory';
-import { Token } from 'src/lexer/token';
+import { quotePatterns } from './regexFactory.js';
+import { Token } from './token.js';
 
 export interface IdentChars {
   // Additional characters that can be used as first character of an identifier.
diff --git a/src/lexer/disambiguateTokens.ts b/src/lexer/disambiguateTokens.ts
index f308fbd7..4527f619 100644
--- a/src/lexer/disambiguateTokens.ts
+++ b/src/lexer/disambiguateTokens.ts
@@ -1,4 +1,4 @@
-import { isReserved, Token, TokenType } from 'src/lexer/token';
+import { isReserved, Token, TokenType } from './token.js';
 
 /**
  * Ensures that no keyword token (RESERVED_*) is preceded by dot (.).
diff --git a/src/lexer/regexFactory.ts b/src/lexer/regexFactory.ts
index 7874629d..3d627ad8 100644
--- a/src/lexer/regexFactory.ts
+++ b/src/lexer/regexFactory.ts
@@ -1,7 +1,7 @@
-import { sortByLengthDesc } from 'src/utils';
+import { sortByLengthDesc } from '../utils.js';
 
-import { IdentChars, QuoteType, VariableType } from './TokenizerOptions';
-import { escapeRegExp, patternToRegex, prefixesPattern, withDashes } from './regexUtil';
+import { IdentChars, QuoteType, VariableType } from './TokenizerOptions.js';
+import { escapeRegExp, patternToRegex, prefixesPattern, withDashes } from './regexUtil.js';
 
 /**
  * Builds a RegExp for valid line comments in a SQL dialect
diff --git a/src/lexer/regexUtil.ts b/src/lexer/regexUtil.ts
index 95cef132..ddece97a 100644
--- a/src/lexer/regexUtil.ts
+++ b/src/lexer/regexUtil.ts
@@ -1,4 +1,4 @@
-import { PrefixedQuoteType } from './TokenizerOptions';
+import { PrefixedQuoteType } from './TokenizerOptions.js';
 
 // Escapes regex special chars
 export const escapeRegExp = (string: string) => string.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
diff --git a/src/parser/LexerAdapter.ts b/src/parser/LexerAdapter.ts
index 8e17f242..959ab64d 100644
--- a/src/parser/LexerAdapter.ts
+++ b/src/parser/LexerAdapter.ts
@@ -1,5 +1,5 @@
-import { lineColFromIndex } from 'src/lexer/lineColFromIndex';
-import { Token, TokenType } from 'src/lexer/token';
+import { lineColFromIndex } from '../lexer/lineColFromIndex.js';
+import { Token, TokenType } from '../lexer/token.js';
 
 // Nearly type definitions say that Token must have a value field,
 // which however is wrong.  Instead Nearley expects a text field.
diff --git a/src/parser/ast.ts b/src/parser/ast.ts
index 7d1a129e..2d468ed8 100644
--- a/src/parser/ast.ts
+++ b/src/parser/ast.ts
@@ -1,4 +1,4 @@
-import { TokenType } from 'src/lexer/token';
+import { TokenType } from '../lexer/token.js';
 
 export enum NodeType {
   statement = 'statement',
diff --git a/src/parser/createParser.ts b/src/parser/createParser.ts
index e15b23a1..da96616b 100644
--- a/src/parser/createParser.ts
+++ b/src/parser/createParser.ts
@@ -1,12 +1,12 @@
 import { Parser as NearleyParser, Grammar } from 'nearley';
 
-import Tokenizer from 'src/lexer/Tokenizer';
-import { disambiguateTokens } from 'src/lexer/disambiguateTokens';
-import { ParamTypes } from 'src/lexer/TokenizerOptions';
-import { StatementNode } from 'src/parser/ast';
-import grammar from 'src/parser/grammar';
-import LexerAdapter from 'src/parser/LexerAdapter';
-import { createEofToken } from 'src/lexer/token';
+import Tokenizer from '../lexer/Tokenizer.js';
+import { disambiguateTokens } from '../lexer/disambiguateTokens.js';
+import { ParamTypes } from '../lexer/TokenizerOptions.js';
+import { StatementNode } from './ast.js';
+import grammar from './grammar.js';
+import LexerAdapter from './LexerAdapter.js';
+import { createEofToken } from '../lexer/token.js';
 
 export interface Parser {
   parse(sql: string, paramTypesOverrides: ParamTypes): StatementNode[];
diff --git a/src/parser/grammar.ne b/src/parser/grammar.ne
index fcb159c2..72497e6e 100644
--- a/src/parser/grammar.ne
+++ b/src/parser/grammar.ne
@@ -1,8 +1,8 @@
 @preprocessor typescript
 @{%
-import LexerAdapter from 'src/parser/LexerAdapter';
-import { NodeType, AstNode, CommentNode, KeywordNode } from 'src/parser/ast';
-import { Token, TokenType } from 'src/lexer/token';
+import LexerAdapter from './LexerAdapter.js';
+import { NodeType, AstNode, CommentNode, KeywordNode } from './ast.js';
+import { Token, TokenType } from '../lexer/token.js';
 
 // The lexer here is only to provide the has() method,
 // that's used inside the generated grammar definition.
diff --git a/src/sqlFormatter.ts b/src/sqlFormatter.ts
index 45b04098..108079db 100644
--- a/src/sqlFormatter.ts
+++ b/src/sqlFormatter.ts
@@ -1,22 +1,22 @@
-import BigQueryFormatter from 'src/languages/bigquery/bigquery.formatter';
-import Db2Formatter from 'src/languages/db2/db2.formatter';
-import HiveFormatter from 'src/languages/hive/hive.formatter';
-import MariaDbFormatter from 'src/languages/mariadb/mariadb.formatter';
-import MySqlFormatter from 'src/languages/mysql/mysql.formatter';
-import N1qlFormatter from 'src/languages/n1ql/n1ql.formatter';
-import PlSqlFormatter from 'src/languages/plsql/plsql.formatter';
-import PostgreSqlFormatter from 'src/languages/postgresql/postgresql.formatter';
-import RedshiftFormatter from 'src/languages/redshift/redshift.formatter';
-import SparkFormatter from 'src/languages/spark/spark.formatter';
-import SqliteFormatter from 'src/languages/sqlite/sqlite.formatter';
-import SqlFormatter from 'src/languages/sql/sql.formatter';
-import TrinoFormatter from 'src/languages/trino/trino.formatter';
-import TransactSqlFormatter from 'src/languages/transactsql/transactsql.formatter';
-import SingleStoreDbFormatter from './languages/singlestoredb/singlestoredb.formatter';
-import SnowflakeFormatter from './languages/snowflake/snowflake.formatter';
-
-import { FormatOptions } from './FormatOptions';
-import { ParamItems } from './formatter/Params';
+import BigQueryFormatter from './languages/bigquery/bigquery.formatter.js';
+import Db2Formatter from './languages/db2/db2.formatter.js';
+import HiveFormatter from './languages/hive/hive.formatter.js';
+import MariaDbFormatter from './languages/mariadb/mariadb.formatter.js';
+import MySqlFormatter from './languages/mysql/mysql.formatter.js';
+import N1qlFormatter from './languages/n1ql/n1ql.formatter.js';
+import PlSqlFormatter from './languages/plsql/plsql.formatter.js';
+import PostgreSqlFormatter from './languages/postgresql/postgresql.formatter.js';
+import RedshiftFormatter from './languages/redshift/redshift.formatter.js';
+import SparkFormatter from './languages/spark/spark.formatter.js';
+import SqliteFormatter from './languages/sqlite/sqlite.formatter.js';
+import SqlFormatter from './languages/sql/sql.formatter.js';
+import TrinoFormatter from './languages/trino/trino.formatter.js';
+import TransactSqlFormatter from './languages/transactsql/transactsql.formatter.js';
+import SingleStoreDbFormatter from './languages/singlestoredb/singlestoredb.formatter.js';
+import SnowflakeFormatter from './languages/snowflake/snowflake.formatter.js';
+
+import { FormatOptions } from './FormatOptions.js';
+import { ParamItems } from './formatter/Params.js';
 
 export const formatters = {
   bigquery: BigQueryFormatter,
diff --git a/tsconfig.json b/tsconfig.json
index 045045b0..ada3d186 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,14 +1,11 @@
 {
   "compilerOptions": {
-    "module": "es6",
+    "module": "NodeNext",
     "target": "es6",
     "lib": ["es6", "dom"],
     "rootDirs": ["src"],
     "outDir": "lib",
     "baseUrl": "./",
-    "paths": {
-      "src/*": ["./src/*"]
-    },
     "plugins": [
       {
         "transform": "@zerollup/ts-transform-paths",
@@ -18,7 +15,6 @@
     "sourceMap": true,
     "declaration": true,
     "esModuleInterop": true,
-    "moduleResolution": "node",
     "strict": true /* enable all strict type-checking options */,
     /* Additional Checks */
     "noImplicitReturns": true /* Report error when not all code paths in function return a value. */
diff --git a/webpack.common.js b/webpack.common.js
index a3f73c4f..f9df6871 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -11,8 +11,8 @@ export default {
   },
   resolve: {
     extensions: ['.js', '.ts'],
-    alias: {
-      src: path.resolve('./src'),
+    extensionAlias: {
+      '.js': ['.ts', '.js'],
     },
   },
   module: {
diff --git a/yarn.lock b/yarn.lock
index 017318e4..e227b7c8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2025,7 +2025,7 @@ acorn-walk@^8.2.0:
   resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
   integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
 
-acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.0, acorn@^8.7.1:
+acorn@^8.5.0, acorn@^8.7.0, acorn@^8.7.1:
   version "8.8.0"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8"
   integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==
@@ -2951,7 +2951,7 @@ enhanced-resolve@^5.0.0:
     graceful-fs "^4.2.4"
     tapable "^2.2.0"
 
-enhanced-resolve@^5.9.3:
+enhanced-resolve@^5.10.0:
   version "5.10.0"
   resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6"
   integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==
@@ -6614,7 +6614,7 @@ walker@^1.0.8:
   dependencies:
     makeerror "1.0.12"
 
-watchpack@^2.3.1:
+watchpack@^2.4.0:
   version "2.4.0"
   resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
   integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
@@ -6665,21 +6665,21 @@ webpack-sources@^3.2.3:
   resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
   integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
 
-webpack@^5.64.1:
-  version "5.73.0"
-  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.73.0.tgz#bbd17738f8a53ee5760ea2f59dce7f3431d35d38"
-  integrity sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==
+webpack@^5.74.0:
+  version "5.74.0"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980"
+  integrity sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==
   dependencies:
     "@types/eslint-scope" "^3.7.3"
     "@types/estree" "^0.0.51"
     "@webassemblyjs/ast" "1.11.1"
     "@webassemblyjs/wasm-edit" "1.11.1"
     "@webassemblyjs/wasm-parser" "1.11.1"
-    acorn "^8.4.1"
+    acorn "^8.7.1"
     acorn-import-assertions "^1.7.6"
     browserslist "^4.14.5"
     chrome-trace-event "^1.0.2"
-    enhanced-resolve "^5.9.3"
+    enhanced-resolve "^5.10.0"
     es-module-lexer "^0.9.0"
     eslint-scope "5.1.1"
     events "^3.2.0"
@@ -6692,7 +6692,7 @@ webpack@^5.64.1:
     schema-utils "^3.1.0"
     tapable "^2.1.1"
     terser-webpack-plugin "^5.1.3"
-    watchpack "^2.3.1"
+    watchpack "^2.4.0"
     webpack-sources "^3.2.3"
 
 whatwg-url@^5.0.0:


Test patch:
diff --git a/test/behavesLikeMariaDbFormatter.ts b/test/behavesLikeMariaDbFormatter.ts
index 9c9dd8bd..9824cef5 100644
--- a/test/behavesLikeMariaDbFormatter.ts
+++ b/test/behavesLikeMariaDbFormatter.ts
@@ -1,17 +1,17 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
+import { FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
 
-import supportsDropTable from './features/dropTable';
-import supportsBetween from './features/between';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsComments from './features/comments';
-import supportsStrings from './features/strings';
-import supportsIdentifiers from './features/identifiers';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsTruncateTable from './features/truncateTable';
+import supportsDropTable from './features/dropTable.js';
+import supportsBetween from './features/between.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsComments from './features/comments.js';
+import supportsStrings from './features/strings.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsTruncateTable from './features/truncateTable.js';
 
 /**
  * Shared tests for MySQL and MariaDB
diff --git a/test/behavesLikeSqlFormatter.ts b/test/behavesLikeSqlFormatter.ts
index d96952da..16389211 100644
--- a/test/behavesLikeSqlFormatter.ts
+++ b/test/behavesLikeSqlFormatter.ts
@@ -1,22 +1,22 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../src/sqlFormatter.js';
 
-import supportsCase from './features/case';
-import supportsNumbers from './features/numbers';
-import supportsWith from './features/with';
-import supportsTabWidth from './options/tabWidth';
-import supportsUseTabs from './options/useTabs';
-import supportsExpressionWidth from './options/expressionWidth';
-import supportsKeywordCase from './options/keywordCase';
-import supportsIndentStyle from './options/indentStyle';
-import supportsCommaPosition from './options/commaPosition';
-import supportsLinesBetweenQueries from './options/linesBetweenQueries';
-import supportsNewlineBeforeSemicolon from './options/newlineBeforeSemicolon';
-import supportsLogicalOperatorNewline from './options/logicalOperatorNewline';
-import supportsTabulateAlias from './options/tabulateAlias';
-import supportsParamTypes from './options/paramTypes';
-import supportsWindowFunctions from './features/windowFunctions';
+import supportsCase from './features/case.js';
+import supportsNumbers from './features/numbers.js';
+import supportsWith from './features/with.js';
+import supportsTabWidth from './options/tabWidth.js';
+import supportsUseTabs from './options/useTabs.js';
+import supportsExpressionWidth from './options/expressionWidth.js';
+import supportsKeywordCase from './options/keywordCase.js';
+import supportsIndentStyle from './options/indentStyle.js';
+import supportsCommaPosition from './options/commaPosition.js';
+import supportsLinesBetweenQueries from './options/linesBetweenQueries.js';
+import supportsNewlineBeforeSemicolon from './options/newlineBeforeSemicolon.js';
+import supportsLogicalOperatorNewline from './options/logicalOperatorNewline.js';
+import supportsTabulateAlias from './options/tabulateAlias.js';
+import supportsParamTypes from './options/paramTypes.js';
+import supportsWindowFunctions from './features/windowFunctions.js';
 
 /**
  * Core tests for all SQL formatters
diff --git a/test/bigquery.test.ts b/test/bigquery.test.ts
index d2834cfc..20defcd5 100644
--- a/test/bigquery.test.ts
+++ b/test/bigquery.test.ts
@@ -1,29 +1,29 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import { flatKeywordList } from 'src/utils';
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
-
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsStrings from './features/strings';
-import supportsArrayLiterals from './features/arrayLiterals';
-import supportsBetween from './features/between';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsParams from './options/param';
-import supportsWindow from './features/window';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsTruncateTable from './features/truncateTable';
-import supportsMergeInto from './features/mergeInto';
-import supportsCreateView from './features/createView';
-import supportsAlterTable from './features/alterTable';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import { flatKeywordList } from '../src/utils.js';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
+
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsStrings from './features/strings.js';
+import supportsArrayLiterals from './features/arrayLiterals.js';
+import supportsBetween from './features/between.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsParams from './options/param.js';
+import supportsWindow from './features/window.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsTruncateTable from './features/truncateTable.js';
+import supportsMergeInto from './features/mergeInto.js';
+import supportsCreateView from './features/createView.js';
+import supportsAlterTable from './features/alterTable.js';
 
 describe('BigQueryFormatter', () => {
   const language = 'bigquery';
diff --git a/test/db2.test.ts b/test/db2.test.ts
index c0da4bb6..87480c83 100644
--- a/test/db2.test.ts
+++ b/test/db2.test.ts
@@ -1,28 +1,28 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
 
-import supportsAlterTable from './features/alterTable';
-import supportsBetween from './features/between';
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsSchema from './features/schema';
-import supportsStrings from './features/strings';
-import supportsConstraints from './features/constraints';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsParams from './options/param';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsTruncateTable from './features/truncateTable';
-import supportsMergeInto from './features/mergeInto';
-import supportsCreateView from './features/createView';
+import supportsAlterTable from './features/alterTable.js';
+import supportsBetween from './features/between.js';
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsSchema from './features/schema.js';
+import supportsStrings from './features/strings.js';
+import supportsConstraints from './features/constraints.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsParams from './options/param.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsTruncateTable from './features/truncateTable.js';
+import supportsMergeInto from './features/mergeInto.js';
+import supportsCreateView from './features/createView.js';
 
 describe('Db2Formatter', () => {
   const language = 'db2';
diff --git a/test/features/alterTable.ts b/test/features/alterTable.ts
index 5b45618d..6494a84a 100644
--- a/test/features/alterTable.ts
+++ b/test/features/alterTable.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface AlterTableConfig {
   addColumn?: boolean;
diff --git a/test/features/arrayAndMapAccessors.ts b/test/features/arrayAndMapAccessors.ts
index 021fb111..3f903bec 100644
--- a/test/features/arrayAndMapAccessors.ts
+++ b/test/features/arrayAndMapAccessors.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsArrayAndMapAccessors(format: FormatFn) {
   it('supports square brackets for array indexing', () => {
diff --git a/test/features/arrayLiterals.ts b/test/features/arrayLiterals.ts
index b5316edc..86591d72 100644
--- a/test/features/arrayLiterals.ts
+++ b/test/features/arrayLiterals.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsArrayLiterals(format: FormatFn) {
   it('supports array literals', () => {
diff --git a/test/features/between.ts b/test/features/between.ts
index 7850112c..3b4b9e91 100644
--- a/test/features/between.ts
+++ b/test/features/between.ts
@@ -1,5 +1,5 @@
 import dedent from 'dedent-js';
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsBetween(format: FormatFn) {
   it('formats BETWEEN _ AND _ on single line', () => {
diff --git a/test/features/case.ts b/test/features/case.ts
index 442714c5..a79e1560 100644
--- a/test/features/case.ts
+++ b/test/features/case.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsCase(format: FormatFn) {
   it('formats CASE ... WHEN with a blank expression', () => {
diff --git a/test/features/comments.ts b/test/features/comments.ts
index a9e65aff..9f269f9f 100644
--- a/test/features/comments.ts
+++ b/test/features/comments.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface CommentsConfig {
   hashComments?: boolean;
diff --git a/test/features/constraints.ts b/test/features/constraints.ts
index 5090e0f8..4bda7788 100644
--- a/test/features/constraints.ts
+++ b/test/features/constraints.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsConstraints(format: FormatFn, actions: string[]) {
   actions.forEach(action => {
diff --git a/test/features/createTable.ts b/test/features/createTable.ts
index 0d097030..0bd8831d 100644
--- a/test/features/createTable.ts
+++ b/test/features/createTable.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface CreateTableConfig {
   orReplace?: boolean;
diff --git a/test/features/createView.ts b/test/features/createView.ts
index 6b16eee0..c368b7cb 100644
--- a/test/features/createView.ts
+++ b/test/features/createView.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface CreateViewConfig {
   orReplace?: boolean;
diff --git a/test/features/deleteFrom.ts b/test/features/deleteFrom.ts
index a63bfe93..542a2a4f 100644
--- a/test/features/deleteFrom.ts
+++ b/test/features/deleteFrom.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface DeleteFromConfig {
   withoutFrom?: boolean;
diff --git a/test/features/dropTable.ts b/test/features/dropTable.ts
index 2dee06a7..25b44ed8 100644
--- a/test/features/dropTable.ts
+++ b/test/features/dropTable.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface DropTableConfig {
   ifExists?: boolean;
diff --git a/test/features/identifiers.ts b/test/features/identifiers.ts
index a701b970..942ef96d 100644
--- a/test/features/identifiers.ts
+++ b/test/features/identifiers.ts
@@ -1,6 +1,6 @@
 import { expect } from '@jest/globals';
 import dedent from 'dedent-js';
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 type IdentType =
   | '""-qq' // with repeated-quote escaping
diff --git a/test/features/insertInto.ts b/test/features/insertInto.ts
index 11a8c610..f7a93d0a 100644
--- a/test/features/insertInto.ts
+++ b/test/features/insertInto.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface InsertIntoConfig {
   withoutInto?: boolean;
diff --git a/test/features/join.ts b/test/features/join.ts
index 21205b91..c12d6687 100644
--- a/test/features/join.ts
+++ b/test/features/join.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface Options {
   without?: string[];
diff --git a/test/features/limiting.ts b/test/features/limiting.ts
index a6a33d5c..b36a87df 100644
--- a/test/features/limiting.ts
+++ b/test/features/limiting.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface LimitingTypes {
   limit?: boolean;
diff --git a/test/features/mergeInto.ts b/test/features/mergeInto.ts
index f214f351..1a6960aa 100644
--- a/test/features/mergeInto.ts
+++ b/test/features/mergeInto.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsMergeInto(format: FormatFn) {
   it('formats MERGE INTO', () => {
diff --git a/test/features/numbers.ts b/test/features/numbers.ts
index f342b671..75e6f93a 100644
--- a/test/features/numbers.ts
+++ b/test/features/numbers.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsNumbers(format: FormatFn) {
   it('supports decimal numbers', () => {
diff --git a/test/features/operators.ts b/test/features/operators.ts
index 01979dab..2bc8714d 100644
--- a/test/features/operators.ts
+++ b/test/features/operators.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsOperators(
   format: FormatFn,
diff --git a/test/features/returning.ts b/test/features/returning.ts
index f1991da5..eaa345a0 100644
--- a/test/features/returning.ts
+++ b/test/features/returning.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsReturning(format: FormatFn) {
   it('places RETURNING to new line', () => {
diff --git a/test/features/schema.ts b/test/features/schema.ts
index 2b10a215..9a5740ac 100644
--- a/test/features/schema.ts
+++ b/test/features/schema.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsSchema(format: FormatFn) {
   it('formats simple SET SCHEMA statements', () => {
diff --git a/test/features/setOperations.ts b/test/features/setOperations.ts
index 99c4f2a6..adff66cc 100644
--- a/test/features/setOperations.ts
+++ b/test/features/setOperations.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export const standardSetOperations = [
   'UNION',
diff --git a/test/features/strings.ts b/test/features/strings.ts
index 286f118b..ee27c489 100644
--- a/test/features/strings.ts
+++ b/test/features/strings.ts
@@ -1,7 +1,7 @@
 import { expect } from '@jest/globals';
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 type StringType =
   // Note: ""-qq and ""-bs can be combined to allow for both types of escaping
diff --git a/test/features/truncateTable.ts b/test/features/truncateTable.ts
index 3346097c..31fb6ea0 100644
--- a/test/features/truncateTable.ts
+++ b/test/features/truncateTable.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface TruncateTableConfig {
   withoutTable?: boolean;
diff --git a/test/features/update.ts b/test/features/update.ts
index ac52893a..533e0f9f 100644
--- a/test/features/update.ts
+++ b/test/features/update.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface UpdateConfig {
   whereCurrentOf?: boolean;
diff --git a/test/features/window.ts b/test/features/window.ts
index e1c34dc9..c3146bbf 100644
--- a/test/features/window.ts
+++ b/test/features/window.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsWindow(format: FormatFn) {
   it('formats WINDOW clause at top level', () => {
diff --git a/test/features/windowFunctions.ts b/test/features/windowFunctions.ts
index 14205232..1f77badb 100644
--- a/test/features/windowFunctions.ts
+++ b/test/features/windowFunctions.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsWindowFunctions(format: FormatFn) {
   it('supports ROWS BETWEEN in window functions', () => {
diff --git a/test/features/with.ts b/test/features/with.ts
index 66f59afa..d552b8fa 100644
--- a/test/features/with.ts
+++ b/test/features/with.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsWith(format: FormatFn) {
   it('formats WITH clause with multiple Common Table Expressions (CTE)', () => {
diff --git a/test/hive.test.ts b/test/hive.test.ts
index b1f05e74..a05b9ee9 100644
--- a/test/hive.test.ts
+++ b/test/hive.test.ts
@@ -1,28 +1,28 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
 
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
 
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsAlterTable from './features/alterTable';
-import supportsSchema from './features/schema';
-import supportsStrings from './features/strings';
-import supportsBetween from './features/between';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsWindow from './features/window';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsUpdate from './features/update';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsTruncateTable from './features/truncateTable';
-import supportsMergeInto from './features/mergeInto';
-import supportsCreateView from './features/createView';
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsAlterTable from './features/alterTable.js';
+import supportsSchema from './features/schema.js';
+import supportsStrings from './features/strings.js';
+import supportsBetween from './features/between.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsWindow from './features/window.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsUpdate from './features/update.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsTruncateTable from './features/truncateTable.js';
+import supportsMergeInto from './features/mergeInto.js';
+import supportsCreateView from './features/createView.js';
 
 describe('HiveFormatter', () => {
   const language = 'hive';
diff --git a/test/mariadb.test.ts b/test/mariadb.test.ts
index 1390e070..0a5b7411 100644
--- a/test/mariadb.test.ts
+++ b/test/mariadb.test.ts
@@ -1,19 +1,19 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeMariaDbFormatter from './behavesLikeMariaDbFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeMariaDbFormatter from './behavesLikeMariaDbFormatter.js';
 
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsReturning from './features/returning';
-import supportsSetOperations, { standardSetOperations } from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsCreateTable from './features/createTable';
-import supportsParams from './options/param';
-import supportsCreateView from './features/createView';
-import supportsAlterTable from './features/alterTable';
-import supportsStrings from './features/strings';
-import supportsConstraints from './features/constraints';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsReturning from './features/returning.js';
+import supportsSetOperations, { standardSetOperations } from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsCreateTable from './features/createTable.js';
+import supportsParams from './options/param.js';
+import supportsCreateView from './features/createView.js';
+import supportsAlterTable from './features/alterTable.js';
+import supportsStrings from './features/strings.js';
+import supportsConstraints from './features/constraints.js';
 
 describe('MariaDbFormatter', () => {
   const language = 'mariadb';
diff --git a/test/mysql.test.ts b/test/mysql.test.ts
index 97080f80..2acbe367 100644
--- a/test/mysql.test.ts
+++ b/test/mysql.test.ts
@@ -1,19 +1,19 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeMariaDbFormatter from './behavesLikeMariaDbFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeMariaDbFormatter from './behavesLikeMariaDbFormatter.js';
 
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsWindow from './features/window';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsCreateTable from './features/createTable';
-import supportsParams from './options/param';
-import supportsCreateView from './features/createView';
-import supportsAlterTable from './features/alterTable';
-import supportsStrings from './features/strings';
-import supportsConstraints from './features/constraints';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsWindow from './features/window.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsCreateTable from './features/createTable.js';
+import supportsParams from './options/param.js';
+import supportsCreateView from './features/createView.js';
+import supportsAlterTable from './features/alterTable.js';
+import supportsStrings from './features/strings.js';
+import supportsConstraints from './features/constraints.js';
 
 describe('MySqlFormatter', () => {
   const language = 'mysql';
diff --git a/test/n1ql.test.ts b/test/n1ql.test.ts
index ceb54441..fe45b349 100644
--- a/test/n1ql.test.ts
+++ b/test/n1ql.test.ts
@@ -1,26 +1,26 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
 
-import supportsBetween from './features/between';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsSchema from './features/schema';
-import supportsStrings from './features/strings';
-import supportsReturning from './features/returning';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors';
-import supportsArrayLiterals from './features/arrayLiterals';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsParams from './options/param';
-import supportsWindow from './features/window';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsMergeInto from './features/mergeInto';
+import supportsBetween from './features/between.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsSchema from './features/schema.js';
+import supportsStrings from './features/strings.js';
+import supportsReturning from './features/returning.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors.js';
+import supportsArrayLiterals from './features/arrayLiterals.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsParams from './options/param.js';
+import supportsWindow from './features/window.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsMergeInto from './features/mergeInto.js';
 
 describe('N1qlFormatter', () => {
   const language = 'n1ql';
diff --git a/test/options/commaPosition.ts b/test/options/commaPosition.ts
index 11c50f5b..dfa69dd7 100644
--- a/test/options/commaPosition.ts
+++ b/test/options/commaPosition.ts
@@ -1,7 +1,7 @@
 import { expect } from '@jest/globals';
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsCommaPosition(format: FormatFn) {
   it('defaults to comma after column', () => {
diff --git a/test/options/expressionWidth.ts b/test/options/expressionWidth.ts
index c3496afe..3a7b2a3f 100644
--- a/test/options/expressionWidth.ts
+++ b/test/options/expressionWidth.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsExpressionWidth(format: FormatFn) {
   it('throws error when expressionWidth negative number', () => {
diff --git a/test/options/indentStyle.ts b/test/options/indentStyle.ts
index 68ee9ec4..d3a86589 100644
--- a/test/options/indentStyle.ts
+++ b/test/options/indentStyle.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsIndentStyle(format: FormatFn) {
   const baseQuery = `
diff --git a/test/options/keywordCase.ts b/test/options/keywordCase.ts
index a7d88478..15bc72e6 100644
--- a/test/options/keywordCase.ts
+++ b/test/options/keywordCase.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsKeywordCase(format: FormatFn) {
   it('preserves keyword case by default', () => {
diff --git a/test/options/linesBetweenQueries.ts b/test/options/linesBetweenQueries.ts
index 976988ef..e08dbcca 100644
--- a/test/options/linesBetweenQueries.ts
+++ b/test/options/linesBetweenQueries.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsLinesBetweenQueries(format: FormatFn) {
   it('defaults to single empty line between queries', () => {
diff --git a/test/options/logicalOperatorNewline.ts b/test/options/logicalOperatorNewline.ts
index 8348beca..3647b38e 100644
--- a/test/options/logicalOperatorNewline.ts
+++ b/test/options/logicalOperatorNewline.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsLogicalOperatorNewline(format: FormatFn) {
   it('by default adds newline before logical operator', () => {
diff --git a/test/options/newlineBeforeSemicolon.ts b/test/options/newlineBeforeSemicolon.ts
index 79ffc76a..8c7d0f77 100644
--- a/test/options/newlineBeforeSemicolon.ts
+++ b/test/options/newlineBeforeSemicolon.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsNewlineBeforeSemicolon(format: FormatFn) {
   it('formats lonely semicolon', () => {
diff --git a/test/options/param.ts b/test/options/param.ts
index 7c06756d..7eab6239 100644
--- a/test/options/param.ts
+++ b/test/options/param.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 interface ParamsTypes {
   positional?: boolean;
diff --git a/test/options/paramTypes.ts b/test/options/paramTypes.ts
index f4dc2b33..213482f0 100644
--- a/test/options/paramTypes.ts
+++ b/test/options/paramTypes.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsParamTypes(format: FormatFn) {
   describe('when paramTypes.positional=true', () => {
diff --git a/test/options/tabWidth.ts b/test/options/tabWidth.ts
index 66ee57dd..870f880d 100644
--- a/test/options/tabWidth.ts
+++ b/test/options/tabWidth.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsTabWidth(format: FormatFn) {
   it('indents with 2 spaces by default', () => {
diff --git a/test/options/tabulateAlias.ts b/test/options/tabulateAlias.ts
index 84b58b45..5cccb95b 100644
--- a/test/options/tabulateAlias.ts
+++ b/test/options/tabulateAlias.ts
@@ -1,6 +1,6 @@
 import dedent from 'dedent-js';
 
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsTabulateAlias(format: FormatFn) {
   it('tabulates aliases which use AS keyword', () => {
diff --git a/test/options/useTabs.ts b/test/options/useTabs.ts
index beaf63bd..59ff0816 100644
--- a/test/options/useTabs.ts
+++ b/test/options/useTabs.ts
@@ -1,4 +1,4 @@
-import { FormatFn } from 'src/sqlFormatter';
+import { FormatFn } from '../../src/sqlFormatter.js';
 
 export default function supportsUseTabs(format: FormatFn) {
   it('supports indenting with tabs', () => {
diff --git a/test/plsql.test.ts b/test/plsql.test.ts
index 43f31cf2..b1f6010d 100644
--- a/test/plsql.test.ts
+++ b/test/plsql.test.ts
@@ -1,29 +1,29 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
 
-import supportsAlterTable from './features/alterTable';
-import supportsBetween from './features/between';
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsSchema from './features/schema';
-import supportsStrings from './features/strings';
-import supportsReturning from './features/returning';
-import supportsConstraints from './features/constraints';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsParams from './options/param';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsTruncateTable from './features/truncateTable';
-import supportsMergeInto from './features/mergeInto';
-import supportsCreateView from './features/createView';
+import supportsAlterTable from './features/alterTable.js';
+import supportsBetween from './features/between.js';
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsSchema from './features/schema.js';
+import supportsStrings from './features/strings.js';
+import supportsReturning from './features/returning.js';
+import supportsConstraints from './features/constraints.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsParams from './options/param.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsTruncateTable from './features/truncateTable.js';
+import supportsMergeInto from './features/mergeInto.js';
+import supportsCreateView from './features/createView.js';
 
 describe('PlSqlFormatter', () => {
   const language = 'plsql';
diff --git a/test/postgresql.test.ts b/test/postgresql.test.ts
index 6b212f21..59d1a0bf 100644
--- a/test/postgresql.test.ts
+++ b/test/postgresql.test.ts
@@ -1,30 +1,30 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
 
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
-import supportsAlterTable from './features/alterTable';
-import supportsBetween from './features/between';
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsSchema from './features/schema';
-import supportsStrings from './features/strings';
-import supportsReturning from './features/returning';
-import supportsConstraints from './features/constraints';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsParams from './options/param';
-import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors';
-import supportsWindow from './features/window';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsTruncateTable from './features/truncateTable';
-import supportsCreateView from './features/createView';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
+import supportsAlterTable from './features/alterTable.js';
+import supportsBetween from './features/between.js';
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsSchema from './features/schema.js';
+import supportsStrings from './features/strings.js';
+import supportsReturning from './features/returning.js';
+import supportsConstraints from './features/constraints.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsParams from './options/param.js';
+import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors.js';
+import supportsWindow from './features/window.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsTruncateTable from './features/truncateTable.js';
+import supportsCreateView from './features/createView.js';
 
 describe('PostgreSqlFormatter', () => {
   const language = 'postgresql';
diff --git a/test/redshift.test.ts b/test/redshift.test.ts
index a537330b..6bdb52d0 100644
--- a/test/redshift.test.ts
+++ b/test/redshift.test.ts
@@ -1,24 +1,24 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
 
-import supportsAlterTable from './features/alterTable';
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsStrings from './features/strings';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsParams from './options/param';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsTruncateTable from './features/truncateTable';
-import supportsCreateView from './features/createView';
+import supportsAlterTable from './features/alterTable.js';
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsStrings from './features/strings.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsParams from './options/param.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsTruncateTable from './features/truncateTable.js';
+import supportsCreateView from './features/createView.js';
 
 describe('RedshiftFormatter', () => {
   const language = 'redshift';
diff --git a/test/singlestoredb.test.ts b/test/singlestoredb.test.ts
index 8aa6c184..5907f981 100644
--- a/test/singlestoredb.test.ts
+++ b/test/singlestoredb.test.ts
@@ -1,14 +1,14 @@
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeMariaDbFormatter from './behavesLikeMariaDbFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeMariaDbFormatter from './behavesLikeMariaDbFormatter.js';
 
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsCreateTable from './features/createTable';
-import supportsCreateView from './features/createView';
-import supportsAlterTable from './features/alterTable';
-import supportsStrings from './features/strings';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsCreateTable from './features/createTable.js';
+import supportsCreateView from './features/createView.js';
+import supportsAlterTable from './features/alterTable.js';
+import supportsStrings from './features/strings.js';
 
 describe('SingleStoreDbFormatter', () => {
   const language = 'singlestoredb';
diff --git a/test/snowflake.test.ts b/test/snowflake.test.ts
index 031aab53..cd9168ce 100644
--- a/test/snowflake.test.ts
+++ b/test/snowflake.test.ts
@@ -1,26 +1,26 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
-import supportsAlterTable from './features/alterTable';
-import supportsBetween from './features/between';
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsStrings from './features/strings';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsTruncateTable from './features/truncateTable';
-import supportsCreateView from './features/createView';
-import supportsConstraints from './features/constraints';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
+import supportsAlterTable from './features/alterTable.js';
+import supportsBetween from './features/between.js';
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsStrings from './features/strings.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsTruncateTable from './features/truncateTable.js';
+import supportsCreateView from './features/createView.js';
+import supportsConstraints from './features/constraints.js';
 
 describe('SnowflakeFormatter', () => {
   const language = 'snowflake';
diff --git a/test/spark.test.ts b/test/spark.test.ts
index b405c600..5bbb2ecc 100644
--- a/test/spark.test.ts
+++ b/test/spark.test.ts
@@ -1,23 +1,23 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
 
-import supportsAlterTable from './features/alterTable';
-import supportsBetween from './features/between';
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsStrings from './features/strings';
-import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsTruncateTable from './features/truncateTable';
-import supportsCreateView from './features/createView';
+import supportsAlterTable from './features/alterTable.js';
+import supportsBetween from './features/between.js';
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsStrings from './features/strings.js';
+import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsTruncateTable from './features/truncateTable.js';
+import supportsCreateView from './features/createView.js';
 
 describe('SparkFormatter', () => {
   const language = 'spark';
diff --git a/test/sql.test.ts b/test/sql.test.ts
index 579bf9a9..1cc78ea0 100644
--- a/test/sql.test.ts
+++ b/test/sql.test.ts
@@ -1,28 +1,28 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
 
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsAlterTable from './features/alterTable';
-import supportsSchema from './features/schema';
-import supportsStrings from './features/strings';
-import supportsBetween from './features/between';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsConstraints from './features/constraints';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsParams from './options/param';
-import supportsWindow from './features/window';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsTruncateTable from './features/truncateTable';
-import supportsCreateView from './features/createView';
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsAlterTable from './features/alterTable.js';
+import supportsSchema from './features/schema.js';
+import supportsStrings from './features/strings.js';
+import supportsBetween from './features/between.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsConstraints from './features/constraints.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsParams from './options/param.js';
+import supportsWindow from './features/window.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsTruncateTable from './features/truncateTable.js';
+import supportsCreateView from './features/createView.js';
 
 describe('SqlFormatter', () => {
   const language = 'sql';
diff --git a/test/sql/README.md b/test/sql/README.md
index 27eaf492..8926e05e 100644
--- a/test/sql/README.md
+++ b/test/sql/README.md
@@ -7,7 +7,7 @@ SQL files can be imported into test files as text files, allowing them to be use
 Example:
 
 ```ts
-import testSql from './test.sql';
+import testSql from './test.sql.js';
 ```
 
 or using the `fs` library:
diff --git a/test/sqlFormatter.test.ts b/test/sqlFormatter.test.ts
index 540389d1..8492136c 100644
--- a/test/sqlFormatter.test.ts
+++ b/test/sqlFormatter.test.ts
@@ -1,7 +1,7 @@
 import dedent from 'dedent-js';
 
-import { format, SqlLanguage } from 'src/sqlFormatter';
-import SqliteFormatter from 'src/languages/sqlite/sqlite.formatter';
+import { format, SqlLanguage } from '../src/sqlFormatter.js';
+import SqliteFormatter from '../src/languages/sqlite/sqlite.formatter.js';
 
 describe('sqlFormatter', () => {
   it('throws error when unsupported language parameter specified', () => {
diff --git a/test/sqlite.test.ts b/test/sqlite.test.ts
index 81ecf193..5106717f 100644
--- a/test/sqlite.test.ts
+++ b/test/sqlite.test.ts
@@ -1,26 +1,26 @@
 import dedent from 'dedent-js';
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
 
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsAlterTable from './features/alterTable';
-import supportsSchema from './features/schema';
-import supportsStrings from './features/strings';
-import supportsBetween from './features/between';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsConstraints from './features/constraints';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsParams from './options/param';
-import supportsWindow from './features/window';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsCreateView from './features/createView';
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsAlterTable from './features/alterTable.js';
+import supportsSchema from './features/schema.js';
+import supportsStrings from './features/strings.js';
+import supportsBetween from './features/between.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsConstraints from './features/constraints.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsParams from './options/param.js';
+import supportsWindow from './features/window.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsCreateView from './features/createView.js';
 
 describe('SqliteFormatter', () => {
   const language = 'sqlite';
diff --git a/test/transactsql.test.ts b/test/transactsql.test.ts
index c6ff9048..cdcfe4d0 100644
--- a/test/transactsql.test.ts
+++ b/test/transactsql.test.ts
@@ -1,28 +1,28 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
 
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsAlterTable from './features/alterTable';
-import supportsStrings from './features/strings';
-import supportsBetween from './features/between';
-import supportsOperators from './features/operators';
-import supportsJoin from './features/join';
-import supportsConstraints from './features/constraints';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsParams from './options/param';
-import supportsWindow from './features/window';
-import supportsSetOperations from './features/setOperations';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsTruncateTable from './features/truncateTable';
-import supportsMergeInto from './features/mergeInto';
-import supportsCreateView from './features/createView';
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsAlterTable from './features/alterTable.js';
+import supportsStrings from './features/strings.js';
+import supportsBetween from './features/between.js';
+import supportsOperators from './features/operators.js';
+import supportsJoin from './features/join.js';
+import supportsConstraints from './features/constraints.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsParams from './options/param.js';
+import supportsWindow from './features/window.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsTruncateTable from './features/truncateTable.js';
+import supportsMergeInto from './features/mergeInto.js';
+import supportsCreateView from './features/createView.js';
 
 describe('TransactSqlFormatter', () => {
   const language = 'transactsql';
diff --git a/test/trino.test.ts b/test/trino.test.ts
index 540b5219..34446a6b 100644
--- a/test/trino.test.ts
+++ b/test/trino.test.ts
@@ -1,28 +1,28 @@
 import dedent from 'dedent-js';
 
-import { format as originalFormat, FormatFn } from 'src/sqlFormatter';
-import behavesLikeSqlFormatter from './behavesLikeSqlFormatter';
+import { format as originalFormat, FormatFn } from '../src/sqlFormatter.js';
+import behavesLikeSqlFormatter from './behavesLikeSqlFormatter.js';
 
-import supportsArrayLiterals from './features/arrayLiterals';
-import supportsBetween from './features/between';
-import supportsCreateTable from './features/createTable';
-import supportsDropTable from './features/dropTable';
-import supportsDeleteFrom from './features/deleteFrom';
-import supportsJoin from './features/join';
-import supportsOperators from './features/operators';
-import supportsStrings from './features/strings';
-import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors';
-import supportsComments from './features/comments';
-import supportsIdentifiers from './features/identifiers';
-import supportsParams from './options/param';
-import supportsSetOperations from './features/setOperations';
-import supportsWindow from './features/window';
-import supportsLimiting from './features/limiting';
-import supportsInsertInto from './features/insertInto';
-import supportsUpdate from './features/update';
-import supportsTruncateTable from './features/truncateTable';
-import supportsCreateView from './features/createView';
-import supportsAlterTable from './features/alterTable';
+import supportsArrayLiterals from './features/arrayLiterals.js';
+import supportsBetween from './features/between.js';
+import supportsCreateTable from './features/createTable.js';
+import supportsDropTable from './features/dropTable.js';
+import supportsDeleteFrom from './features/deleteFrom.js';
+import supportsJoin from './features/join.js';
+import supportsOperators from './features/operators.js';
+import supportsStrings from './features/strings.js';
+import supportsArrayAndMapAccessors from './features/arrayAndMapAccessors.js';
+import supportsComments from './features/comments.js';
+import supportsIdentifiers from './features/identifiers.js';
+import supportsParams from './options/param.js';
+import supportsSetOperations from './features/setOperations.js';
+import supportsWindow from './features/window.js';
+import supportsLimiting from './features/limiting.js';
+import supportsInsertInto from './features/insertInto.js';
+import supportsUpdate from './features/update.js';
+import supportsTruncateTable from './features/truncateTable.js';
+import supportsCreateView from './features/createView.js';
+import supportsAlterTable from './features/alterTable.js';
 
 describe('TrinoFormatter', () => {
   const language = 'trino';
diff --git a/test/unit/Layout.test.ts b/test/unit/Layout.test.ts
index 539339da..1b8c00a9 100644
--- a/test/unit/Layout.test.ts
+++ b/test/unit/Layout.test.ts
@@ -1,5 +1,5 @@
-import Indentation from 'src/formatter/Indentation';
-import Layout, { WS } from 'src/formatter/Layout';
+import Indentation from '../../src/formatter/Indentation.js';
+import Layout, { WS } from '../../src/formatter/Layout.js';
 
 describe('Layout', () => {
   function testLayout(...items: (WS | string)[]): string {
diff --git a/test/unit/NestedComment.test.ts b/test/unit/NestedComment.test.ts
index fe0567f2..7e1b5c89 100644
--- a/test/unit/NestedComment.test.ts
+++ b/test/unit/NestedComment.test.ts
@@ -1,4 +1,4 @@
-import { NestedComment } from 'src/lexer/NestedComment';
+import { NestedComment } from '../../src/lexer/NestedComment.js';
 
 describe('NestedComment', () => {
   const match = (input: string, index: number) => {
diff --git a/test/unit/Parser.test.ts b/test/unit/Parser.test.ts
index f98f666f..0e619c63 100644
--- a/test/unit/Parser.test.ts
+++ b/test/unit/Parser.test.ts
@@ -1,5 +1,5 @@
-import Tokenizer from 'src/lexer/Tokenizer';
-import { createParser } from 'src/parser/createParser';
+import Tokenizer from '../../src/lexer/Tokenizer.js';
+import { createParser } from '../../src/parser/createParser.js';
 
 describe('Parser', () => {
   const parse = (sql: string) => {
diff --git a/test/unit/Tokenizer.test.ts b/test/unit/Tokenizer.test.ts
index 95ed7859..8ef11f9e 100644
--- a/test/unit/Tokenizer.test.ts
+++ b/test/unit/Tokenizer.test.ts
@@ -1,4 +1,4 @@
-import Tokenizer from 'src/lexer/Tokenizer';
+import Tokenizer from '../../src/lexer/Tokenizer.js';
 
 describe('Tokenizer', () => {
   const tokenize = (sql: string) =>
diff --git a/test/unit/expandPhrases.test.ts b/test/unit/expandPhrases.test.ts
index b505758e..b5a32b9b 100644
--- a/test/unit/expandPhrases.test.ts
+++ b/test/unit/expandPhrases.test.ts
@@ -1,4 +1,4 @@
-import { expandSinglePhrase } from 'src/expandPhrases';
+import { expandSinglePhrase } from '../../src/expandPhrases.js';
 
 describe('expandSinglePhrase()', () => {
   it('returns single item when no [optional blocks] found', () => {
diff --git a/test/unit/tabularStyle.test.ts b/test/unit/tabularStyle.test.ts
index 3ae93794..5d8df2e3 100644
--- a/test/unit/tabularStyle.test.ts
+++ b/test/unit/tabularStyle.test.ts
@@ -1,4 +1,4 @@
-import toTabularFormat from 'src/formatter/tabularStyle';
+import toTabularFormat from '../../src/formatter/tabularStyle.js';
 
 describe('toTabularFormat()', () => {
   it('does nothing in standard style', () => {