inline-sql-toolkit 0.4.10 → 0.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/README.md +12 -1
- package/dist/cli.js +158 -4
- package/package.json +17 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.12 - 2026-09-24
|
|
4
|
+
|
|
5
|
+
- Feature: added the `inlineSql.format.keepFunctionsInline` setting (default
|
|
6
|
+
`false`). `sql-formatter` has no option that holds function arguments on
|
|
7
|
+
one line — it breaks `CASE` structurally regardless of `wrapAfter` — so the
|
|
8
|
+
extension re-joins the line breaks the engine inserts inside `word(...)`
|
|
9
|
+
groups as a post-pass over its output. With the setting on,
|
|
10
|
+
`COUNT(CASE WHEN a THEN 1 ELSE 0 END)` stays on a single line while select
|
|
11
|
+
lists, clause breaks, and `AND` / `OR` chains keep their usual layout.
|
|
12
|
+
- The same choice is exposed everywhere the other options are: the VS Code
|
|
13
|
+
setting, the CLI flag `--keep-functions-inline`, and
|
|
14
|
+
`"keepFunctionsInline"` in `.inline-sql.json`, under the unchanged CLI
|
|
15
|
+
flags > configuration file > defaults precedence.
|
|
16
|
+
- Safety: only newlines in code state are removed. A newline inside a string
|
|
17
|
+
literal, a `$$ … $$` body, or a block comment is copied verbatim, and the
|
|
18
|
+
newline that terminates a `-- line comment` is kept, so literal content can
|
|
19
|
+
never change and no code can fall into a comment. The default `false`
|
|
20
|
+
reproduces the previous output byte for byte, and the fixed-point loop still
|
|
21
|
+
skips any candidate whose formatting does not converge.
|
|
22
|
+
|
|
23
|
+
## 0.4.11 - 2026-09-24
|
|
24
|
+
|
|
25
|
+
- Feature: added the `inlineSql.format.commaPosition` setting (`after` |
|
|
26
|
+
`before`, default `after`) for codebases that want a wrapped item's comma at
|
|
27
|
+
the start of the next line instead of the end of the previous one. The
|
|
28
|
+
default reproduces the previous output byte for byte, so existing files do
|
|
29
|
+
not move until the setting is turned on; `before` emits the comma at the
|
|
30
|
+
next line's indent in front of the item, and a trailing `-- comment` stays
|
|
31
|
+
with its own column (`order_id -- note` followed by `, order_date -- note`)
|
|
32
|
+
rather than pinning the comma behind it.
|
|
33
|
+
- The same choice is exposed everywhere the other options are: the VS Code
|
|
34
|
+
setting, the CLI flag `--comma-position after|before`, and
|
|
35
|
+
`"commaPosition"` in `.inline-sql.json`, under the unchanged CLI flags >
|
|
36
|
+
configuration file > defaults precedence.
|
|
37
|
+
- Safety: `sql-formatter` removed its own `commaPosition` option long ago, so
|
|
38
|
+
the move is a small post-pass over its output. A scanner locates the
|
|
39
|
+
wrapping separator comma and never moves one from inside a quoted string
|
|
40
|
+
(`'...'`, `"..."`, backticks) or from after a `--` line comment, and a
|
|
41
|
+
candidate whose output still fails to converge to a fixed point is skipped
|
|
42
|
+
untouched as before, so no file can be rewritten with corrupted SQL.
|
|
43
|
+
|
|
3
44
|
## 0.4.10 - 2026-09-19
|
|
4
45
|
|
|
5
46
|
- CI: the npm publish job is now OIDC-only. The dormant `NPM_TOKEN` path that was
|
package/README.md
CHANGED
|
@@ -110,6 +110,13 @@ later atomic precondition.
|
|
|
110
110
|
aliases (default `true`).
|
|
111
111
|
- `inlineSql.format.dialect`: SQL dialect used by the formatter (`sql`,
|
|
112
112
|
`mysql`, `postgresql`, or `sqlite`; default `postgresql`).
|
|
113
|
+
- `inlineSql.format.commaPosition`: `after` (default) keeps a wrapping comma at
|
|
114
|
+
the end of the previous line; `before` moves it to the start of the next
|
|
115
|
+
line.
|
|
116
|
+
- `inlineSql.format.keepFunctionsInline`: re-join the formatter's line breaks
|
|
117
|
+
inside `word(...)` groups so `SUM(...)`, `COUNT(CASE ... END)`, and nested
|
|
118
|
+
calls stay on one line (default `false`). Newlines inside string literals and
|
|
119
|
+
comments are never removed.
|
|
113
120
|
|
|
114
121
|
The extension highlights inline SQL with an injected TextMate grammar: SQL
|
|
115
122
|
strings that start with `-- sql` (or a leading SQL keyword) are embedded as
|
|
@@ -144,6 +151,8 @@ When run without file arguments, the CLI reads Python source from standard input
|
|
|
144
151
|
| `--wrap-after <20-500>` | Preferred expression line width | `88` |
|
|
145
152
|
| `--no-space-around-operators` | Keep dense operators | spaced |
|
|
146
153
|
| `--no-ordinals` | Do not replace `GROUP BY` / `ORDER BY` ordinals with column names | replace |
|
|
154
|
+
| `--comma-position <pos>` | Where a wrapping comma sits: `after` or `before` | `after` |
|
|
155
|
+
| `--keep-functions-inline` | Keep `SUM(...)` / `COUNT(CASE ... END)` on one line | off |
|
|
147
156
|
| `-c, --config <file>` | Configuration JSON file | Nearest `.inline-sql.json` |
|
|
148
157
|
| `-h, --help` | Show usage help | |
|
|
149
158
|
| `--version` | Show version number | |
|
|
@@ -162,7 +171,9 @@ The CLI automatically searches for a `.inline-sql.json` file in the current work
|
|
|
162
171
|
"wrapAfter": 88,
|
|
163
172
|
"useSpaceAroundOperators": true,
|
|
164
173
|
"replaceOrdinals": true,
|
|
165
|
-
"dialect": "postgresql"
|
|
174
|
+
"dialect": "postgresql",
|
|
175
|
+
"commaPosition": "after",
|
|
176
|
+
"keepFunctionsInline": false
|
|
166
177
|
}
|
|
167
178
|
}
|
|
168
179
|
```
|
package/dist/cli.js
CHANGED
|
@@ -494,7 +494,9 @@ function resolveFormatOptions(raw) {
|
|
|
494
494
|
const useSpaceAroundOperators = raw.useSpaceAroundOperators === void 0 ? true : raw.useSpaceAroundOperators;
|
|
495
495
|
const replaceOrdinals2 = raw.replaceOrdinals === void 0 ? true : raw.replaceOrdinals;
|
|
496
496
|
const dialect = raw.dialect === void 0 ? "postgresql" : raw.dialect;
|
|
497
|
-
|
|
497
|
+
const commaPosition = raw.commaPosition === void 0 ? "after" : raw.commaPosition;
|
|
498
|
+
const keepFunctionsInline = raw.keepFunctionsInline === void 0 ? false : raw.keepFunctionsInline;
|
|
499
|
+
if (keywordCase !== "upper" && keywordCase !== "lower" && keywordCase !== "preserve" || !integerBetween(indentWidth, 1, 8) || !integerBetween(wrapAfter, 20, 500) || typeof useSpaceAroundOperators !== "boolean" || typeof replaceOrdinals2 !== "boolean" || dialect !== "sql" && dialect !== "mysql" && dialect !== "postgresql" && dialect !== "sqlite" || commaPosition !== "after" && commaPosition !== "before" || typeof keepFunctionsInline !== "boolean") {
|
|
498
500
|
return { ok: false, reason: "INVALID_CONFIGURATION" };
|
|
499
501
|
}
|
|
500
502
|
return {
|
|
@@ -505,7 +507,9 @@ function resolveFormatOptions(raw) {
|
|
|
505
507
|
wrapAfter,
|
|
506
508
|
useSpaceAroundOperators,
|
|
507
509
|
replaceOrdinals: replaceOrdinals2,
|
|
508
|
-
dialect
|
|
510
|
+
dialect,
|
|
511
|
+
commaPosition,
|
|
512
|
+
keepFunctionsInline
|
|
509
513
|
}
|
|
510
514
|
};
|
|
511
515
|
}
|
|
@@ -1584,6 +1588,144 @@ function breakTrailingDistributeLines(text) {
|
|
|
1584
1588
|
${indent}${rest}`
|
|
1585
1589
|
);
|
|
1586
1590
|
}
|
|
1591
|
+
function wrappingComma(line) {
|
|
1592
|
+
let comma = -1;
|
|
1593
|
+
for (let index = 0; index < line.length; index++) {
|
|
1594
|
+
const char = line[index];
|
|
1595
|
+
if (char === "'" || char === '"' || char === "`") {
|
|
1596
|
+
for (index += 1; index < line.length && line[index] !== char; index++) {
|
|
1597
|
+
if (line[index] === "\\") index += 1;
|
|
1598
|
+
}
|
|
1599
|
+
continue;
|
|
1600
|
+
}
|
|
1601
|
+
if (char === "-" && line[index + 1] === "-") break;
|
|
1602
|
+
if (char === ",") comma = index;
|
|
1603
|
+
}
|
|
1604
|
+
if (comma < 0) return -1;
|
|
1605
|
+
return /^[ \t]*(?:--.*)?$/.test(line.slice(comma + 1)) ? comma : -1;
|
|
1606
|
+
}
|
|
1607
|
+
function moveCommasToLineStarts(text) {
|
|
1608
|
+
const lines = text.split("\n");
|
|
1609
|
+
for (let index = 0; index + 1 < lines.length; index++) {
|
|
1610
|
+
const line = lines[index] ?? "";
|
|
1611
|
+
const next = lines[index + 1] ?? "";
|
|
1612
|
+
if (next.trim() === "") continue;
|
|
1613
|
+
const comma = wrappingComma(line);
|
|
1614
|
+
if (comma < 0 || line.slice(0, comma).trim() === "") continue;
|
|
1615
|
+
const nextParts = /^([ \t]*)([\s\S]*)$/.exec(next);
|
|
1616
|
+
const indent = nextParts?.[1] ?? "";
|
|
1617
|
+
const content = nextParts?.[2] ?? "";
|
|
1618
|
+
lines[index] = `${line.slice(0, comma)}${line.slice(comma + 1)}`.trimEnd();
|
|
1619
|
+
lines[index + 1] = `${indent}, ${content}`;
|
|
1620
|
+
}
|
|
1621
|
+
return lines.join("\n");
|
|
1622
|
+
}
|
|
1623
|
+
var DOLLAR_QUOTE = /\$[A-Za-z_][A-Za-z0-9_]*\$|\$\$/y;
|
|
1624
|
+
function rejoinFunctionCalls(text) {
|
|
1625
|
+
const stack = [];
|
|
1626
|
+
let out = "";
|
|
1627
|
+
let i = 0;
|
|
1628
|
+
const at = (index) => text.charAt(index);
|
|
1629
|
+
const isCallOpener = () => {
|
|
1630
|
+
const match = /[A-Za-z_][A-Za-z0-9_]*\s*$/.exec(out);
|
|
1631
|
+
if (match === null) return false;
|
|
1632
|
+
const before = out.slice(0, match.index);
|
|
1633
|
+
return before === "" || !/[A-Za-z0-9_]$/.test(before);
|
|
1634
|
+
};
|
|
1635
|
+
while (i < text.length) {
|
|
1636
|
+
const ch = at(i);
|
|
1637
|
+
if (ch === "'" || ch === '"' || ch === "`") {
|
|
1638
|
+
const quote = ch;
|
|
1639
|
+
out += ch;
|
|
1640
|
+
i += 1;
|
|
1641
|
+
while (i < text.length) {
|
|
1642
|
+
if (at(i) === quote && at(i + 1) === quote) {
|
|
1643
|
+
out += at(i) + at(i + 1);
|
|
1644
|
+
i += 2;
|
|
1645
|
+
continue;
|
|
1646
|
+
}
|
|
1647
|
+
out += at(i);
|
|
1648
|
+
i += 1;
|
|
1649
|
+
if (at(i - 1) === quote) break;
|
|
1650
|
+
if (at(i - 1) === "\\" && quote !== "`" && i < text.length) {
|
|
1651
|
+
out += at(i);
|
|
1652
|
+
i += 1;
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
continue;
|
|
1656
|
+
}
|
|
1657
|
+
if (ch === "$") {
|
|
1658
|
+
DOLLAR_QUOTE.lastIndex = i;
|
|
1659
|
+
const dollar = DOLLAR_QUOTE.exec(text);
|
|
1660
|
+
if (dollar !== null) {
|
|
1661
|
+
const end = text.indexOf(dollar[0], i + dollar[0].length);
|
|
1662
|
+
const stop = end === -1 ? text.length : end + dollar[0].length;
|
|
1663
|
+
out += text.slice(i, stop);
|
|
1664
|
+
i = stop;
|
|
1665
|
+
continue;
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
if (ch === "-" && at(i + 1) === "-" || ch === "#") {
|
|
1669
|
+
while (i < text.length && at(i) !== "\n") {
|
|
1670
|
+
out += at(i);
|
|
1671
|
+
i += 1;
|
|
1672
|
+
}
|
|
1673
|
+
if (i < text.length) {
|
|
1674
|
+
out += at(i);
|
|
1675
|
+
i += 1;
|
|
1676
|
+
}
|
|
1677
|
+
continue;
|
|
1678
|
+
}
|
|
1679
|
+
if (ch === "/" && at(i + 1) === "*") {
|
|
1680
|
+
out += "/*";
|
|
1681
|
+
i += 2;
|
|
1682
|
+
while (i < text.length && !(at(i) === "*" && at(i + 1) === "/")) {
|
|
1683
|
+
out += at(i);
|
|
1684
|
+
i += 1;
|
|
1685
|
+
}
|
|
1686
|
+
if (i < text.length) {
|
|
1687
|
+
out += "*/";
|
|
1688
|
+
i += 2;
|
|
1689
|
+
}
|
|
1690
|
+
continue;
|
|
1691
|
+
}
|
|
1692
|
+
if (ch === "\n") {
|
|
1693
|
+
if (stack.includes(true)) {
|
|
1694
|
+
let indent = i + 1;
|
|
1695
|
+
while (indent < text.length && (at(indent) === " " || at(indent) === " ")) {
|
|
1696
|
+
indent += 1;
|
|
1697
|
+
}
|
|
1698
|
+
let peek = indent;
|
|
1699
|
+
while (peek < text.length && (at(peek) === "\n" || at(peek) === " " || at(peek) === " ")) {
|
|
1700
|
+
peek += 1;
|
|
1701
|
+
}
|
|
1702
|
+
const next = at(peek);
|
|
1703
|
+
const prev = out.slice(-1);
|
|
1704
|
+
i = indent;
|
|
1705
|
+
if (prev !== "(" && next !== "," && next !== ")") out += " ";
|
|
1706
|
+
} else {
|
|
1707
|
+
out += ch;
|
|
1708
|
+
i += 1;
|
|
1709
|
+
}
|
|
1710
|
+
continue;
|
|
1711
|
+
}
|
|
1712
|
+
if (ch === "(") {
|
|
1713
|
+
stack.push(isCallOpener());
|
|
1714
|
+
out += ch;
|
|
1715
|
+
i += 1;
|
|
1716
|
+
continue;
|
|
1717
|
+
}
|
|
1718
|
+
if (ch === ")") {
|
|
1719
|
+
stack.pop();
|
|
1720
|
+
out += ch;
|
|
1721
|
+
i += 1;
|
|
1722
|
+
continue;
|
|
1723
|
+
}
|
|
1724
|
+
out += ch;
|
|
1725
|
+
i += 1;
|
|
1726
|
+
}
|
|
1727
|
+
return out;
|
|
1728
|
+
}
|
|
1587
1729
|
function formatOnce(analysis, literal, detection, options, nonce, sqlFormatter) {
|
|
1588
1730
|
const plan = buildProtectionPlan(analysis.sourceMap, literal, detection, nonce);
|
|
1589
1731
|
let formatted = sqlFormatter(plan.protectedSql, {
|
|
@@ -1598,6 +1740,12 @@ function formatOnce(analysis, literal, detection, options, nonce, sqlFormatter)
|
|
|
1598
1740
|
}
|
|
1599
1741
|
formatted = breakTrailingFieldMarkers(formatted);
|
|
1600
1742
|
formatted = moveCommasBeforeLineComments(formatted);
|
|
1743
|
+
if (options.keepFunctionsInline) {
|
|
1744
|
+
formatted = rejoinFunctionCalls(formatted);
|
|
1745
|
+
}
|
|
1746
|
+
if (options.commaPosition === "before") {
|
|
1747
|
+
formatted = moveCommasToLineStarts(formatted);
|
|
1748
|
+
}
|
|
1601
1749
|
formatted = breakTrailingDistributeLines(formatted);
|
|
1602
1750
|
const restored = restoreProtected(formatted, plan);
|
|
1603
1751
|
const resolved = options.replaceOrdinals ? replaceOrdinals(restored) : restored;
|
|
@@ -1824,7 +1972,7 @@ function formatDocument(source, options, target, nonce, sqlFormatter, logger) {
|
|
|
1824
1972
|
};
|
|
1825
1973
|
if (logger !== void 0) {
|
|
1826
1974
|
logger(
|
|
1827
|
-
`format: dialect=${options.dialect} keywordCase=${options.keywordCase} indentWidth=${options.indentWidth} wrapAfter=${options.wrapAfter} useSpaceAroundOperators=${options.useSpaceAroundOperators} replaceOrdinals=${options.replaceOrdinals} discovered=${summary.discovered} selected=${summary.selected} changed=${summary.changed} unchanged=${summary.unchanged} skipped=${summary.skipped}${skipReasons.length > 0 ? ` reasons=[${skipReasons.join(", ")}]` : ""}`
|
|
1975
|
+
`format: dialect=${options.dialect} keywordCase=${options.keywordCase} indentWidth=${options.indentWidth} wrapAfter=${options.wrapAfter} useSpaceAroundOperators=${options.useSpaceAroundOperators} replaceOrdinals=${options.replaceOrdinals} commaPosition=${options.commaPosition} keepFunctionsInline=${options.keepFunctionsInline} discovered=${summary.discovered} selected=${summary.selected} changed=${summary.changed} unchanged=${summary.unchanged} skipped=${summary.skipped}${skipReasons.length > 0 ? ` reasons=[${skipReasons.join(", ")}]` : ""}`
|
|
1828
1976
|
);
|
|
1829
1977
|
}
|
|
1830
1978
|
return {
|
|
@@ -22476,6 +22624,8 @@ var USAGE = `Usage: inline-sql-toolkit [options] [files...]
|
|
|
22476
22624
|
--wrap-after <20-500> (default: 88)
|
|
22477
22625
|
--no-space-around-operators keep dense operators (default: spaced)
|
|
22478
22626
|
--no-ordinals do not replace GROUP BY / ORDER BY ordinals
|
|
22627
|
+
--comma-position <pos> after | before (default: after)
|
|
22628
|
+
--keep-functions-inline keep SUM(...) / COUNT(CASE ...) on one line
|
|
22479
22629
|
-c, --config <file> config JSON (default: nearest .inline-sql.json)
|
|
22480
22630
|
-h, --help / --version`;
|
|
22481
22631
|
function printError(message) {
|
|
@@ -22534,7 +22684,9 @@ function buildRawOptions(fileOptions, cliValues) {
|
|
|
22534
22684
|
indentWidth: cliValues["indent-width"] !== void 0 ? Number(cliValues["indent-width"]) : fileOptions.indentWidth,
|
|
22535
22685
|
wrapAfter: cliValues["wrap-after"] !== void 0 ? Number(cliValues["wrap-after"]) : fileOptions.wrapAfter,
|
|
22536
22686
|
useSpaceAroundOperators: cliValues["no-space-around-operators"] ? false : fileOptions.useSpaceAroundOperators,
|
|
22537
|
-
replaceOrdinals: cliValues["no-ordinals"] ? false : fileOptions.replaceOrdinals
|
|
22687
|
+
replaceOrdinals: cliValues["no-ordinals"] ? false : fileOptions.replaceOrdinals,
|
|
22688
|
+
commaPosition: cliValues["comma-position"] ?? fileOptions.commaPosition,
|
|
22689
|
+
keepFunctionsInline: cliValues["keep-functions-inline"] ? true : fileOptions.keepFunctionsInline
|
|
22538
22690
|
};
|
|
22539
22691
|
}
|
|
22540
22692
|
function formatPythonSource(text, options, logger) {
|
|
@@ -22570,6 +22722,8 @@ function runCli(argv) {
|
|
|
22570
22722
|
"wrap-after": { type: "string" },
|
|
22571
22723
|
"no-space-around-operators": { type: "boolean", default: false },
|
|
22572
22724
|
"no-ordinals": { type: "boolean", default: false },
|
|
22725
|
+
"comma-position": { type: "string" },
|
|
22726
|
+
"keep-functions-inline": { type: "boolean", default: false },
|
|
22573
22727
|
config: { type: "string", short: "c" },
|
|
22574
22728
|
help: { type: "boolean", short: "h", default: false },
|
|
22575
22729
|
version: { type: "boolean", default: false }
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/hidenobunagai/inline-sql-toolkit/issues"
|
|
13
13
|
},
|
|
14
|
-
"version": "0.4.
|
|
14
|
+
"version": "0.4.12",
|
|
15
15
|
"icon": "icon.png",
|
|
16
16
|
"type": "module",
|
|
17
17
|
"bin": {
|
|
@@ -104,6 +104,22 @@
|
|
|
104
104
|
"default": "postgresql",
|
|
105
105
|
"scope": "resource",
|
|
106
106
|
"description": "%configuration.format.dialect.description%"
|
|
107
|
+
},
|
|
108
|
+
"inlineSql.format.commaPosition": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"enum": [
|
|
111
|
+
"after",
|
|
112
|
+
"before"
|
|
113
|
+
],
|
|
114
|
+
"default": "after",
|
|
115
|
+
"scope": "resource",
|
|
116
|
+
"description": "%configuration.format.commaPosition.description%"
|
|
117
|
+
},
|
|
118
|
+
"inlineSql.format.keepFunctionsInline": {
|
|
119
|
+
"type": "boolean",
|
|
120
|
+
"default": false,
|
|
121
|
+
"scope": "resource",
|
|
122
|
+
"description": "%configuration.format.keepFunctionsInline.description%"
|
|
107
123
|
}
|
|
108
124
|
}
|
|
109
125
|
},
|