batis-xml 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-APACHE +202 -0
- package/LICENSE-MIT +21 -0
- package/README.md +152 -0
- package/THIRD_PARTY_NOTICES +36 -0
- package/batis_xml_wasm.d.ts +37 -0
- package/batis_xml_wasm.js +325 -0
- package/batis_xml_wasm_bg.wasm +0 -0
- package/package.json +42 -0
- package/schema.d.ts +320 -0
package/LICENSE-APACHE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/LICENSE-MIT
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ESPINS <dlwlalsggg@gmail.com>
|
|
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,152 @@
|
|
|
1
|
+
# batis-xml
|
|
2
|
+
|
|
3
|
+
WebAssembly bindings for [`batis-xml`](https://github.com/espins-labs/batis-xml)
|
|
4
|
+
— a parser and dynamic-SQL flattener for MyBatis and iBatis mapper XML.
|
|
5
|
+
|
|
6
|
+
```js
|
|
7
|
+
const batisXml = require("batis-xml");
|
|
8
|
+
|
|
9
|
+
const bytes = fs.readFileSync("OrderMapper.xml"); // Buffer, NOT a decoded string
|
|
10
|
+
const result = JSON.parse(batisXml.parse(bytes)); // schema v1, see schema.d.ts
|
|
11
|
+
const dialect = batisXml.detect(bytes); // "mybatis" | "ibatis" | "unknown" -- cheap pre-check
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
TypeScript consumers: `schema.d.ts` ships in this package (generated from
|
|
15
|
+
`schema/batis-xml.v1.json`, drift-checked in CI) —
|
|
16
|
+
`import type { ParseResult } from "batis-xml/schema"`.
|
|
17
|
+
|
|
18
|
+
**Node.js target only — no browser/bundler build yet.** This package is
|
|
19
|
+
built with `wasm-pack --target nodejs` (CommonJS, loads the `.wasm` via
|
|
20
|
+
`fs.readFileSync` at require time). It will not work as-is in a browser
|
|
21
|
+
or with a bundler expecting `--target web`/`--target bundler` output
|
|
22
|
+
(`fetch`-based instantiation, ESM). That's a separate build target to
|
|
23
|
+
add later, not a difference in the Rust source.
|
|
24
|
+
|
|
25
|
+
## Four things that will bite you
|
|
26
|
+
|
|
27
|
+
**(a) Feed raw bytes — never a host-pre-decoded string.** Always pass the
|
|
28
|
+
file's original `Buffer`/`Uint8Array` to `parse`/`detect`, not a string
|
|
29
|
+
you already decoded (e.g. `fs.readFileSync(path, "utf-8")` then
|
|
30
|
+
re-encoded). `batis-xml` detects the encoding itself: a BOM sniff first
|
|
31
|
+
(UTF-16 LE/BE select directly; a UTF-8 BOM is stripped), then a UTF-8
|
|
32
|
+
attempt, then the XML declaration's own `encoding=` label
|
|
33
|
+
(BOM/declared-label-driven, covering every WHATWG encoding via
|
|
34
|
+
`encoding_rs` — Shift_JIS, GB18030, Big5, UTF-16, …), then an EUC-KR
|
|
35
|
+
heuristic for declaration-less legacy files; anything else decodes
|
|
36
|
+
lossily with a diagnostic. `result.encoding` reports which of these
|
|
37
|
+
actually won (see (b)). Feeding it bytes that already went through a host
|
|
38
|
+
UTF-8 decoder defeats all of that, since a genuinely non-UTF-8 file would
|
|
39
|
+
already have been mangled (replacement characters) before `batis-xml`
|
|
40
|
+
ever sees it. Read files as bytes and stay in bytes until you call in.
|
|
41
|
+
|
|
42
|
+
**(b) Spans are byte offsets into the UTF-8 text `batis-xml` itself
|
|
43
|
+
decoded — never JS string indices, and never the *original* file's raw
|
|
44
|
+
bytes for anything but a UTF-8 source.** Every `ByteSpan { start, end }`
|
|
45
|
+
in the JSON indexes into the UTF-8 bytes of the *decoded* text (see
|
|
46
|
+
`ByteSpan`'s own doc in `schema.d.ts`), while a JS string is indexed by
|
|
47
|
+
UTF-16 code units — these diverge the moment a multi-byte character
|
|
48
|
+
appears before the offset you care about. Worse, for anything decoded
|
|
49
|
+
from a non-UTF-8 encoding, the original file's raw bytes aren't even the
|
|
50
|
+
same *length* as the UTF-8 re-encoding the spans are offsets into — do
|
|
51
|
+
not slice the original `Buffer`/`Uint8Array` directly with these offsets.
|
|
52
|
+
`result.encoding` (the WHATWG name `TextDecoder` accepts directly) is
|
|
53
|
+
what makes this reproducible:
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
// bytes is the same Buffer/Uint8Array you fed to parse()
|
|
57
|
+
const decodedText = new TextDecoder(result.encoding).decode(bytes);
|
|
58
|
+
const utf8Bytes = new TextEncoder().encode(decodedText); // byte-identical to batis-xml's own internal String
|
|
59
|
+
const text = new TextDecoder("utf-8").decode(
|
|
60
|
+
utf8Bytes.subarray(span.start, span.end)
|
|
61
|
+
);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
If the input was plain UTF-8, `bytes` and `utf8Bytes` are already
|
|
65
|
+
byte-identical (decoding then re-encoding UTF-8 is a no-op), so slicing
|
|
66
|
+
`bytes` directly happens to work in that one case — but relying on that
|
|
67
|
+
silently breaks the moment a file turns out to be Shift_JIS/EUC-KR/
|
|
68
|
+
UTF-16/etc., which is exactly the failure mode `result.encoding` exists
|
|
69
|
+
to prevent. Always go through the `TextDecoder`/`TextEncoder` round trip
|
|
70
|
+
above regardless of what encoding you expect.
|
|
71
|
+
|
|
72
|
+
**(c) Build qualified names as `ns.id`, suffixed `@databaseId` when
|
|
73
|
+
present.** `Statement.database_id` is deliberately *not* folded into
|
|
74
|
+
`id` — that's the consumer's call. If you build a "qualified name" key
|
|
75
|
+
(e.g. `namespace.statementId`) and drop `database_id`, two dual-dialect
|
|
76
|
+
variants of the same statement (`databaseId="oracle"` / `"mysql"`)
|
|
77
|
+
collide onto one key. Recommended recipe:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
// Both mapper.namespace (Option<Spanned<String>> — a namespace-less iBatis
|
|
81
|
+
// sqlMap has none) and statement.id (Option<..>, absent + a
|
|
82
|
+
// MissingStatementId diagnostic when the tag is missing an id attribute)
|
|
83
|
+
// are nullable in the schema -- `statement.id` in particular is easy to
|
|
84
|
+
// miss, since template literals silently accept `undefined` (stringified
|
|
85
|
+
// as "undefined") instead of a type error, so `tsc --strict` alone won't
|
|
86
|
+
// catch skipping this guard.
|
|
87
|
+
if (statement.id == null) {
|
|
88
|
+
// No stable identifier for this statement at all -- MissingStatementId
|
|
89
|
+
// is already in result.diagnostics; skip it rather than fabricate a key.
|
|
90
|
+
} else {
|
|
91
|
+
const namespace = mapper.namespace?.value ?? "";
|
|
92
|
+
const qualifiedName = statement.database_id
|
|
93
|
+
? `${namespace}.${statement.id.value}@${statement.database_id.value}`
|
|
94
|
+
: `${namespace}.${statement.id.value}`;
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**(d) `<include>` expands *before* `<where>`/`<set>`/`<trim>` in MyBatis/
|
|
99
|
+
iBatis — this crate doesn't expand it at all.** `IncludeRef` gives you the
|
|
100
|
+
raw `refid` plus a best-effort `IncludeTarget`; substituting the
|
|
101
|
+
referenced `<sql>` fragment's text in is on you.
|
|
102
|
+
|
|
103
|
+
The marker's textual form is a **stable v1 contract**: it renders in the
|
|
104
|
+
flattened SQL as the literal, fixed-prefix comment token
|
|
105
|
+
`` /* batis:include(<raw>) */ ``, where `<raw>` is `IncludeRef.raw`
|
|
106
|
+
verbatim (any literal `*/` inside it is replaced with `*_/` so it can't
|
|
107
|
+
terminate the comment early) — the same whether the target is `Local`,
|
|
108
|
+
`Qualified` (rendered with its original dot, e.g. `otherNs.frag`), or
|
|
109
|
+
`Dynamic` (the unresolved `${...}` text rendered as-is). Since the prefix
|
|
110
|
+
is fixed, `sqlText.indexOf("/* batis:include(")` (or a global regex) finds
|
|
111
|
+
every token directly; match each one to its `Statement.includes`/
|
|
112
|
+
`SqlFragment.includes` entry by reconstructing the exact token string
|
|
113
|
+
from that entry's `raw` field:
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
for (const inc of statement.includes) {
|
|
117
|
+
const token = `/* batis:include(${inc.value.raw.replaceAll("*/", "*_/")}) */`;
|
|
118
|
+
sqlText = sqlText.replace(token, resolveFragmentText(inc.value)); // your own lookup
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
If the fragment you're substituting is itself multi-variant
|
|
123
|
+
(`sql.variants` on the fragment's own flattened output has more than one
|
|
124
|
+
entry), there's no single deterministic substitution — pick the
|
|
125
|
+
fragment's variant whose `conditions` match the same parameter state as
|
|
126
|
+
the *enclosing* statement's variant you're substituting into, not
|
|
127
|
+
`variants[0]` arbitrarily.
|
|
128
|
+
|
|
129
|
+
If you splice fragment text in *after* flattening (rather than before,
|
|
130
|
+
like the real engines do), redo the wrapper's own cleanup against that
|
|
131
|
+
substituted text: re-apply the leading-AND/OR strip or trailing-comma
|
|
132
|
+
strip when the include token was first/last inside the wrapper, and
|
|
133
|
+
treat a wrapper whose only content is an include token as conditional
|
|
134
|
+
(the fragment might expand to nothing). `result.diagnostics` carries
|
|
135
|
+
`include_at_wrapper_boundary` for every spot this applies to — each
|
|
136
|
+
diagnostic's `span` is the same original-XML span as the matching
|
|
137
|
+
`includes[]` entry's `span` (not a position in the flattened text) — see
|
|
138
|
+
the core crate's README ("Include expansion order") for the full
|
|
139
|
+
contract. As with any diagnostic, match on `code`
|
|
140
|
+
(`"include_at_wrapper_boundary"`), never on `message` text — messages
|
|
141
|
+
may be reworded between versions without that being a breaking change.
|
|
142
|
+
|
|
143
|
+
One more ordering guarantee worth relying on: `result.mapper.statements`
|
|
144
|
+
(and `fragments`/`result_maps`) preserve the source document's order.
|
|
145
|
+
|
|
146
|
+
## One more thing
|
|
147
|
+
|
|
148
|
+
`IncludeRef.raw` (the raw, unparsed `refid` text) is kept even when
|
|
149
|
+
`IncludeTarget` is `Dynamic` (a `${}`-driven refid `batis-xml` can't
|
|
150
|
+
resolve statically) — inspect it for a static prefix or pattern to
|
|
151
|
+
attempt your own best-effort match, rather than treating every dynamic
|
|
152
|
+
include as a dead end.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
This package's compiled WebAssembly binary statically links the Rust crate
|
|
2
|
+
`encoding_rs` (https://docs.rs/encoding_rs), used for encoding detection and
|
|
3
|
+
decoding. `encoding_rs` is itself dual-licensed under Apache-2.0 OR MIT (see
|
|
4
|
+
LICENSE-APACHE / LICENSE-MIT in this package), but it also embeds encoding
|
|
5
|
+
index/conversion data owned by WHATWG (Apple, Google, Mozilla, Microsoft)
|
|
6
|
+
that is licensed separately under BSD-3-Clause. That notice is reproduced
|
|
7
|
+
below, unmodified, per its own terms.
|
|
8
|
+
|
|
9
|
+
-------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
Copyright © WHATWG (Apple, Google, Mozilla, Microsoft).
|
|
12
|
+
|
|
13
|
+
Redistribution and use in source and binary forms, with or without
|
|
14
|
+
modification, are permitted provided that the following conditions are met:
|
|
15
|
+
|
|
16
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
17
|
+
list of conditions and the following disclaimer.
|
|
18
|
+
|
|
19
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
20
|
+
this list of conditions and the following disclaimer in the documentation
|
|
21
|
+
and/or other materials provided with the distribution.
|
|
22
|
+
|
|
23
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
24
|
+
contributors may be used to endorse or promote products derived from
|
|
25
|
+
this software without specific prior written permission.
|
|
26
|
+
|
|
27
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
28
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
29
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
30
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
31
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
32
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
33
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
34
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
35
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
36
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Cheap dialect pre-check (MM-01 logic only, no statement/fragment/
|
|
6
|
+
* resultMap capture or flattening) -- returns the plain string
|
|
7
|
+
* (`"mybatis"` / `"ibatis"` / `"unknown"`, matching the schema's enum
|
|
8
|
+
* spelling), not a JSON-quoted one: unlike `parse`, this returns a single
|
|
9
|
+
* scalar with no nested model to keep schema-faithful, so there's no
|
|
10
|
+
* reason to make callers `JSON.parse` it. Guaranteed to agree with
|
|
11
|
+
* `parse(bytes)`'s `dialect` field (see the core crate's contract test).
|
|
12
|
+
* Same `Uint8Array`/`Buffer` input validation as `parse` (A16).
|
|
13
|
+
*
|
|
14
|
+
* B32 (cold code review, minor): typed as the `Dialect` union
|
|
15
|
+
* (`unchecked_return_type`) rather than the generic `string` wasm-bindgen
|
|
16
|
+
* would otherwise infer from `Result<String, _>` -- callers get real
|
|
17
|
+
* autocomplete/type-narrowing on the three actual values instead of an
|
|
18
|
+
* unconstrained string.
|
|
19
|
+
*/
|
|
20
|
+
export function detect(input: Uint8Array): "mybatis" | "ibatis" | "unknown";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Parses mapper XML bytes and returns the `ParseResult` (schema v1) as a
|
|
24
|
+
* JSON string. Never panics: encoding/parse failures already surface as
|
|
25
|
+
* diagnostics inside the JSON per the core crate's contract, and the
|
|
26
|
+
* (practically unreachable, since `ParseResult` has no non-string map
|
|
27
|
+
* keys) serialization failure case falls back to the JSON literal `null`
|
|
28
|
+
* rather than trapping the wasm instance. Throws a `TypeError` (rejecting
|
|
29
|
+
* the call, not silently coercing) if `input` isn't a `Uint8Array`/`Buffer`
|
|
30
|
+
* -- see [`require_bytes`].
|
|
31
|
+
*/
|
|
32
|
+
export function parse(input: Uint8Array): string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* This crate's version, from `Cargo.toml`.
|
|
36
|
+
*/
|
|
37
|
+
export function version(): string;
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/* @ts-self-types="./batis_xml_wasm.d.ts" */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cheap dialect pre-check (MM-01 logic only, no statement/fragment/
|
|
5
|
+
* resultMap capture or flattening) -- returns the plain string
|
|
6
|
+
* (`"mybatis"` / `"ibatis"` / `"unknown"`, matching the schema's enum
|
|
7
|
+
* spelling), not a JSON-quoted one: unlike `parse`, this returns a single
|
|
8
|
+
* scalar with no nested model to keep schema-faithful, so there's no
|
|
9
|
+
* reason to make callers `JSON.parse` it. Guaranteed to agree with
|
|
10
|
+
* `parse(bytes)`'s `dialect` field (see the core crate's contract test).
|
|
11
|
+
* Same `Uint8Array`/`Buffer` input validation as `parse` (A16).
|
|
12
|
+
*
|
|
13
|
+
* B32 (cold code review, minor): typed as the `Dialect` union
|
|
14
|
+
* (`unchecked_return_type`) rather than the generic `string` wasm-bindgen
|
|
15
|
+
* would otherwise infer from `Result<String, _>` -- callers get real
|
|
16
|
+
* autocomplete/type-narrowing on the three actual values instead of an
|
|
17
|
+
* unconstrained string.
|
|
18
|
+
* @param {Uint8Array} input
|
|
19
|
+
* @returns {"mybatis" | "ibatis" | "unknown"}
|
|
20
|
+
*/
|
|
21
|
+
function detect(input) {
|
|
22
|
+
let deferred2_0;
|
|
23
|
+
let deferred2_1;
|
|
24
|
+
try {
|
|
25
|
+
const ret = wasm.detect(input);
|
|
26
|
+
var ptr1 = ret[0];
|
|
27
|
+
var len1 = ret[1];
|
|
28
|
+
if (ret[3]) {
|
|
29
|
+
ptr1 = 0; len1 = 0;
|
|
30
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
31
|
+
}
|
|
32
|
+
deferred2_0 = ptr1;
|
|
33
|
+
deferred2_1 = len1;
|
|
34
|
+
return getStringFromWasm0(ptr1, len1);
|
|
35
|
+
} finally {
|
|
36
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.detect = detect;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Parses mapper XML bytes and returns the `ParseResult` (schema v1) as a
|
|
43
|
+
* JSON string. Never panics: encoding/parse failures already surface as
|
|
44
|
+
* diagnostics inside the JSON per the core crate's contract, and the
|
|
45
|
+
* (practically unreachable, since `ParseResult` has no non-string map
|
|
46
|
+
* keys) serialization failure case falls back to the JSON literal `null`
|
|
47
|
+
* rather than trapping the wasm instance. Throws a `TypeError` (rejecting
|
|
48
|
+
* the call, not silently coercing) if `input` isn't a `Uint8Array`/`Buffer`
|
|
49
|
+
* -- see [`require_bytes`].
|
|
50
|
+
* @param {Uint8Array} input
|
|
51
|
+
* @returns {string}
|
|
52
|
+
*/
|
|
53
|
+
function parse(input) {
|
|
54
|
+
let deferred2_0;
|
|
55
|
+
let deferred2_1;
|
|
56
|
+
try {
|
|
57
|
+
const ret = wasm.parse(input);
|
|
58
|
+
var ptr1 = ret[0];
|
|
59
|
+
var len1 = ret[1];
|
|
60
|
+
if (ret[3]) {
|
|
61
|
+
ptr1 = 0; len1 = 0;
|
|
62
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
63
|
+
}
|
|
64
|
+
deferred2_0 = ptr1;
|
|
65
|
+
deferred2_1 = len1;
|
|
66
|
+
return getStringFromWasm0(ptr1, len1);
|
|
67
|
+
} finally {
|
|
68
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.parse = parse;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* This crate's version, from `Cargo.toml`.
|
|
75
|
+
* @returns {string}
|
|
76
|
+
*/
|
|
77
|
+
function version() {
|
|
78
|
+
let deferred1_0;
|
|
79
|
+
let deferred1_1;
|
|
80
|
+
try {
|
|
81
|
+
const ret = wasm.version();
|
|
82
|
+
deferred1_0 = ret[0];
|
|
83
|
+
deferred1_1 = ret[1];
|
|
84
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
85
|
+
} finally {
|
|
86
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.version = version;
|
|
90
|
+
function __wbg_get_imports() {
|
|
91
|
+
const import0 = {
|
|
92
|
+
__proto__: null,
|
|
93
|
+
__wbg___wbindgen_boolean_get_fa956cfa2d1bd751: function(arg0) {
|
|
94
|
+
const v = arg0;
|
|
95
|
+
const ret = typeof(v) === 'boolean' ? v : undefined;
|
|
96
|
+
return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
|
|
97
|
+
},
|
|
98
|
+
__wbg___wbindgen_is_null_ea9085d691f535d3: function(arg0) {
|
|
99
|
+
const ret = arg0 === null;
|
|
100
|
+
return ret;
|
|
101
|
+
},
|
|
102
|
+
__wbg___wbindgen_is_object_a27215656b807791: function(arg0) {
|
|
103
|
+
const val = arg0;
|
|
104
|
+
const ret = typeof(val) === 'object' && val !== null;
|
|
105
|
+
return ret;
|
|
106
|
+
},
|
|
107
|
+
__wbg___wbindgen_is_undefined_c05833b95a3cf397: function(arg0) {
|
|
108
|
+
const ret = arg0 === undefined;
|
|
109
|
+
return ret;
|
|
110
|
+
},
|
|
111
|
+
__wbg___wbindgen_number_get_394265ed1e1b84ee: function(arg0, arg1) {
|
|
112
|
+
const obj = arg1;
|
|
113
|
+
const ret = typeof(obj) === 'number' ? obj : undefined;
|
|
114
|
+
getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
|
|
115
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
|
|
116
|
+
},
|
|
117
|
+
__wbg___wbindgen_string_get_b0ca35b86a603356: function(arg0, arg1) {
|
|
118
|
+
const obj = arg1;
|
|
119
|
+
const ret = typeof(obj) === 'string' ? obj : undefined;
|
|
120
|
+
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
121
|
+
var len1 = WASM_VECTOR_LEN;
|
|
122
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
123
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
124
|
+
},
|
|
125
|
+
__wbg___wbindgen_throw_344f42d3211c4765: function(arg0, arg1) {
|
|
126
|
+
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
127
|
+
},
|
|
128
|
+
__wbg_byteLength_41862ca4020b9c43: function(arg0) {
|
|
129
|
+
const ret = arg0.byteLength;
|
|
130
|
+
return ret;
|
|
131
|
+
},
|
|
132
|
+
__wbg_construct_4e1a16de27aea5b9: function() { return handleError(function (arg0, arg1) {
|
|
133
|
+
const ret = Reflect.construct(arg0, arg1);
|
|
134
|
+
return ret;
|
|
135
|
+
}, arguments); },
|
|
136
|
+
__wbg_get_78f252d074a84d0b: function() { return handleError(function (arg0, arg1) {
|
|
137
|
+
const ret = Reflect.get(arg0, arg1);
|
|
138
|
+
return ret;
|
|
139
|
+
}, arguments); },
|
|
140
|
+
__wbg_instanceof_Array_de0fa65266a8c7c0: function(arg0) {
|
|
141
|
+
let result;
|
|
142
|
+
try {
|
|
143
|
+
result = arg0 instanceof Array;
|
|
144
|
+
} catch (_) {
|
|
145
|
+
result = false;
|
|
146
|
+
}
|
|
147
|
+
const ret = result;
|
|
148
|
+
return ret;
|
|
149
|
+
},
|
|
150
|
+
__wbg_instanceof_Uint8Array_309b927aaf7a3fc7: function(arg0) {
|
|
151
|
+
let result;
|
|
152
|
+
try {
|
|
153
|
+
result = arg0 instanceof Uint8Array;
|
|
154
|
+
} catch (_) {
|
|
155
|
+
result = false;
|
|
156
|
+
}
|
|
157
|
+
const ret = result;
|
|
158
|
+
return ret;
|
|
159
|
+
},
|
|
160
|
+
__wbg_length_1f0964f4a5e2c6d8: function(arg0) {
|
|
161
|
+
const ret = arg0.length;
|
|
162
|
+
return ret;
|
|
163
|
+
},
|
|
164
|
+
__wbg_new_5e245ef5857d7f33: function(arg0, arg1) {
|
|
165
|
+
const ret = new TypeError(getStringFromWasm0(arg0, arg1));
|
|
166
|
+
return ret;
|
|
167
|
+
},
|
|
168
|
+
__wbg_of_85f52f8b6491a7ca: function(arg0) {
|
|
169
|
+
const ret = Array.of(arg0);
|
|
170
|
+
return ret;
|
|
171
|
+
},
|
|
172
|
+
__wbg_prototypesetcall_4770620bbe4688a0: function(arg0, arg1, arg2) {
|
|
173
|
+
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
|
|
174
|
+
},
|
|
175
|
+
__wbg_static_accessor_GLOBAL_4ef717fb391d88b7: function() {
|
|
176
|
+
const ret = typeof global === 'undefined' ? null : global;
|
|
177
|
+
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
|
178
|
+
},
|
|
179
|
+
__wbg_static_accessor_GLOBAL_THIS_8d1badc68b5a74f4: function() {
|
|
180
|
+
const ret = typeof globalThis === 'undefined' ? null : globalThis;
|
|
181
|
+
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
|
182
|
+
},
|
|
183
|
+
__wbg_static_accessor_SELF_146583524fe1469b: function() {
|
|
184
|
+
const ret = typeof self === 'undefined' ? null : self;
|
|
185
|
+
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
|
186
|
+
},
|
|
187
|
+
__wbg_static_accessor_WINDOW_f2829a2234d7819e: function() {
|
|
188
|
+
const ret = typeof window === 'undefined' ? null : window;
|
|
189
|
+
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
|
190
|
+
},
|
|
191
|
+
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
|
192
|
+
// Cast intrinsic for `Ref(String) -> Externref`.
|
|
193
|
+
const ret = getStringFromWasm0(arg0, arg1);
|
|
194
|
+
return ret;
|
|
195
|
+
},
|
|
196
|
+
__wbindgen_init_externref_table: function() {
|
|
197
|
+
const table = wasm.__wbindgen_externrefs;
|
|
198
|
+
const offset = table.grow(4);
|
|
199
|
+
table.set(0, undefined);
|
|
200
|
+
table.set(offset + 0, undefined);
|
|
201
|
+
table.set(offset + 1, null);
|
|
202
|
+
table.set(offset + 2, true);
|
|
203
|
+
table.set(offset + 3, false);
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
return {
|
|
207
|
+
__proto__: null,
|
|
208
|
+
"./batis_xml_wasm_bg.js": import0,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function addToExternrefTable0(obj) {
|
|
213
|
+
const idx = wasm.__externref_table_alloc();
|
|
214
|
+
wasm.__wbindgen_externrefs.set(idx, obj);
|
|
215
|
+
return idx;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function getArrayU8FromWasm0(ptr, len) {
|
|
219
|
+
ptr = ptr >>> 0;
|
|
220
|
+
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
let cachedDataViewMemory0 = null;
|
|
224
|
+
function getDataViewMemory0() {
|
|
225
|
+
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
|
226
|
+
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
|
227
|
+
}
|
|
228
|
+
return cachedDataViewMemory0;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function getStringFromWasm0(ptr, len) {
|
|
232
|
+
return decodeText(ptr >>> 0, len);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let cachedUint8ArrayMemory0 = null;
|
|
236
|
+
function getUint8ArrayMemory0() {
|
|
237
|
+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
238
|
+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
|
239
|
+
}
|
|
240
|
+
return cachedUint8ArrayMemory0;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function handleError(f, args) {
|
|
244
|
+
try {
|
|
245
|
+
return f.apply(this, args);
|
|
246
|
+
} catch (e) {
|
|
247
|
+
const idx = addToExternrefTable0(e);
|
|
248
|
+
wasm.__wbindgen_exn_store(idx);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function isLikeNone(x) {
|
|
253
|
+
return x === undefined || x === null;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function passStringToWasm0(arg, malloc, realloc) {
|
|
257
|
+
if (realloc === undefined) {
|
|
258
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
259
|
+
const ptr = malloc(buf.length, 1) >>> 0;
|
|
260
|
+
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
261
|
+
WASM_VECTOR_LEN = buf.length;
|
|
262
|
+
return ptr;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
let len = arg.length;
|
|
266
|
+
let ptr = malloc(len, 1) >>> 0;
|
|
267
|
+
|
|
268
|
+
const mem = getUint8ArrayMemory0();
|
|
269
|
+
|
|
270
|
+
let offset = 0;
|
|
271
|
+
|
|
272
|
+
for (; offset < len; offset++) {
|
|
273
|
+
const code = arg.charCodeAt(offset);
|
|
274
|
+
if (code > 0x7F) break;
|
|
275
|
+
mem[ptr + offset] = code;
|
|
276
|
+
}
|
|
277
|
+
if (offset !== len) {
|
|
278
|
+
if (offset !== 0) {
|
|
279
|
+
arg = arg.slice(offset);
|
|
280
|
+
}
|
|
281
|
+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
|
282
|
+
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
|
283
|
+
const ret = cachedTextEncoder.encodeInto(arg, view);
|
|
284
|
+
|
|
285
|
+
offset += ret.written;
|
|
286
|
+
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
WASM_VECTOR_LEN = offset;
|
|
290
|
+
return ptr;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function takeFromExternrefTable0(idx) {
|
|
294
|
+
const value = wasm.__wbindgen_externrefs.get(idx);
|
|
295
|
+
wasm.__externref_table_dealloc(idx);
|
|
296
|
+
return value;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
300
|
+
cachedTextDecoder.decode();
|
|
301
|
+
function decodeText(ptr, len) {
|
|
302
|
+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const cachedTextEncoder = new TextEncoder();
|
|
306
|
+
|
|
307
|
+
if (!('encodeInto' in cachedTextEncoder)) {
|
|
308
|
+
cachedTextEncoder.encodeInto = function (arg, view) {
|
|
309
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
310
|
+
view.set(buf);
|
|
311
|
+
return {
|
|
312
|
+
read: arg.length,
|
|
313
|
+
written: buf.length
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
let WASM_VECTOR_LEN = 0;
|
|
319
|
+
|
|
320
|
+
const wasmPath = `${__dirname}/batis_xml_wasm_bg.wasm`;
|
|
321
|
+
const wasmBytes = require('fs').readFileSync(wasmPath);
|
|
322
|
+
const wasmModule = new WebAssembly.Module(wasmBytes);
|
|
323
|
+
let wasmInstance = new WebAssembly.Instance(wasmModule, __wbg_get_imports());
|
|
324
|
+
let wasm = wasmInstance.exports;
|
|
325
|
+
wasm.__wbindgen_start();
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "batis-xml",
|
|
3
|
+
"collaborators": [
|
|
4
|
+
"ESPINS <dlwlalsggg@gmail.com>"
|
|
5
|
+
],
|
|
6
|
+
"description": "WebAssembly bindings for batis-xml (MyBatis/iBatis mapper XML parser)",
|
|
7
|
+
"version": "0.1.0",
|
|
8
|
+
"license": "MIT OR Apache-2.0",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/espins-labs/batis-xml.git"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"batis_xml_wasm_bg.wasm",
|
|
15
|
+
"batis_xml_wasm.js",
|
|
16
|
+
"batis_xml_wasm.d.ts",
|
|
17
|
+
"schema.d.ts",
|
|
18
|
+
"LICENSE-MIT",
|
|
19
|
+
"LICENSE-APACHE",
|
|
20
|
+
"THIRD_PARTY_NOTICES"
|
|
21
|
+
],
|
|
22
|
+
"main": "batis_xml_wasm.js",
|
|
23
|
+
"types": "batis_xml_wasm.d.ts",
|
|
24
|
+
"keywords": [
|
|
25
|
+
"mybatis",
|
|
26
|
+
"ibatis",
|
|
27
|
+
"wasm",
|
|
28
|
+
"parser"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./batis_xml_wasm.d.ts",
|
|
36
|
+
"default": "./batis_xml_wasm.js"
|
|
37
|
+
},
|
|
38
|
+
"./schema": {
|
|
39
|
+
"types": "./schema.d.ts"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
package/schema.d.ts
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* This file was automatically generated by json-schema-to-typescript.
|
|
4
|
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
5
|
+
* and run json-schema-to-typescript to regenerate this file.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Additions only; removal/renaming is breaking. `#[non_exhaustive]` because new codes may appear within v1 itself (see `schema/README.md`) -- an exhaustive `match` outside this crate must add a wildcard arm, which is exactly the forward-compat behavior consumers need (an unrecognized code is not an error). `Other` covers the equivalent case for *deserialization* (this build reading JSON produced by a newer version).
|
|
10
|
+
*
|
|
11
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
12
|
+
* via the `definition` "DiagCode".
|
|
13
|
+
*/
|
|
14
|
+
export type DiagCode =
|
|
15
|
+
| (
|
|
16
|
+
| "encoding_undetectable"
|
|
17
|
+
| "encoding_mismatch"
|
|
18
|
+
| "unclosed_tag"
|
|
19
|
+
| "duplicate_statement_id"
|
|
20
|
+
| "missing_statement_id"
|
|
21
|
+
| "branch_limit_exceeded"
|
|
22
|
+
| "unknown_element"
|
|
23
|
+
)
|
|
24
|
+
| "dangling_refid"
|
|
25
|
+
| "oversize_input"
|
|
26
|
+
| "duplicate_attribute"
|
|
27
|
+
| "invalid_entity"
|
|
28
|
+
| "unterminated_placeholder"
|
|
29
|
+
| "nesting_limit_exceeded"
|
|
30
|
+
| "include_at_wrapper_boundary"
|
|
31
|
+
| "other";
|
|
32
|
+
/**
|
|
33
|
+
* Closed set: an exhaustive `match` is a consumer feature (there's no forward-compat concern the way there is for `DiagCode`/`SqlText`, since `Unknown` already covers "neither of the two known dialects"). Adding a third dialect would be a v2.
|
|
34
|
+
*
|
|
35
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
36
|
+
* via the `definition` "Dialect".
|
|
37
|
+
*/
|
|
38
|
+
export type Dialect = "mybatis" | "ibatis" | "unknown";
|
|
39
|
+
/**
|
|
40
|
+
* Closed set: an exhaustive `match` is a consumer feature. `Dynamic` already covers "can't be resolved statically" -- there's no third kind of refid target. Adding a variant here would be a v2.
|
|
41
|
+
*
|
|
42
|
+
* ## Expansion-order contract
|
|
43
|
+
*
|
|
44
|
+
* This crate never substitutes the referenced `<sql>` fragment's text in place of the `<include>` token -- resolving `IncludeTarget` to actual SQL and splicing it in is entirely the consumer's job. MyBatis/iBatis themselves expand `<include>` *before* evaluating `<where>`/`<set>`/ `<trim>` dynamic semantics, so a wrapper's leading-AND/OR strip or trailing-comma strip sees the fragment's real, substituted text. Flattening here with the token still in place means a consumer substituting fragment text in afterward must, at minimum:
|
|
45
|
+
*
|
|
46
|
+
* - re-apply the wrapper's leading-AND/OR / trailing-comma cleanup to the substituted text when the include token was first/last inside a `<where>`/`<set>`/`<trim>`, and - treat a wrapper whose only content is an include token as conditional (the fragment may expand to nothing).
|
|
47
|
+
*
|
|
48
|
+
* `DiagCode::IncludeAtWrapperBoundary` flags exactly the spots this applies to -- see the README's "Include expansion order" section for the full write-up.
|
|
49
|
+
*
|
|
50
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
51
|
+
* via the `definition` "IncludeTarget".
|
|
52
|
+
*/
|
|
53
|
+
export type IncludeTarget =
|
|
54
|
+
| {
|
|
55
|
+
local: string;
|
|
56
|
+
}
|
|
57
|
+
| {
|
|
58
|
+
qualified: {
|
|
59
|
+
id: string;
|
|
60
|
+
ns: string;
|
|
61
|
+
[k: string]: unknown;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
| "dynamic";
|
|
65
|
+
/**
|
|
66
|
+
* Result of dynamic-tag flattening (MM-06). Branch combination cap N=32 — total candidates per statement, computed as the cartesian product of tag branches.
|
|
67
|
+
*
|
|
68
|
+
* `#[non_exhaustive]`: a third fallback representation is plausible future work, and consumers matching exhaustively today must not break at compile time if one's added.
|
|
69
|
+
*
|
|
70
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
71
|
+
* via the `definition` "SqlText".
|
|
72
|
+
*/
|
|
73
|
+
export type SqlText =
|
|
74
|
+
| {
|
|
75
|
+
variants: SqlVariant[];
|
|
76
|
+
}
|
|
77
|
+
| {
|
|
78
|
+
union: {
|
|
79
|
+
/**
|
|
80
|
+
* A **lower bound**, not necessarily the exact branch count: flattening bails out of cartesian expansion as soon as it's certain the total exceeds the cap, without finishing the (possibly much larger) exact count. Treat this as "at least this many, over the cap" rather than a precise total.
|
|
81
|
+
*/
|
|
82
|
+
branch_count: number;
|
|
83
|
+
text: SqlString;
|
|
84
|
+
[k: string]: unknown;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Closed set: an exhaustive `match` is a consumer feature. `Generic` already covers "some other statement-like tag with no CRUD-verb equivalent" -- a new MyBatis/iBatis statement-like tag would be recognized by adding to `Generic`'s callers, not by growing this enum. Adding a variant here would be a v2.
|
|
89
|
+
*
|
|
90
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
91
|
+
* via the `definition` "StatementKind".
|
|
92
|
+
*/
|
|
93
|
+
export type StatementKind = ("select" | "insert" | "update" | "delete" | "procedure") | "generic";
|
|
94
|
+
|
|
95
|
+
export interface ParseResult {
|
|
96
|
+
/**
|
|
97
|
+
* Parsing never fails — every anomaly accumulates here.
|
|
98
|
+
*/
|
|
99
|
+
diagnostics: Diagnostic[];
|
|
100
|
+
dialect: Dialect;
|
|
101
|
+
/**
|
|
102
|
+
* The WHATWG name of the encoding the detection chain actually decoded the input with (`"UTF-8"`, `"EUC-KR"`, `"Shift_JIS"`, `"UTF-16LE"`, ...; `encoding_rs::Encoding::name()`'s own values, which are WHATWG-standard labels). `None` only when no decode was attempted at all (the raw-byte oversize cap rejected the input before `encoding.rs` ever ran) -- `parse` (already-decoded `&str` input) always reports `"UTF-8"`, since that's the one encoding a Rust `&str` can ever be.
|
|
103
|
+
*
|
|
104
|
+
* This is what makes the [`ByteSpan`] re-encoding caveat actionable: every span in this result is a byte offset into the UTF-8 text *after* decoding, so a consumer working with the **original** input bytes must decode them the same way first -- `new TextDecoder(result.encoding)` (Node.js/browsers both accept WHATWG labels directly), re-encode that decoded text to UTF-8, and slice spans against *that* buffer, not the original input bytes directly (see `wasm/README.md` for a worked recipe).
|
|
105
|
+
*
|
|
106
|
+
* BOM handling: for a document that opened with a byte-order mark, the mark is consumed during decoding and never appears in the decoded text -- spans are relative to the BOM-stripped content, same as every other span in this crate (offsets into what this crate's own decoding produced, not the original file's raw byte layout). A consumer re-decoding the original file with `TextDecoder` gets BOM-stripping for free (that's standard `TextDecoder` behavior for UTF-8/UTF-16 with a matching BOM), so no extra adjustment is needed on the consumer's side either.
|
|
107
|
+
*/
|
|
108
|
+
encoding?: string | null;
|
|
109
|
+
/**
|
|
110
|
+
* `None` when the root element is not a mapper/sqlMap (reason is reported as a diagnostic).
|
|
111
|
+
*/
|
|
112
|
+
mapper?: Mapper | null;
|
|
113
|
+
[k: string]: unknown;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
117
|
+
* via the `definition` "Diagnostic".
|
|
118
|
+
*/
|
|
119
|
+
export interface Diagnostic {
|
|
120
|
+
code: DiagCode;
|
|
121
|
+
message: string;
|
|
122
|
+
span?: ByteSpan | null;
|
|
123
|
+
[k: string]: unknown;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Half-open range `[start, end)`: byte offsets into the UTF-8 text as decoded by this crate (identical to raw input bytes for UTF-8 sources; see the caveat below for re-encoded documents).
|
|
127
|
+
*
|
|
128
|
+
* Caveat: this holds exactly for UTF-8 input, which decoding leaves byte-for-byte unchanged. For documents decoded from any other encoding (EUC-KR, Shift_JIS, GB18030, UTF-16, ... -- see `encoding.rs`, which supports every WHATWG encoding via a BOM/declared-label-driven chain, not just EUC-KR), decoding to UTF-8 changes byte *widths* per character, so spans on such documents are offsets into the re-encoded UTF-8 string, not the original raw bytes. This applies uniformly to every re-encoded document, not just Korean legacy files. Consumers reading spans back against a source file must decode that source the same way this crate did before slicing.
|
|
129
|
+
*
|
|
130
|
+
* A leading byte-order mark is never part of this text either way: a BOM is consumed during decoding for [`crate::parse_bytes`] (see [`ParseResult::encoding`]'s doc comment) and stripped from the input string itself for [`crate::parse`] (a caller can hand it an already-decoded string that still carries a BOM, e.g. read from a file without stripping it first) -- both entry points agree that every span is relative to the BOM-stripped content.
|
|
131
|
+
*
|
|
132
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
133
|
+
* via the `definition` "ByteSpan".
|
|
134
|
+
*/
|
|
135
|
+
export interface ByteSpan {
|
|
136
|
+
end: number;
|
|
137
|
+
start: number;
|
|
138
|
+
[k: string]: unknown;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
142
|
+
* via the `definition` "Mapper".
|
|
143
|
+
*/
|
|
144
|
+
export interface Mapper {
|
|
145
|
+
fragments: SqlFragment[];
|
|
146
|
+
/**
|
|
147
|
+
* Usually `None` for iBatis sqlMaps (observed in the wild: the prefix lives inside the statement id itself, e.g. `WidgetDAO.getWidget`).
|
|
148
|
+
*/
|
|
149
|
+
namespace?: SpannedFor_String | null;
|
|
150
|
+
result_maps: ResultMap[];
|
|
151
|
+
statements: Statement[];
|
|
152
|
+
[k: string]: unknown;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
156
|
+
* via the `definition` "SqlFragment".
|
|
157
|
+
*/
|
|
158
|
+
export interface SqlFragment {
|
|
159
|
+
id: SpannedFor_String;
|
|
160
|
+
/**
|
|
161
|
+
* Nested includes inside the fragment (MM-04).
|
|
162
|
+
*/
|
|
163
|
+
includes: SpannedFor_IncludeRef[];
|
|
164
|
+
/**
|
|
165
|
+
* Full original extent: opening-tag start → subtree end.
|
|
166
|
+
*/
|
|
167
|
+
span: ByteSpan;
|
|
168
|
+
sql: SqlText;
|
|
169
|
+
[k: string]: unknown;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
173
|
+
* via the `definition` "Spanned_for_String".
|
|
174
|
+
*/
|
|
175
|
+
export interface SpannedFor_String {
|
|
176
|
+
span: ByteSpan;
|
|
177
|
+
value: string;
|
|
178
|
+
[k: string]: unknown;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
182
|
+
* via the `definition` "Spanned_for_IncludeRef".
|
|
183
|
+
*/
|
|
184
|
+
export interface SpannedFor_IncludeRef {
|
|
185
|
+
span: ByteSpan;
|
|
186
|
+
value: IncludeRef;
|
|
187
|
+
[k: string]: unknown;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The include-token textual contract -- a stable part of the v1 output.
|
|
191
|
+
*
|
|
192
|
+
* Every `<include refid="...">` marker renders into the flattened [`SqlText`] as a SQL block comment: an opening `/`+`*`, the literal text `batis:include(`, this struct's own `raw` field, a closing `)`, then the closing `*`+`/`. `raw` is rendered verbatim -- the unparsed `refid` attribute value -- **except** any literal `*` immediately followed by `/` inside it is rewritten to `*` + `_` + `/`, so the token can never terminate its own enclosing comment early (a `refid` is untrusted XML attribute content, not something this crate controls the shape of). This holds regardless of `target`'s classification: `Local("frag")` renders the comment around `frag` verbatim; `Qualified { ns: "otherNs", id: "frag" }` renders the *original, still-dotted* text `otherNs.frag` (`raw` is the whole unparsed attribute value; `ns`/`id` are just it split on the last dot for convenience, not a separate rendering); `Dynamic` renders the literal, unresolved `${...}` text as-is.
|
|
193
|
+
*
|
|
194
|
+
* **Locating tokens**: since the token's opening (`/`+`*` followed by the literal text `batis:include(`) is a fixed prefix, a plain substring search over the flattened SQL text finds every token directly -- no need to reconstruct it from `raw` first. Each token's position correlates 1:1 with one entry in the owning [`Statement::includes`]/[`SqlFragment::includes`] list: match by `Spanned::span`, which is the *original XML* span of the `<include>` element (not a position in the flattened text) -- the same span a [`DiagCode::IncludeAtWrapperBoundary`] diagnostic reports when this token sits at a `<where>`/`<set>`/`<trim>` boundary (see that variant's own doc comment, and the README's "Include expansion order" section, for the substitution contract itself).
|
|
195
|
+
*
|
|
196
|
+
* **Substituting a fragment with multiple variants**: a referenced `<sql>` fragment is itself flattened to a [`SqlText`], which may be `Variants` (several condition-gated alternatives) rather than one fixed string. There is no single deterministic substitution in that case -- the fragment's *own* active variant depends on the same runtime parameter state as the enclosing statement's variant does, so a consumer substituting fragment text into one variant of the parent statement must pick the matching variant of the fragment (by `conditions`), not an arbitrary one (e.g. `variants[0]`).
|
|
197
|
+
*
|
|
198
|
+
* **Document order**: [`Mapper::statements`] (and `fragments`/ `result_maps`) preserve source document order -- safe to assume when resolving forward/backward references across statements in one file.
|
|
199
|
+
*
|
|
200
|
+
* **Diagnostic messages are not a stable matching surface.** `message` strings may be reworded between versions without that being a breaking change; match on [`Diagnostic::code`] instead.
|
|
201
|
+
*
|
|
202
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
203
|
+
* via the `definition` "IncludeRef".
|
|
204
|
+
*/
|
|
205
|
+
export interface IncludeRef {
|
|
206
|
+
raw: string;
|
|
207
|
+
target: IncludeTarget;
|
|
208
|
+
[k: string]: unknown;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
212
|
+
* via the `definition` "SqlVariant".
|
|
213
|
+
*/
|
|
214
|
+
export interface SqlVariant {
|
|
215
|
+
/**
|
|
216
|
+
* The `test` expressions (verbatim) that activate this variant -- positive-only, and not a full boolean formula.
|
|
217
|
+
*
|
|
218
|
+
* Only the `test` conditions of `<if>`/dynamic tags whose branch is actually *taken* in this variant's path through the tag tree are recorded here, in document order. An `<if>`'s *not-taken* path contributes an alternative with `conditions: []` (empty) -- which is indistinguishable, at the type level, from a statement that had no `<if>` at all. This is by design (recording "this condition was false" would require inventing a negated-expression representation this crate doesn't have a use for elsewhere), but it means an empty `conditions` list is not itself proof that a variant is unconditional -- a consumer that needs that distinction has to correlate against the source XML's own dynamic-tag structure.
|
|
219
|
+
*
|
|
220
|
+
* `SqlText::Variants` as a whole lists *candidate* SQL shapes, not a runtime guarantee: this crate has no visibility into actual parameter values, so it cannot say which variant (if any single one) will execute for a given call -- only that these are the shapes the dynamic-tag tree can produce, gated by the conditions listed here.
|
|
221
|
+
*/
|
|
222
|
+
conditions: string[];
|
|
223
|
+
text: SqlString;
|
|
224
|
+
[k: string]: unknown;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Flattened SQL text plus a mapping back to the source.
|
|
228
|
+
*
|
|
229
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
230
|
+
* via the `definition` "SqlString".
|
|
231
|
+
*/
|
|
232
|
+
export interface SqlString {
|
|
233
|
+
/**
|
|
234
|
+
* (synthetic-text offset, original byte offset) segment-start pairs.
|
|
235
|
+
*
|
|
236
|
+
* Only the first column -- the synthetic-text offset (position in `text` above) -- is strictly increasing (B45, cold code review): each entry marks where a new mapped segment starts in the flattened output, so later entries always point further into `text` than earlier ones. The second column -- the original byte offset into the source document -- has no such guarantee, and legitimately repeats or goes backwards at synthetic tokens. Wrapper-added text (a `<trim>`/`<where>`/`<set>`/`<foreach>`'s `prefix`/`open`/`close`/`separator` etc.) has no original bytes of its own, so its span_map entry reuses the wrapper tag's own span start -- for *every* synthetic token the wrapper contributes, including a trailing `close`. E.g. `<foreach open="(" close=")">` around `#{id}` flattens to `"(?)"` with `span_map == [(0, wrapper_start), (1, <raw offset of #{id}>), (2, wrapper_start)]` -- the raw column rises across the body then drops back to `wrapper_start` for the closing `)`, which sits earlier in the source than the body it follows in `text`. Consumers must sort/dedupe on the first column only; the second is not monotonic and must not be assumed so.
|
|
237
|
+
*/
|
|
238
|
+
span_map: [number, number][];
|
|
239
|
+
/**
|
|
240
|
+
* Placeholders already normalized: `#{..}` → `?`, `${..}` → `__BATIS_DYN__`.
|
|
241
|
+
*/
|
|
242
|
+
text: string;
|
|
243
|
+
[k: string]: unknown;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
247
|
+
* via the `definition` "ResultMap".
|
|
248
|
+
*/
|
|
249
|
+
export interface ResultMap {
|
|
250
|
+
extends?: SpannedFor_String | null;
|
|
251
|
+
id: SpannedFor_String;
|
|
252
|
+
mappings: ColumnMapping[];
|
|
253
|
+
/**
|
|
254
|
+
* Full original extent: opening-tag start → subtree end.
|
|
255
|
+
*/
|
|
256
|
+
span: ByteSpan;
|
|
257
|
+
type_ref?: SpannedFor_ClassRef | null;
|
|
258
|
+
[k: string]: unknown;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
262
|
+
* via the `definition` "ColumnMapping".
|
|
263
|
+
*/
|
|
264
|
+
export interface ColumnMapping {
|
|
265
|
+
column?: string | null;
|
|
266
|
+
property?: string | null;
|
|
267
|
+
[k: string]: unknown;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
271
|
+
* via the `definition` "Spanned_for_ClassRef".
|
|
272
|
+
*/
|
|
273
|
+
export interface SpannedFor_ClassRef {
|
|
274
|
+
span: ByteSpan;
|
|
275
|
+
value: ClassRef;
|
|
276
|
+
[k: string]: unknown;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Alias resolution is the consumer's job — only the raw text is kept.
|
|
280
|
+
*
|
|
281
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
282
|
+
* via the `definition` "ClassRef".
|
|
283
|
+
*/
|
|
284
|
+
export interface ClassRef {
|
|
285
|
+
raw: string;
|
|
286
|
+
[k: string]: unknown;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* This interface was referenced by `ParseResult`'s JSON-Schema
|
|
290
|
+
* via the `definition` "Statement".
|
|
291
|
+
*/
|
|
292
|
+
export interface Statement {
|
|
293
|
+
/**
|
|
294
|
+
* MyBatis per-vendor branching (`databaseId="oracle"` etc.) — `None` when neither this statement nor (for a `<selectKey>`-synthesized statement) its parent declares one. Distinguishes otherwise duplicate ids (MM-03).
|
|
295
|
+
*
|
|
296
|
+
* Inheritance rule (A20/A22, cold code review): a `<selectKey>` child statement (synthesized as `"{parent_id}!selectKey"`, see `id`) reads its *own* `databaseId` attribute first; only when it has none does it inherit the parent statement's `databaseId`. An explicit `databaseId` on the `<selectKey>` itself always wins.
|
|
297
|
+
*
|
|
298
|
+
* When inherited, `span` points at the **parent's** `databaseId` attribute, not anywhere inside this child statement's own `span` -- the parent's attribute is textually outside the child's subtree (a `<selectKey>` never contains its enclosing statement's opening tag). This is the one case where a `Spanned` value's `span` is legitimately outside the `Statement` it's attached to; every other `Spanned`/`ByteSpan` field on `Statement` points within `span`.
|
|
299
|
+
*/
|
|
300
|
+
database_id?: SpannedFor_String | null;
|
|
301
|
+
/**
|
|
302
|
+
* `None` when missing, plus a `MissingStatementId` diagnostic. Synthesized ids are never invented.
|
|
303
|
+
*/
|
|
304
|
+
id?: SpannedFor_String | null;
|
|
305
|
+
includes: SpannedFor_IncludeRef[];
|
|
306
|
+
kind: StatementKind;
|
|
307
|
+
param_class?: SpannedFor_ClassRef | null;
|
|
308
|
+
/**
|
|
309
|
+
* Expression paths collected from `#{a.b}` / `${c}` (MM-07).
|
|
310
|
+
*/
|
|
311
|
+
property_paths: SpannedFor_String[];
|
|
312
|
+
result_class?: SpannedFor_ClassRef | null;
|
|
313
|
+
result_map_ref?: SpannedFor_String | null;
|
|
314
|
+
/**
|
|
315
|
+
* Full original extent of the statement: opening-tag start → subtree end (i.e. past its closing tag, or its own end for a self-closed element).
|
|
316
|
+
*/
|
|
317
|
+
span: ByteSpan;
|
|
318
|
+
sql: SqlText;
|
|
319
|
+
[k: string]: unknown;
|
|
320
|
+
}
|