tsx-sql 0.1.0
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/LICENSE +21 -0
- package/README.md +169 -0
- package/dist/index.cjs +160 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +130 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-dev-runtime.cjs +53 -0
- package/dist/jsx-dev-runtime.cjs.map +1 -0
- package/dist/jsx-dev-runtime.d.cts +2 -0
- package/dist/jsx-dev-runtime.d.ts +2 -0
- package/dist/jsx-dev-runtime.js +23 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.cjs +51 -0
- package/dist/jsx-runtime.cjs.map +1 -0
- package/dist/jsx-runtime.d.cts +16 -0
- package/dist/jsx-runtime.d.ts +16 -0
- package/dist/jsx-runtime.js +22 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/node-DV0niL4A.d.cts +24 -0
- package/dist/node-DV0niL4A.d.ts +24 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GuXianWN
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# tsx-sql
|
|
2
|
+
|
|
3
|
+
Compile TSX SQL fragments into parameterized SQL.
|
|
4
|
+
|
|
5
|
+
`tsx-sql` is a small SQL generation library. It lets you write dynamic SQL with TSX tags, then compile it into SQL text and parameter values.
|
|
6
|
+
|
|
7
|
+
It does not execute SQL, manage database connections, model schemas, or replace your ORM. Use the generated SQL with your database client or ORM of choice.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install tsx-sql
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## TypeScript Setup
|
|
16
|
+
|
|
17
|
+
Configure TypeScript to use the `tsx-sql` JSX runtime:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"compilerOptions": {
|
|
22
|
+
"jsx": "react-jsx",
|
|
23
|
+
"jsxImportSource": "tsx-sql"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Use `.tsx` files for SQL fragments written with JSX syntax.
|
|
29
|
+
|
|
30
|
+
## Basic Usage
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { $, compile, If, Where } from "tsx-sql";
|
|
34
|
+
|
|
35
|
+
const name: string | undefined = "Tom";
|
|
36
|
+
const age: number | undefined = undefined;
|
|
37
|
+
|
|
38
|
+
const query = compile(
|
|
39
|
+
<>
|
|
40
|
+
SELECT * FROM users
|
|
41
|
+
<Where>
|
|
42
|
+
<If test={name !== undefined}> AND name = { $(name) }</If>
|
|
43
|
+
<If test={age !== undefined}> AND age = { $(age) }</If>
|
|
44
|
+
</Where>
|
|
45
|
+
</>
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
console.log(query);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Output:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
{
|
|
55
|
+
sql: "SELECT * FROM users WHERE name = ?",
|
|
56
|
+
values: ["Tom"],
|
|
57
|
+
text: "SELECT * FROM users WHERE name = 'Tom'"
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Dynamic Conditions
|
|
62
|
+
|
|
63
|
+
Use `If` to include SQL only when a condition is true.
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { $, compile, If } from "tsx-sql";
|
|
67
|
+
|
|
68
|
+
const name: string | undefined = "Tom";
|
|
69
|
+
|
|
70
|
+
const query = compile(
|
|
71
|
+
<>
|
|
72
|
+
SELECT * FROM users
|
|
73
|
+
<If test={name !== undefined}> WHERE name = { $(name) }</If>
|
|
74
|
+
</>
|
|
75
|
+
);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Where
|
|
79
|
+
|
|
80
|
+
`Where` follows the MyBatis-style behavior:
|
|
81
|
+
|
|
82
|
+
- emits `WHERE` only when its children produce SQL
|
|
83
|
+
- removes a leading `AND` or `OR`
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { $, compile, If, Where } from "tsx-sql";
|
|
87
|
+
|
|
88
|
+
const name: string | undefined = "Tom";
|
|
89
|
+
const age: number | undefined = undefined;
|
|
90
|
+
|
|
91
|
+
const query = compile(
|
|
92
|
+
<>
|
|
93
|
+
SELECT * FROM users
|
|
94
|
+
<Where>
|
|
95
|
+
<If test={name !== undefined}> AND name = { $(name) }</If>
|
|
96
|
+
<If test={age !== undefined}> AND age = { $(age) }</If>
|
|
97
|
+
</Where>
|
|
98
|
+
</>
|
|
99
|
+
);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Output:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
{
|
|
106
|
+
sql: "SELECT * FROM users WHERE name = ?",
|
|
107
|
+
values: ["Tom"],
|
|
108
|
+
text: "SELECT * FROM users WHERE name = 'Tom'"
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Execute With Your Database Library
|
|
113
|
+
|
|
114
|
+
`compile` returns a plain object:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
interface CompileResult {
|
|
118
|
+
sql: string;
|
|
119
|
+
values: unknown[];
|
|
120
|
+
text: string;
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Use `sql` and `values` with a mature database client that accepts `?` placeholders.
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
await connection.query(query.sql, query.values);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`text` is intended for debugging and logging. Do not use it as executable SQL.
|
|
131
|
+
|
|
132
|
+
## API
|
|
133
|
+
|
|
134
|
+
### `compile(node)`
|
|
135
|
+
|
|
136
|
+
Compiles a TSX SQL node into:
|
|
137
|
+
|
|
138
|
+
- `sql`: SQL with `?` placeholders
|
|
139
|
+
- `values`: parameter values in order
|
|
140
|
+
- `text`: debug SQL with escaped values
|
|
141
|
+
|
|
142
|
+
### `$(value)`
|
|
143
|
+
|
|
144
|
+
Marks a value as a SQL parameter. Raw `{value}` expressions are not treated as SQL parameters; wrap values with `$()`.
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
WHERE id = { $(id) }
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### `<If test={boolean}>`
|
|
151
|
+
|
|
152
|
+
Includes its children when `test` is true.
|
|
153
|
+
|
|
154
|
+
### `<Where>`
|
|
155
|
+
|
|
156
|
+
Adds `WHERE` when children are not empty, and removes a leading `AND` or `OR`.
|
|
157
|
+
|
|
158
|
+
## Scope
|
|
159
|
+
|
|
160
|
+
This project only generates SQL.
|
|
161
|
+
|
|
162
|
+
It intentionally does not provide:
|
|
163
|
+
|
|
164
|
+
- database drivers
|
|
165
|
+
- connection pooling
|
|
166
|
+
- query execution
|
|
167
|
+
- schema modeling
|
|
168
|
+
- migrations
|
|
169
|
+
- ORM behavior
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
$: () => $,
|
|
24
|
+
If: () => If,
|
|
25
|
+
Where: () => Where,
|
|
26
|
+
compile: () => compile
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
|
|
30
|
+
// src/internal/escape.ts
|
|
31
|
+
function escapeSqlTextValue(value) {
|
|
32
|
+
if (value === null || value === void 0) {
|
|
33
|
+
return "NULL";
|
|
34
|
+
}
|
|
35
|
+
if (typeof value === "number") {
|
|
36
|
+
return Number.isFinite(value) ? String(value) : "NULL";
|
|
37
|
+
}
|
|
38
|
+
if (typeof value === "bigint") {
|
|
39
|
+
return value.toString();
|
|
40
|
+
}
|
|
41
|
+
if (typeof value === "boolean") {
|
|
42
|
+
return value ? "TRUE" : "FALSE";
|
|
43
|
+
}
|
|
44
|
+
if (value instanceof Date) {
|
|
45
|
+
return quoteString(value.toISOString());
|
|
46
|
+
}
|
|
47
|
+
return quoteString(String(value));
|
|
48
|
+
}
|
|
49
|
+
function quoteString(value) {
|
|
50
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/node.ts
|
|
54
|
+
var FRAGMENT_SYMBOL = "tsx-sql.fragment";
|
|
55
|
+
var SqlFragment = Symbol.for(FRAGMENT_SYMBOL);
|
|
56
|
+
|
|
57
|
+
// src/internal/resolve.ts
|
|
58
|
+
function resolveNode(input) {
|
|
59
|
+
if (Array.isArray(input)) {
|
|
60
|
+
return input.flatMap(resolveNode);
|
|
61
|
+
}
|
|
62
|
+
if (typeof input === "string") {
|
|
63
|
+
return [input];
|
|
64
|
+
}
|
|
65
|
+
if (input.kind === "param") {
|
|
66
|
+
return [input];
|
|
67
|
+
}
|
|
68
|
+
if (input.kind === "element") {
|
|
69
|
+
if (input.type === SqlFragment) {
|
|
70
|
+
return resolveNode(input.children ?? "");
|
|
71
|
+
}
|
|
72
|
+
return resolveNode(input.type(componentProps(input)));
|
|
73
|
+
}
|
|
74
|
+
return assertNever(input);
|
|
75
|
+
}
|
|
76
|
+
function componentProps(element) {
|
|
77
|
+
return {
|
|
78
|
+
...element.props,
|
|
79
|
+
children: element.children
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function assertNever(value) {
|
|
83
|
+
throw new TypeError(`Unsupported SQL node: ${String(value)}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/compile.ts
|
|
87
|
+
function compile(input) {
|
|
88
|
+
const sqlParts = [];
|
|
89
|
+
const values = [];
|
|
90
|
+
const textParts = [];
|
|
91
|
+
for (const node of resolveNode(input)) {
|
|
92
|
+
if (typeof node === "string") {
|
|
93
|
+
sqlParts.push(node);
|
|
94
|
+
textParts.push(node);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
sqlParts.push("?");
|
|
98
|
+
values.push(node.value);
|
|
99
|
+
textParts.push(escapeSqlTextValue(node.value));
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
sql: compactWhitespace(sqlParts.join("")),
|
|
103
|
+
values,
|
|
104
|
+
text: textParts.join("")
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function compactWhitespace(source) {
|
|
108
|
+
return source.replace(/\s+/g, " ").trim();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/param.ts
|
|
112
|
+
function $(value) {
|
|
113
|
+
return {
|
|
114
|
+
kind: "param",
|
|
115
|
+
value
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/tags/if.ts
|
|
120
|
+
function If(props) {
|
|
121
|
+
return props.test ? props.children ?? "" : "";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/tags/where.ts
|
|
125
|
+
function Where(props) {
|
|
126
|
+
const children = removeLeadingAndOr(resolveNode(props.children ?? ""));
|
|
127
|
+
if (isBlank(children)) {
|
|
128
|
+
return "";
|
|
129
|
+
}
|
|
130
|
+
return [" WHERE ", children];
|
|
131
|
+
}
|
|
132
|
+
function removeLeadingAndOr(nodes) {
|
|
133
|
+
const firstConditionIndex = nodes.findIndex((node) => typeof node !== "string" || node.trim().length > 0);
|
|
134
|
+
if (firstConditionIndex === -1) {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
const firstCondition = nodes[firstConditionIndex];
|
|
138
|
+
if (typeof firstCondition !== "string") {
|
|
139
|
+
return nodes;
|
|
140
|
+
}
|
|
141
|
+
return [
|
|
142
|
+
...nodes.slice(0, firstConditionIndex),
|
|
143
|
+
removeLeadingAndOrText(firstCondition),
|
|
144
|
+
...nodes.slice(firstConditionIndex + 1)
|
|
145
|
+
];
|
|
146
|
+
}
|
|
147
|
+
function removeLeadingAndOrText(text) {
|
|
148
|
+
return text.replace(/^\s*(AND|OR)\b\s*/i, "");
|
|
149
|
+
}
|
|
150
|
+
function isBlank(nodes) {
|
|
151
|
+
return nodes.every((node) => typeof node === "string" && node.trim().length === 0);
|
|
152
|
+
}
|
|
153
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
154
|
+
0 && (module.exports = {
|
|
155
|
+
$,
|
|
156
|
+
If,
|
|
157
|
+
Where,
|
|
158
|
+
compile
|
|
159
|
+
});
|
|
160
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/internal/escape.ts","../src/node.ts","../src/internal/resolve.ts","../src/compile.ts","../src/param.ts","../src/tags/if.ts","../src/tags/where.ts"],"sourcesContent":["export { compile } from \"./compile\";\nexport { $ } from \"./param\";\nexport { If } from \"./tags/if\";\nexport { Where } from \"./tags/where\";\nexport type { CompileResult } from \"./compile\";\nexport type { IfProps } from \"./tags/if\";\nexport type { SqlParam } from \"./param\";\n","export function escapeSqlTextValue(value: unknown): string {\r\n if (value === null || value === undefined) {\r\n return \"NULL\";\r\n }\r\n\r\n if (typeof value === \"number\") {\r\n return Number.isFinite(value) ? String(value) : \"NULL\";\r\n }\r\n\r\n if (typeof value === \"bigint\") {\r\n return value.toString();\r\n }\r\n\r\n if (typeof value === \"boolean\") {\r\n return value ? \"TRUE\" : \"FALSE\";\r\n }\r\n\r\n if (value instanceof Date) {\r\n return quoteString(value.toISOString());\r\n }\r\n\r\n return quoteString(String(value));\r\n}\r\n\r\nfunction quoteString(value: string): string {\r\n return `'${value.replaceAll(\"'\", \"''\")}'`;\r\n}\r\n","import type { SqlParam } from \"./param\";\n\nconst FRAGMENT_SYMBOL = \"tsx-sql.fragment\";\n\n// SQL fragments are transparent wrappers for <>...</>.\nexport const SqlFragment = Symbol.for(FRAGMENT_SYMBOL);\n\r\n// Any piece of SQL content that compile(...) knows how to read.\n// You can write:\n// <>WHERE name = { $(\"Tom\") }</>\n// TSX stores those children as:\r\n// [\"WHERE name = \", SqlParam]\r\n// Nested tags are also SqlNode values, so children can contain more elements.\nexport type SqlNode = string | SqlParam | SqlElement | SqlNode[];\n\ntype SqlProps = Record<string, unknown>;\n\nexport type SqlComponentProps = SqlProps & { children?: SqlNode };\n\n// A function that can be used as a TSX SQL tag.\n// You can write:\n// <If test={name}>...</If>\n// The element stores the If function in its type field, and compile(...)\n// calls that function to decide which SqlNode should be compiled next.\nexport type SqlComponent = (props: SqlComponentProps) => SqlNode;\n\r\n// The object created by createNode(...) after TypeScript compiles TSX.\r\n// You can write:\r\n// <If test={name}>AND name = { $(\"Tom\") }</If>\r\n// Runtime stores:\r\n// { type: If, props: { test: name, children: [\"AND name = \", SqlParam] } }\r\n// Fragment elements use SqlFragment as their type and only wrap children.\r\nexport interface SqlElement {\n kind: \"element\";\n type: typeof SqlFragment | SqlComponent;\n props: SqlProps;\n children?: SqlNode;\n}\n\n// TypeScript calls this through jsx/jsxs/jsxDEV after compiling TSX.\n// We keep the node shape tiny: just the tag/component type and its props.\nexport function createNode(type: SqlElement[\"type\"], props: (SqlProps & { children?: SqlNode }) | null): SqlElement {\n const { children, ...restProps } = props ?? {};\n\n return {\n kind: \"element\",\n type,\n props: restProps,\n children\n };\n}\n","import { SqlFragment, type SqlComponentProps, type SqlElement, type SqlNode } from \"../node\";\nimport type { SqlParam } from \"tsx-sql\";\n\nexport type ResolvedSqlNode = string | SqlParam;\n\nexport function resolveNode(input: SqlNode): ResolvedSqlNode[] {\n if (Array.isArray(input)) {\n return input.flatMap(resolveNode);\n }\n\n if (typeof input === \"string\") {\n return [input];\n }\n\n if (input.kind === \"param\") {\n return [input];\n }\n\n if (input.kind === \"element\") {\n if (input.type === SqlFragment) {\n return resolveNode(input.children ?? \"\");\n }\n\n return resolveNode(input.type(componentProps(input)));\n }\n\n return assertNever(input);\n}\n\nfunction componentProps(element: SqlElement): SqlComponentProps {\n return {\n ...element.props,\n children: element.children\n };\n}\n\nfunction assertNever(value: never): never {\n throw new TypeError(`Unsupported SQL node: ${String(value)}`);\n}\n","import { escapeSqlTextValue } from \"./internal/escape\";\nimport { resolveNode } from \"./internal/resolve\";\nimport type { SqlNode } from \"./node\";\n\nexport interface CompileResult {\n sql: string;\n values: unknown[];\n text: string;\n}\n\nexport function compile(input: SqlNode): CompileResult {\n const sqlParts: string[] = [];\n const values: unknown[] = [];\n const textParts: string[] = [];\n\n for (const node of resolveNode(input)) {\n // Raw strings are SQL text, not parameters.\n if (typeof node === \"string\") {\n sqlParts.push(node);\n textParts.push(node);\n continue;\n }\n\n // Parameters become placeholders in executable SQL and values in order.\n sqlParts.push(\"?\");\n values.push(node.value);\n textParts.push(escapeSqlTextValue(node.value));\n }\n\n return {\n sql: compactWhitespace(sqlParts.join(\"\")),\n values,\n text: textParts.join(\"\")\n };\n}\n\nfunction compactWhitespace(source: string): string {\n return source.replace(/\\s+/g, \" \").trim();\n}\n","export interface SqlParam {\n kind: \"param\";\n value: unknown;\n}\n\nexport function $(value: unknown): SqlParam {\n return {\n kind: \"param\",\n value\n };\n}\n","import type { SqlComponentProps, SqlNode } from \"../node\";\n\nexport interface IfProps extends SqlComponentProps {\n test: boolean;\n}\n\r\nexport function If(props: IfProps): SqlNode {\r\n return props.test ? props.children ?? \"\" : \"\";\r\n}\r\n","import { resolveNode, type ResolvedSqlNode } from \"../internal/resolve\";\nimport type { SqlComponentProps, SqlNode } from \"../node\";\n\nexport function Where(props: SqlComponentProps): SqlNode {\n const children = removeLeadingAndOr(resolveNode(props.children ?? \"\"));\n\n if (isBlank(children)) {\n return \"\";\n }\n\n return [\" WHERE \", children];\n}\n\nfunction removeLeadingAndOr(nodes: ResolvedSqlNode[]): ResolvedSqlNode[] {\n // MyBatis where ignores leading whitespace, then removes a leading AND/OR.\n const firstConditionIndex = nodes.findIndex((node) => typeof node !== \"string\" || node.trim().length > 0);\n if (firstConditionIndex === -1) {\n return [];\n }\n\n const firstCondition = nodes[firstConditionIndex];\n if (typeof firstCondition !== \"string\") {\n return nodes;\n }\n\n return [\n ...nodes.slice(0, firstConditionIndex),\n removeLeadingAndOrText(firstCondition),\n ...nodes.slice(firstConditionIndex + 1)\n ];\n}\n\nfunction removeLeadingAndOrText(text: string): string {\n return text.replace(/^\\s*(AND|OR)\\b\\s*/i, \"\");\n}\n\nfunction isBlank(nodes: ResolvedSqlNode[]): boolean {\n return nodes.every((node) => typeof node === \"string\" && node.trim().length === 0);\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { S as SqlNode, a as SqlComponentProps } from './node-DV0niL4A.cjs';
|
|
2
|
+
export { $, b as SqlParam } from './node-DV0niL4A.cjs';
|
|
3
|
+
|
|
4
|
+
interface CompileResult {
|
|
5
|
+
sql: string;
|
|
6
|
+
values: unknown[];
|
|
7
|
+
text: string;
|
|
8
|
+
}
|
|
9
|
+
declare function compile(input: SqlNode): CompileResult;
|
|
10
|
+
|
|
11
|
+
interface IfProps extends SqlComponentProps {
|
|
12
|
+
test: boolean;
|
|
13
|
+
}
|
|
14
|
+
declare function If(props: IfProps): SqlNode;
|
|
15
|
+
|
|
16
|
+
declare function Where(props: SqlComponentProps): SqlNode;
|
|
17
|
+
|
|
18
|
+
export { type CompileResult, If, type IfProps, Where, compile };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { S as SqlNode, a as SqlComponentProps } from './node-DV0niL4A.js';
|
|
2
|
+
export { $, b as SqlParam } from './node-DV0niL4A.js';
|
|
3
|
+
|
|
4
|
+
interface CompileResult {
|
|
5
|
+
sql: string;
|
|
6
|
+
values: unknown[];
|
|
7
|
+
text: string;
|
|
8
|
+
}
|
|
9
|
+
declare function compile(input: SqlNode): CompileResult;
|
|
10
|
+
|
|
11
|
+
interface IfProps extends SqlComponentProps {
|
|
12
|
+
test: boolean;
|
|
13
|
+
}
|
|
14
|
+
declare function If(props: IfProps): SqlNode;
|
|
15
|
+
|
|
16
|
+
declare function Where(props: SqlComponentProps): SqlNode;
|
|
17
|
+
|
|
18
|
+
export { type CompileResult, If, type IfProps, Where, compile };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// src/internal/escape.ts
|
|
2
|
+
function escapeSqlTextValue(value) {
|
|
3
|
+
if (value === null || value === void 0) {
|
|
4
|
+
return "NULL";
|
|
5
|
+
}
|
|
6
|
+
if (typeof value === "number") {
|
|
7
|
+
return Number.isFinite(value) ? String(value) : "NULL";
|
|
8
|
+
}
|
|
9
|
+
if (typeof value === "bigint") {
|
|
10
|
+
return value.toString();
|
|
11
|
+
}
|
|
12
|
+
if (typeof value === "boolean") {
|
|
13
|
+
return value ? "TRUE" : "FALSE";
|
|
14
|
+
}
|
|
15
|
+
if (value instanceof Date) {
|
|
16
|
+
return quoteString(value.toISOString());
|
|
17
|
+
}
|
|
18
|
+
return quoteString(String(value));
|
|
19
|
+
}
|
|
20
|
+
function quoteString(value) {
|
|
21
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/node.ts
|
|
25
|
+
var FRAGMENT_SYMBOL = "tsx-sql.fragment";
|
|
26
|
+
var SqlFragment = Symbol.for(FRAGMENT_SYMBOL);
|
|
27
|
+
|
|
28
|
+
// src/internal/resolve.ts
|
|
29
|
+
function resolveNode(input) {
|
|
30
|
+
if (Array.isArray(input)) {
|
|
31
|
+
return input.flatMap(resolveNode);
|
|
32
|
+
}
|
|
33
|
+
if (typeof input === "string") {
|
|
34
|
+
return [input];
|
|
35
|
+
}
|
|
36
|
+
if (input.kind === "param") {
|
|
37
|
+
return [input];
|
|
38
|
+
}
|
|
39
|
+
if (input.kind === "element") {
|
|
40
|
+
if (input.type === SqlFragment) {
|
|
41
|
+
return resolveNode(input.children ?? "");
|
|
42
|
+
}
|
|
43
|
+
return resolveNode(input.type(componentProps(input)));
|
|
44
|
+
}
|
|
45
|
+
return assertNever(input);
|
|
46
|
+
}
|
|
47
|
+
function componentProps(element) {
|
|
48
|
+
return {
|
|
49
|
+
...element.props,
|
|
50
|
+
children: element.children
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function assertNever(value) {
|
|
54
|
+
throw new TypeError(`Unsupported SQL node: ${String(value)}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/compile.ts
|
|
58
|
+
function compile(input) {
|
|
59
|
+
const sqlParts = [];
|
|
60
|
+
const values = [];
|
|
61
|
+
const textParts = [];
|
|
62
|
+
for (const node of resolveNode(input)) {
|
|
63
|
+
if (typeof node === "string") {
|
|
64
|
+
sqlParts.push(node);
|
|
65
|
+
textParts.push(node);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
sqlParts.push("?");
|
|
69
|
+
values.push(node.value);
|
|
70
|
+
textParts.push(escapeSqlTextValue(node.value));
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
sql: compactWhitespace(sqlParts.join("")),
|
|
74
|
+
values,
|
|
75
|
+
text: textParts.join("")
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function compactWhitespace(source) {
|
|
79
|
+
return source.replace(/\s+/g, " ").trim();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/param.ts
|
|
83
|
+
function $(value) {
|
|
84
|
+
return {
|
|
85
|
+
kind: "param",
|
|
86
|
+
value
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/tags/if.ts
|
|
91
|
+
function If(props) {
|
|
92
|
+
return props.test ? props.children ?? "" : "";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/tags/where.ts
|
|
96
|
+
function Where(props) {
|
|
97
|
+
const children = removeLeadingAndOr(resolveNode(props.children ?? ""));
|
|
98
|
+
if (isBlank(children)) {
|
|
99
|
+
return "";
|
|
100
|
+
}
|
|
101
|
+
return [" WHERE ", children];
|
|
102
|
+
}
|
|
103
|
+
function removeLeadingAndOr(nodes) {
|
|
104
|
+
const firstConditionIndex = nodes.findIndex((node) => typeof node !== "string" || node.trim().length > 0);
|
|
105
|
+
if (firstConditionIndex === -1) {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
const firstCondition = nodes[firstConditionIndex];
|
|
109
|
+
if (typeof firstCondition !== "string") {
|
|
110
|
+
return nodes;
|
|
111
|
+
}
|
|
112
|
+
return [
|
|
113
|
+
...nodes.slice(0, firstConditionIndex),
|
|
114
|
+
removeLeadingAndOrText(firstCondition),
|
|
115
|
+
...nodes.slice(firstConditionIndex + 1)
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
function removeLeadingAndOrText(text) {
|
|
119
|
+
return text.replace(/^\s*(AND|OR)\b\s*/i, "");
|
|
120
|
+
}
|
|
121
|
+
function isBlank(nodes) {
|
|
122
|
+
return nodes.every((node) => typeof node === "string" && node.trim().length === 0);
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
$,
|
|
126
|
+
If,
|
|
127
|
+
Where,
|
|
128
|
+
compile
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/escape.ts","../src/node.ts","../src/internal/resolve.ts","../src/compile.ts","../src/param.ts","../src/tags/if.ts","../src/tags/where.ts"],"sourcesContent":["export function escapeSqlTextValue(value: unknown): string {\r\n if (value === null || value === undefined) {\r\n return \"NULL\";\r\n }\r\n\r\n if (typeof value === \"number\") {\r\n return Number.isFinite(value) ? String(value) : \"NULL\";\r\n }\r\n\r\n if (typeof value === \"bigint\") {\r\n return value.toString();\r\n }\r\n\r\n if (typeof value === \"boolean\") {\r\n return value ? \"TRUE\" : \"FALSE\";\r\n }\r\n\r\n if (value instanceof Date) {\r\n return quoteString(value.toISOString());\r\n }\r\n\r\n return quoteString(String(value));\r\n}\r\n\r\nfunction quoteString(value: string): string {\r\n return `'${value.replaceAll(\"'\", \"''\")}'`;\r\n}\r\n","import type { SqlParam } from \"./param\";\n\nconst FRAGMENT_SYMBOL = \"tsx-sql.fragment\";\n\n// SQL fragments are transparent wrappers for <>...</>.\nexport const SqlFragment = Symbol.for(FRAGMENT_SYMBOL);\n\r\n// Any piece of SQL content that compile(...) knows how to read.\n// You can write:\n// <>WHERE name = { $(\"Tom\") }</>\n// TSX stores those children as:\r\n// [\"WHERE name = \", SqlParam]\r\n// Nested tags are also SqlNode values, so children can contain more elements.\nexport type SqlNode = string | SqlParam | SqlElement | SqlNode[];\n\ntype SqlProps = Record<string, unknown>;\n\nexport type SqlComponentProps = SqlProps & { children?: SqlNode };\n\n// A function that can be used as a TSX SQL tag.\n// You can write:\n// <If test={name}>...</If>\n// The element stores the If function in its type field, and compile(...)\n// calls that function to decide which SqlNode should be compiled next.\nexport type SqlComponent = (props: SqlComponentProps) => SqlNode;\n\r\n// The object created by createNode(...) after TypeScript compiles TSX.\r\n// You can write:\r\n// <If test={name}>AND name = { $(\"Tom\") }</If>\r\n// Runtime stores:\r\n// { type: If, props: { test: name, children: [\"AND name = \", SqlParam] } }\r\n// Fragment elements use SqlFragment as their type and only wrap children.\r\nexport interface SqlElement {\n kind: \"element\";\n type: typeof SqlFragment | SqlComponent;\n props: SqlProps;\n children?: SqlNode;\n}\n\n// TypeScript calls this through jsx/jsxs/jsxDEV after compiling TSX.\n// We keep the node shape tiny: just the tag/component type and its props.\nexport function createNode(type: SqlElement[\"type\"], props: (SqlProps & { children?: SqlNode }) | null): SqlElement {\n const { children, ...restProps } = props ?? {};\n\n return {\n kind: \"element\",\n type,\n props: restProps,\n children\n };\n}\n","import { SqlFragment, type SqlComponentProps, type SqlElement, type SqlNode } from \"../node\";\nimport type { SqlParam } from \"tsx-sql\";\n\nexport type ResolvedSqlNode = string | SqlParam;\n\nexport function resolveNode(input: SqlNode): ResolvedSqlNode[] {\n if (Array.isArray(input)) {\n return input.flatMap(resolveNode);\n }\n\n if (typeof input === \"string\") {\n return [input];\n }\n\n if (input.kind === \"param\") {\n return [input];\n }\n\n if (input.kind === \"element\") {\n if (input.type === SqlFragment) {\n return resolveNode(input.children ?? \"\");\n }\n\n return resolveNode(input.type(componentProps(input)));\n }\n\n return assertNever(input);\n}\n\nfunction componentProps(element: SqlElement): SqlComponentProps {\n return {\n ...element.props,\n children: element.children\n };\n}\n\nfunction assertNever(value: never): never {\n throw new TypeError(`Unsupported SQL node: ${String(value)}`);\n}\n","import { escapeSqlTextValue } from \"./internal/escape\";\nimport { resolveNode } from \"./internal/resolve\";\nimport type { SqlNode } from \"./node\";\n\nexport interface CompileResult {\n sql: string;\n values: unknown[];\n text: string;\n}\n\nexport function compile(input: SqlNode): CompileResult {\n const sqlParts: string[] = [];\n const values: unknown[] = [];\n const textParts: string[] = [];\n\n for (const node of resolveNode(input)) {\n // Raw strings are SQL text, not parameters.\n if (typeof node === \"string\") {\n sqlParts.push(node);\n textParts.push(node);\n continue;\n }\n\n // Parameters become placeholders in executable SQL and values in order.\n sqlParts.push(\"?\");\n values.push(node.value);\n textParts.push(escapeSqlTextValue(node.value));\n }\n\n return {\n sql: compactWhitespace(sqlParts.join(\"\")),\n values,\n text: textParts.join(\"\")\n };\n}\n\nfunction compactWhitespace(source: string): string {\n return source.replace(/\\s+/g, \" \").trim();\n}\n","export interface SqlParam {\n kind: \"param\";\n value: unknown;\n}\n\nexport function $(value: unknown): SqlParam {\n return {\n kind: \"param\",\n value\n };\n}\n","import type { SqlComponentProps, SqlNode } from \"../node\";\n\nexport interface IfProps extends SqlComponentProps {\n test: boolean;\n}\n\r\nexport function If(props: IfProps): SqlNode {\r\n return props.test ? props.children ?? \"\" : \"\";\r\n}\r\n","import { resolveNode, type ResolvedSqlNode } from \"../internal/resolve\";\nimport type { SqlComponentProps, SqlNode } from \"../node\";\n\nexport function Where(props: SqlComponentProps): SqlNode {\n const children = removeLeadingAndOr(resolveNode(props.children ?? \"\"));\n\n if (isBlank(children)) {\n return \"\";\n }\n\n return [\" WHERE \", children];\n}\n\nfunction removeLeadingAndOr(nodes: ResolvedSqlNode[]): ResolvedSqlNode[] {\n // MyBatis where ignores leading whitespace, then removes a leading AND/OR.\n const firstConditionIndex = nodes.findIndex((node) => typeof node !== \"string\" || node.trim().length > 0);\n if (firstConditionIndex === -1) {\n return [];\n }\n\n const firstCondition = nodes[firstConditionIndex];\n if (typeof firstCondition !== \"string\") {\n return nodes;\n }\n\n return [\n ...nodes.slice(0, firstConditionIndex),\n removeLeadingAndOrText(firstCondition),\n ...nodes.slice(firstConditionIndex + 1)\n ];\n}\n\nfunction removeLeadingAndOrText(text: string): string {\n return text.replace(/^\\s*(AND|OR)\\b\\s*/i, \"\");\n}\n\nfunction isBlank(nodes: ResolvedSqlNode[]): boolean {\n return nodes.every((node) => typeof node === \"string\" && node.trim().length === 0);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/jsx-dev-runtime.ts
|
|
21
|
+
var jsx_dev_runtime_exports = {};
|
|
22
|
+
__export(jsx_dev_runtime_exports, {
|
|
23
|
+
Fragment: () => SqlFragment,
|
|
24
|
+
jsx: () => jsx,
|
|
25
|
+
jsxDEV: () => createNode,
|
|
26
|
+
jsxs: () => jsxs
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(jsx_dev_runtime_exports);
|
|
29
|
+
|
|
30
|
+
// src/node.ts
|
|
31
|
+
var FRAGMENT_SYMBOL = "tsx-sql.fragment";
|
|
32
|
+
var SqlFragment = Symbol.for(FRAGMENT_SYMBOL);
|
|
33
|
+
function createNode(type, props) {
|
|
34
|
+
const { children, ...restProps } = props ?? {};
|
|
35
|
+
return {
|
|
36
|
+
kind: "element",
|
|
37
|
+
type,
|
|
38
|
+
props: restProps,
|
|
39
|
+
children
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/jsx-runtime.ts
|
|
44
|
+
var jsx = createNode;
|
|
45
|
+
var jsxs = createNode;
|
|
46
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
47
|
+
0 && (module.exports = {
|
|
48
|
+
Fragment,
|
|
49
|
+
jsx,
|
|
50
|
+
jsxDEV,
|
|
51
|
+
jsxs
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=jsx-dev-runtime.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/jsx-dev-runtime.ts","../src/node.ts","../src/jsx-runtime.ts"],"sourcesContent":["export { Fragment, jsx, jsxs } from \"./jsx-runtime\";\nexport { createNode as jsxDEV } from \"./node\";\n","import type { SqlParam } from \"./param\";\n\nconst FRAGMENT_SYMBOL = \"tsx-sql.fragment\";\n\n// SQL fragments are transparent wrappers for <>...</>.\nexport const SqlFragment = Symbol.for(FRAGMENT_SYMBOL);\n\r\n// Any piece of SQL content that compile(...) knows how to read.\n// You can write:\n// <>WHERE name = { $(\"Tom\") }</>\n// TSX stores those children as:\r\n// [\"WHERE name = \", SqlParam]\r\n// Nested tags are also SqlNode values, so children can contain more elements.\nexport type SqlNode = string | SqlParam | SqlElement | SqlNode[];\n\ntype SqlProps = Record<string, unknown>;\n\nexport type SqlComponentProps = SqlProps & { children?: SqlNode };\n\n// A function that can be used as a TSX SQL tag.\n// You can write:\n// <If test={name}>...</If>\n// The element stores the If function in its type field, and compile(...)\n// calls that function to decide which SqlNode should be compiled next.\nexport type SqlComponent = (props: SqlComponentProps) => SqlNode;\n\r\n// The object created by createNode(...) after TypeScript compiles TSX.\r\n// You can write:\r\n// <If test={name}>AND name = { $(\"Tom\") }</If>\r\n// Runtime stores:\r\n// { type: If, props: { test: name, children: [\"AND name = \", SqlParam] } }\r\n// Fragment elements use SqlFragment as their type and only wrap children.\r\nexport interface SqlElement {\n kind: \"element\";\n type: typeof SqlFragment | SqlComponent;\n props: SqlProps;\n children?: SqlNode;\n}\n\n// TypeScript calls this through jsx/jsxs/jsxDEV after compiling TSX.\n// We keep the node shape tiny: just the tag/component type and its props.\nexport function createNode(type: SqlElement[\"type\"], props: (SqlProps & { children?: SqlNode }) | null): SqlElement {\n const { children, ...restProps } = props ?? {};\n\n return {\n kind: \"element\",\n type,\n props: restProps,\n children\n };\n}\n","import { createNode, SqlFragment } from \"./node\";\nimport type { SqlNode } from \"./node\";\n\ndeclare global {\n namespace JSX {\n type Element = SqlNode;\n\n interface ElementChildrenAttribute {\n children: {};\n }\n }\n}\n\nexport { SqlFragment as Fragment };\n\nexport const jsx = createNode;\nexport const jsxs = createNode;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,IAAM,kBAAkB;AAGjB,IAAM,cAAc,OAAO,IAAI,eAAe;AAoC9C,SAAS,WAAW,MAA0B,OAA+D;AAClH,QAAM,EAAE,UAAU,GAAG,UAAU,IAAI,SAAS,CAAC;AAE7C,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO;AAAA,IACP;AAAA,EACF;AACF;;;ACnCO,IAAM,MAAM;AACZ,IAAM,OAAO;","names":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/node.ts
|
|
2
|
+
var FRAGMENT_SYMBOL = "tsx-sql.fragment";
|
|
3
|
+
var SqlFragment = Symbol.for(FRAGMENT_SYMBOL);
|
|
4
|
+
function createNode(type, props) {
|
|
5
|
+
const { children, ...restProps } = props ?? {};
|
|
6
|
+
return {
|
|
7
|
+
kind: "element",
|
|
8
|
+
type,
|
|
9
|
+
props: restProps,
|
|
10
|
+
children
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/jsx-runtime.ts
|
|
15
|
+
var jsx = createNode;
|
|
16
|
+
var jsxs = createNode;
|
|
17
|
+
export {
|
|
18
|
+
SqlFragment as Fragment,
|
|
19
|
+
jsx,
|
|
20
|
+
createNode as jsxDEV,
|
|
21
|
+
jsxs
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=jsx-dev-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/node.ts","../src/jsx-runtime.ts"],"sourcesContent":["import type { SqlParam } from \"./param\";\n\nconst FRAGMENT_SYMBOL = \"tsx-sql.fragment\";\n\n// SQL fragments are transparent wrappers for <>...</>.\nexport const SqlFragment = Symbol.for(FRAGMENT_SYMBOL);\n\r\n// Any piece of SQL content that compile(...) knows how to read.\n// You can write:\n// <>WHERE name = { $(\"Tom\") }</>\n// TSX stores those children as:\r\n// [\"WHERE name = \", SqlParam]\r\n// Nested tags are also SqlNode values, so children can contain more elements.\nexport type SqlNode = string | SqlParam | SqlElement | SqlNode[];\n\ntype SqlProps = Record<string, unknown>;\n\nexport type SqlComponentProps = SqlProps & { children?: SqlNode };\n\n// A function that can be used as a TSX SQL tag.\n// You can write:\n// <If test={name}>...</If>\n// The element stores the If function in its type field, and compile(...)\n// calls that function to decide which SqlNode should be compiled next.\nexport type SqlComponent = (props: SqlComponentProps) => SqlNode;\n\r\n// The object created by createNode(...) after TypeScript compiles TSX.\r\n// You can write:\r\n// <If test={name}>AND name = { $(\"Tom\") }</If>\r\n// Runtime stores:\r\n// { type: If, props: { test: name, children: [\"AND name = \", SqlParam] } }\r\n// Fragment elements use SqlFragment as their type and only wrap children.\r\nexport interface SqlElement {\n kind: \"element\";\n type: typeof SqlFragment | SqlComponent;\n props: SqlProps;\n children?: SqlNode;\n}\n\n// TypeScript calls this through jsx/jsxs/jsxDEV after compiling TSX.\n// We keep the node shape tiny: just the tag/component type and its props.\nexport function createNode(type: SqlElement[\"type\"], props: (SqlProps & { children?: SqlNode }) | null): SqlElement {\n const { children, ...restProps } = props ?? {};\n\n return {\n kind: \"element\",\n type,\n props: restProps,\n children\n };\n}\n","import { createNode, SqlFragment } from \"./node\";\nimport type { SqlNode } from \"./node\";\n\ndeclare global {\n namespace JSX {\n type Element = SqlNode;\n\n interface ElementChildrenAttribute {\n children: {};\n }\n }\n}\n\nexport { SqlFragment as Fragment };\n\nexport const jsx = createNode;\nexport const jsxs = createNode;\n"],"mappings":";AAEA,IAAM,kBAAkB;AAGjB,IAAM,cAAc,OAAO,IAAI,eAAe;AAoC9C,SAAS,WAAW,MAA0B,OAA+D;AAClH,QAAM,EAAE,UAAU,GAAG,UAAU,IAAI,SAAS,CAAC;AAE7C,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO;AAAA,IACP;AAAA,EACF;AACF;;;ACnCO,IAAM,MAAM;AACZ,IAAM,OAAO;","names":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/jsx-runtime.ts
|
|
21
|
+
var jsx_runtime_exports = {};
|
|
22
|
+
__export(jsx_runtime_exports, {
|
|
23
|
+
Fragment: () => SqlFragment,
|
|
24
|
+
jsx: () => jsx,
|
|
25
|
+
jsxs: () => jsxs
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(jsx_runtime_exports);
|
|
28
|
+
|
|
29
|
+
// src/node.ts
|
|
30
|
+
var FRAGMENT_SYMBOL = "tsx-sql.fragment";
|
|
31
|
+
var SqlFragment = Symbol.for(FRAGMENT_SYMBOL);
|
|
32
|
+
function createNode(type, props) {
|
|
33
|
+
const { children, ...restProps } = props ?? {};
|
|
34
|
+
return {
|
|
35
|
+
kind: "element",
|
|
36
|
+
type,
|
|
37
|
+
props: restProps,
|
|
38
|
+
children
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// src/jsx-runtime.ts
|
|
43
|
+
var jsx = createNode;
|
|
44
|
+
var jsxs = createNode;
|
|
45
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
46
|
+
0 && (module.exports = {
|
|
47
|
+
Fragment,
|
|
48
|
+
jsx,
|
|
49
|
+
jsxs
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=jsx-runtime.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/jsx-runtime.ts","../src/node.ts"],"sourcesContent":["import { createNode, SqlFragment } from \"./node\";\nimport type { SqlNode } from \"./node\";\n\ndeclare global {\n namespace JSX {\n type Element = SqlNode;\n\n interface ElementChildrenAttribute {\n children: {};\n }\n }\n}\n\nexport { SqlFragment as Fragment };\n\nexport const jsx = createNode;\nexport const jsxs = createNode;\n","import type { SqlParam } from \"./param\";\n\nconst FRAGMENT_SYMBOL = \"tsx-sql.fragment\";\n\n// SQL fragments are transparent wrappers for <>...</>.\nexport const SqlFragment = Symbol.for(FRAGMENT_SYMBOL);\n\r\n// Any piece of SQL content that compile(...) knows how to read.\n// You can write:\n// <>WHERE name = { $(\"Tom\") }</>\n// TSX stores those children as:\r\n// [\"WHERE name = \", SqlParam]\r\n// Nested tags are also SqlNode values, so children can contain more elements.\nexport type SqlNode = string | SqlParam | SqlElement | SqlNode[];\n\ntype SqlProps = Record<string, unknown>;\n\nexport type SqlComponentProps = SqlProps & { children?: SqlNode };\n\n// A function that can be used as a TSX SQL tag.\n// You can write:\n// <If test={name}>...</If>\n// The element stores the If function in its type field, and compile(...)\n// calls that function to decide which SqlNode should be compiled next.\nexport type SqlComponent = (props: SqlComponentProps) => SqlNode;\n\r\n// The object created by createNode(...) after TypeScript compiles TSX.\r\n// You can write:\r\n// <If test={name}>AND name = { $(\"Tom\") }</If>\r\n// Runtime stores:\r\n// { type: If, props: { test: name, children: [\"AND name = \", SqlParam] } }\r\n// Fragment elements use SqlFragment as their type and only wrap children.\r\nexport interface SqlElement {\n kind: \"element\";\n type: typeof SqlFragment | SqlComponent;\n props: SqlProps;\n children?: SqlNode;\n}\n\n// TypeScript calls this through jsx/jsxs/jsxDEV after compiling TSX.\n// We keep the node shape tiny: just the tag/component type and its props.\nexport function createNode(type: SqlElement[\"type\"], props: (SqlProps & { children?: SqlNode }) | null): SqlElement {\n const { children, ...restProps } = props ?? {};\n\n return {\n kind: \"element\",\n type,\n props: restProps,\n children\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,IAAM,kBAAkB;AAGjB,IAAM,cAAc,OAAO,IAAI,eAAe;AAoC9C,SAAS,WAAW,MAA0B,OAA+D;AAClH,QAAM,EAAE,UAAU,GAAG,UAAU,IAAI,SAAS,CAAC;AAE7C,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO;AAAA,IACP;AAAA,EACF;AACF;;;ADnCO,IAAM,MAAM;AACZ,IAAM,OAAO;","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { S as SqlNode, c as createNode } from './node-DV0niL4A.cjs';
|
|
2
|
+
export { d as Fragment } from './node-DV0niL4A.cjs';
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
namespace JSX {
|
|
6
|
+
type Element = SqlNode;
|
|
7
|
+
interface ElementChildrenAttribute {
|
|
8
|
+
children: {};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
declare const jsx: typeof createNode;
|
|
14
|
+
declare const jsxs: typeof createNode;
|
|
15
|
+
|
|
16
|
+
export { jsx, jsxs };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { S as SqlNode, c as createNode } from './node-DV0niL4A.js';
|
|
2
|
+
export { d as Fragment } from './node-DV0niL4A.js';
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
namespace JSX {
|
|
6
|
+
type Element = SqlNode;
|
|
7
|
+
interface ElementChildrenAttribute {
|
|
8
|
+
children: {};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
declare const jsx: typeof createNode;
|
|
14
|
+
declare const jsxs: typeof createNode;
|
|
15
|
+
|
|
16
|
+
export { jsx, jsxs };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// src/node.ts
|
|
2
|
+
var FRAGMENT_SYMBOL = "tsx-sql.fragment";
|
|
3
|
+
var SqlFragment = Symbol.for(FRAGMENT_SYMBOL);
|
|
4
|
+
function createNode(type, props) {
|
|
5
|
+
const { children, ...restProps } = props ?? {};
|
|
6
|
+
return {
|
|
7
|
+
kind: "element",
|
|
8
|
+
type,
|
|
9
|
+
props: restProps,
|
|
10
|
+
children
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/jsx-runtime.ts
|
|
15
|
+
var jsx = createNode;
|
|
16
|
+
var jsxs = createNode;
|
|
17
|
+
export {
|
|
18
|
+
SqlFragment as Fragment,
|
|
19
|
+
jsx,
|
|
20
|
+
jsxs
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=jsx-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/node.ts","../src/jsx-runtime.ts"],"sourcesContent":["import type { SqlParam } from \"./param\";\n\nconst FRAGMENT_SYMBOL = \"tsx-sql.fragment\";\n\n// SQL fragments are transparent wrappers for <>...</>.\nexport const SqlFragment = Symbol.for(FRAGMENT_SYMBOL);\n\r\n// Any piece of SQL content that compile(...) knows how to read.\n// You can write:\n// <>WHERE name = { $(\"Tom\") }</>\n// TSX stores those children as:\r\n// [\"WHERE name = \", SqlParam]\r\n// Nested tags are also SqlNode values, so children can contain more elements.\nexport type SqlNode = string | SqlParam | SqlElement | SqlNode[];\n\ntype SqlProps = Record<string, unknown>;\n\nexport type SqlComponentProps = SqlProps & { children?: SqlNode };\n\n// A function that can be used as a TSX SQL tag.\n// You can write:\n// <If test={name}>...</If>\n// The element stores the If function in its type field, and compile(...)\n// calls that function to decide which SqlNode should be compiled next.\nexport type SqlComponent = (props: SqlComponentProps) => SqlNode;\n\r\n// The object created by createNode(...) after TypeScript compiles TSX.\r\n// You can write:\r\n// <If test={name}>AND name = { $(\"Tom\") }</If>\r\n// Runtime stores:\r\n// { type: If, props: { test: name, children: [\"AND name = \", SqlParam] } }\r\n// Fragment elements use SqlFragment as their type and only wrap children.\r\nexport interface SqlElement {\n kind: \"element\";\n type: typeof SqlFragment | SqlComponent;\n props: SqlProps;\n children?: SqlNode;\n}\n\n// TypeScript calls this through jsx/jsxs/jsxDEV after compiling TSX.\n// We keep the node shape tiny: just the tag/component type and its props.\nexport function createNode(type: SqlElement[\"type\"], props: (SqlProps & { children?: SqlNode }) | null): SqlElement {\n const { children, ...restProps } = props ?? {};\n\n return {\n kind: \"element\",\n type,\n props: restProps,\n children\n };\n}\n","import { createNode, SqlFragment } from \"./node\";\nimport type { SqlNode } from \"./node\";\n\ndeclare global {\n namespace JSX {\n type Element = SqlNode;\n\n interface ElementChildrenAttribute {\n children: {};\n }\n }\n}\n\nexport { SqlFragment as Fragment };\n\nexport const jsx = createNode;\nexport const jsxs = createNode;\n"],"mappings":";AAEA,IAAM,kBAAkB;AAGjB,IAAM,cAAc,OAAO,IAAI,eAAe;AAoC9C,SAAS,WAAW,MAA0B,OAA+D;AAClH,QAAM,EAAE,UAAU,GAAG,UAAU,IAAI,SAAS,CAAC;AAE7C,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO;AAAA,IACP;AAAA,EACF;AACF;;;ACnCO,IAAM,MAAM;AACZ,IAAM,OAAO;","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
interface SqlParam {
|
|
2
|
+
kind: "param";
|
|
3
|
+
value: unknown;
|
|
4
|
+
}
|
|
5
|
+
declare function $(value: unknown): SqlParam;
|
|
6
|
+
|
|
7
|
+
declare const SqlFragment: unique symbol;
|
|
8
|
+
type SqlNode = string | SqlParam | SqlElement | SqlNode[];
|
|
9
|
+
type SqlProps = Record<string, unknown>;
|
|
10
|
+
type SqlComponentProps = SqlProps & {
|
|
11
|
+
children?: SqlNode;
|
|
12
|
+
};
|
|
13
|
+
type SqlComponent = (props: SqlComponentProps) => SqlNode;
|
|
14
|
+
interface SqlElement {
|
|
15
|
+
kind: "element";
|
|
16
|
+
type: typeof SqlFragment | SqlComponent;
|
|
17
|
+
props: SqlProps;
|
|
18
|
+
children?: SqlNode;
|
|
19
|
+
}
|
|
20
|
+
declare function createNode(type: SqlElement["type"], props: (SqlProps & {
|
|
21
|
+
children?: SqlNode;
|
|
22
|
+
}) | null): SqlElement;
|
|
23
|
+
|
|
24
|
+
export { $, type SqlNode as S, type SqlComponentProps as a, type SqlParam as b, createNode as c, SqlFragment as d };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
interface SqlParam {
|
|
2
|
+
kind: "param";
|
|
3
|
+
value: unknown;
|
|
4
|
+
}
|
|
5
|
+
declare function $(value: unknown): SqlParam;
|
|
6
|
+
|
|
7
|
+
declare const SqlFragment: unique symbol;
|
|
8
|
+
type SqlNode = string | SqlParam | SqlElement | SqlNode[];
|
|
9
|
+
type SqlProps = Record<string, unknown>;
|
|
10
|
+
type SqlComponentProps = SqlProps & {
|
|
11
|
+
children?: SqlNode;
|
|
12
|
+
};
|
|
13
|
+
type SqlComponent = (props: SqlComponentProps) => SqlNode;
|
|
14
|
+
interface SqlElement {
|
|
15
|
+
kind: "element";
|
|
16
|
+
type: typeof SqlFragment | SqlComponent;
|
|
17
|
+
props: SqlProps;
|
|
18
|
+
children?: SqlNode;
|
|
19
|
+
}
|
|
20
|
+
declare function createNode(type: SqlElement["type"], props: (SqlProps & {
|
|
21
|
+
children?: SqlNode;
|
|
22
|
+
}) | null): SqlElement;
|
|
23
|
+
|
|
24
|
+
export { $, type SqlNode as S, type SqlComponentProps as a, type SqlParam as b, createNode as c, SqlFragment as d };
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tsx-sql",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Compile TSX SQL fragments into parameterized SQL.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"sql",
|
|
7
|
+
"tsx",
|
|
8
|
+
"jsx",
|
|
9
|
+
"typescript",
|
|
10
|
+
"mybatis",
|
|
11
|
+
"query-builder"
|
|
12
|
+
],
|
|
13
|
+
"author": "GuXianWN",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/GuXianWN/tsx-sql.git"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/GuXianWN/tsx-sql/issues"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/GuXianWN/tsx-sql#readme",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.cjs",
|
|
25
|
+
"module": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"packageManager": "pnpm@9.15.0",
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE"
|
|
33
|
+
],
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"import": "./dist/index.js",
|
|
38
|
+
"require": "./dist/index.cjs"
|
|
39
|
+
},
|
|
40
|
+
"./jsx-runtime": {
|
|
41
|
+
"types": "./dist/jsx-runtime.d.ts",
|
|
42
|
+
"import": "./dist/jsx-runtime.js",
|
|
43
|
+
"require": "./dist/jsx-runtime.cjs"
|
|
44
|
+
},
|
|
45
|
+
"./jsx-dev-runtime": {
|
|
46
|
+
"types": "./dist/jsx-dev-runtime.d.ts",
|
|
47
|
+
"import": "./dist/jsx-dev-runtime.js",
|
|
48
|
+
"require": "./dist/jsx-dev-runtime.cjs"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsup",
|
|
53
|
+
"prepublishOnly": "pnpm test && pnpm typecheck && pnpm build",
|
|
54
|
+
"test": "vitest run",
|
|
55
|
+
"typecheck": "tsc --noEmit"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"tsup": "^8.3.5",
|
|
59
|
+
"typescript": "^5.6.3",
|
|
60
|
+
"vitest": "^2.1.4"
|
|
61
|
+
}
|
|
62
|
+
}
|