tamedevil 0.0.0-0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/LICENSE.md +20 -0
- package/README.md +315 -0
- package/dist/index.d.ts +198 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +724 -0
- package/dist/index.js.map +1 -0
- package/dist/reservedWords.d.ts +2 -0
- package/dist/reservedWords.d.ts.map +1 -0
- package/dist/reservedWords.js +100 -0
- package/dist/reservedWords.js.map +1 -0
- package/package.json +56 -0
package/CHANGELOG.md
ADDED
package/LICENSE.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright © `2023` Benjie Gillam
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the “Software”), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
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, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# tamedevil
|
|
2
|
+
|
|
3
|
+
[](https://github.com/sponsors/benjie)
|
|
4
|
+
[](https://patreon.com/benjie)
|
|
5
|
+
[](http://discord.gg/graphile)
|
|
6
|
+
[](https://twitter.com/GraphileHQ)
|
|
7
|
+
|
|
8
|
+
**Eval is evil, this module helps tame it!**
|
|
9
|
+
|
|
10
|
+
It's generally recommended that you don't use `eval` or `new Function` when
|
|
11
|
+
writing JavaScript/TypeScript code. There's many many reasons for this, here are
|
|
12
|
+
but a few:
|
|
13
|
+
|
|
14
|
+
- **code injection**: without sufficient caution, attackers could inject
|
|
15
|
+
poisoned strings into your `eval`s and you might unwittingly start evaluating
|
|
16
|
+
their code, which can lead to extremely serious security incidents
|
|
17
|
+
- **garbage collection**: `eval` (and, to a lesser extend, `new Function`) are
|
|
18
|
+
hard for the JS engine to understand, which can result in values that should
|
|
19
|
+
have been garbage collected instead being retained just in case
|
|
20
|
+
- **debugging**: errors thrown from or issues inside of evaluated code are hard
|
|
21
|
+
to inspect, they don't have line numbers that match up with your source code
|
|
22
|
+
|
|
23
|
+
However, `eval` and `new Function` can be powerful tools for building performant
|
|
24
|
+
code - if you have a list of operations to perform, it may be much more
|
|
25
|
+
performant to build a dynamic function to evaluate those operations at native JS
|
|
26
|
+
speed rather than to build your own interpretter.
|
|
27
|
+
|
|
28
|
+
`tamedevil` makes it much safer to build this kind of dynamic function, by
|
|
29
|
+
ensuring that every string and substring that is to be evaluated is either code
|
|
30
|
+
that you, the author, has written (it's something "you know"), or is some text
|
|
31
|
+
that has been suitably escaped - this helps to address the **code injection**
|
|
32
|
+
concern. We accomplish this with the power of tagged template literals and
|
|
33
|
+
symbols.
|
|
34
|
+
|
|
35
|
+
We also attempt to address the **garbage collection** concern by ensuring that
|
|
36
|
+
there is no ephemeral data in the closure in which the code is evaluated, so
|
|
37
|
+
nothing to be garbage collected. Note that we **do not** capture the closure in
|
|
38
|
+
which you define the string - all parameters must be passed explicitly (via the
|
|
39
|
+
helpers), which is one reason we use `new Function` rather than `eval` under the
|
|
40
|
+
hood.
|
|
41
|
+
|
|
42
|
+
<!-- SPONSORS_BEGIN -->
|
|
43
|
+
|
|
44
|
+
## Crowd-funded open-source software
|
|
45
|
+
|
|
46
|
+
To help us develop this software sustainably under the MIT license, we ask all
|
|
47
|
+
individuals and businesses that use it to help support its ongoing maintenance
|
|
48
|
+
and development via sponsorship.
|
|
49
|
+
|
|
50
|
+
### [Click here to find out more about sponsors and sponsorship.](https://www.graphile.org/sponsor/)
|
|
51
|
+
|
|
52
|
+
And please give some love to our featured sponsors 🤩:
|
|
53
|
+
|
|
54
|
+
<table><tr>
|
|
55
|
+
<td align="center"><a href="https://surge.io/"><img src="https://graphile.org/images/sponsors/surge.png" width="90" height="90" alt="Surge" /><br />Surge</a> *</td>
|
|
56
|
+
<td align="center"><a href="https://www.netflix.com/"><img src="https://graphile.org/images/sponsors/Netflix.png" width="90" height="90" alt="Netflix" /><br />Netflix</a> *</td>
|
|
57
|
+
<td align="center"><a href="https://qwick.com/"><img src="https://graphile.org/images/sponsors/qwick.png" width="90" height="90" alt="Qwick" /><br />Qwick</a> *</td>
|
|
58
|
+
<td align="center"><a href="https://www.the-guild.dev/"><img src="https://graphile.org/images/sponsors/theguild.png" width="90" height="90" alt="The Guild" /><br />The Guild</a> *</td>
|
|
59
|
+
</tr><tr>
|
|
60
|
+
<td align="center"><a href="http://chads.website"><img src="https://graphile.org/images/sponsors/chadf.png" width="90" height="90" alt="Chad Furman" /><br />Chad Furman</a> *</td>
|
|
61
|
+
<td align="center"><a href="https://www.fanatics.com/"><img src="https://graphile.org/images/sponsors/fanatics.png" width="90" height="90" alt="Fanatics" /><br />Fanatics</a> *</td>
|
|
62
|
+
<td align="center"><a href="https://dovetailapp.com/"><img src="https://graphile.org/images/sponsors/dovetail.png" width="90" height="90" alt="Dovetail" /><br />Dovetail</a> *</td>
|
|
63
|
+
<td align="center"><a href="https://www.enzuzo.com/"><img src="https://graphile.org/images/sponsors/enzuzo.png" width="90" height="90" alt="Enzuzo" /><br />Enzuzo</a> *</td>
|
|
64
|
+
</tr><tr>
|
|
65
|
+
<td align="center"><a href="https://stellate.co/"><img src="https://graphile.org/images/sponsors/Stellate.png" width="90" height="90" alt="Stellate" /><br />Stellate</a> *</td>
|
|
66
|
+
</tr></table>
|
|
67
|
+
|
|
68
|
+
<em>\* Sponsors the entire Graphile suite</em>
|
|
69
|
+
|
|
70
|
+
<!-- SPONSORS_END -->
|
|
71
|
+
|
|
72
|
+
## Installation
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
yarn add tamedevil
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
or
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
npm install --save tamedevil
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Importing
|
|
85
|
+
|
|
86
|
+
We use the abbreviation `te` to refer to the tagged template literal function,
|
|
87
|
+
and all the helpers are available as properties on this function, so it's
|
|
88
|
+
typically the only thing you need to import.
|
|
89
|
+
|
|
90
|
+
For ESM, import `te`:
|
|
91
|
+
|
|
92
|
+
<!-- skip-example -->
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
import { te } from "tamedevil";
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Or for CommonJS, `require` it:
|
|
99
|
+
|
|
100
|
+
<!-- skip-example -->
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
const { te } = require("tamedevil");
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Example
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
// Here's a string we want to embed into the function:
|
|
110
|
+
const spec = "some string here";
|
|
111
|
+
|
|
112
|
+
// And here's a complex variable we want to use within the function's scope:
|
|
113
|
+
const source = new Source(/* ... */);
|
|
114
|
+
|
|
115
|
+
const toEval = te`\
|
|
116
|
+
const source = ${te.ref(source)};
|
|
117
|
+
return function plan($record) {
|
|
118
|
+
const $records = source.find(${te.lit(spec)});
|
|
119
|
+
return connection($records);
|
|
120
|
+
}
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
const plan = te.run(toEval);
|
|
124
|
+
|
|
125
|
+
console.log(plan.toString());
|
|
126
|
+
/* Outputs:
|
|
127
|
+
|
|
128
|
+
function plan($record) {
|
|
129
|
+
const $records = source.find("some string here");
|
|
130
|
+
return connection($records);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
*/
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## API
|
|
137
|
+
|
|
138
|
+
### `` te`...` ``
|
|
139
|
+
|
|
140
|
+
Builds part of (or the whole of) a JS expression, safely interpreting the
|
|
141
|
+
embedded expressions. If a non `te` expression is passed in, e.g.:
|
|
142
|
+
|
|
143
|
+
<!-- skip-example -->
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
te`return 2 + ${1}`;
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
then an error will be thrown. This prevents code injection, as all values must
|
|
150
|
+
go through an allowed API.
|
|
151
|
+
|
|
152
|
+
### `te.ref(val)` (alias: te.reference)
|
|
153
|
+
|
|
154
|
+
Tells `te` to pass the given value by reference into the scope of the function
|
|
155
|
+
via a closure, and returns an identifier that can be used to reference it. Note:
|
|
156
|
+
the identifier used will be randomized to avoid the risk of conflicts, so if you
|
|
157
|
+
are building code that will ultimately return a function, we recommend giving
|
|
158
|
+
the ref an alias outside of the function to make the function text easier to
|
|
159
|
+
debug, e.g.:
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
const source = new Source(/* ... */);
|
|
163
|
+
const spec = "some string here";
|
|
164
|
+
|
|
165
|
+
const toEval = te`\
|
|
166
|
+
const source = ${te.ref(source)};
|
|
167
|
+
return function plan($record) {
|
|
168
|
+
const $records = source.find(${te.lit(spec)});
|
|
169
|
+
return connection($records);
|
|
170
|
+
}
|
|
171
|
+
`;
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### `te.lit(val)` (alias: te.literal)
|
|
175
|
+
|
|
176
|
+
As `te.ref`, but in the case of simple primitive values (strings, numbers,
|
|
177
|
+
booleans, null, undefined) may write them directly to the code rather than
|
|
178
|
+
passing them by reference, which may make the resulting code easier to read.
|
|
179
|
+
|
|
180
|
+
Besides being useful for general purposes, this is the preferred way of safely
|
|
181
|
+
settings keys on a dynamic object, for example:
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
// This is a perfectly reasonable key
|
|
185
|
+
const key1 = "one";
|
|
186
|
+
|
|
187
|
+
// Note this key would be unsafe to set on an object created via `{}`, but is
|
|
188
|
+
// fine for `Object.create(null)`
|
|
189
|
+
const key2 = "__proto__";
|
|
190
|
+
|
|
191
|
+
const fragment = te`\
|
|
192
|
+
const obj = Object.create(null);
|
|
193
|
+
obj[${te.lit(key1)}] = 1;
|
|
194
|
+
obj[${te.lit(key2)}] = {str: true};
|
|
195
|
+
return obj;
|
|
196
|
+
`;
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### `te.substring(str, stringType)`
|
|
200
|
+
|
|
201
|
+
If you're building a string and you want to inject untrusted content into it
|
|
202
|
+
without opening yourself to code injection attacks, this is the method for you.
|
|
203
|
+
Pass the string you'd like escaped as the first argument, and the second
|
|
204
|
+
argument should be `"`, `'` or `` ` `` depending on what type of string you're
|
|
205
|
+
embedding into. Example:
|
|
206
|
+
|
|
207
|
+
```js
|
|
208
|
+
const code = te`const str = "abc${te.substring(untrusted, '"')}123";`;
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### `te.join(arrayOfFragments, delimiter)`
|
|
212
|
+
|
|
213
|
+
Joins an array of `te` values using the delimiter (a plain string); e.g.
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
const keysAndValues = ["a", "b", "c", "d"].map(
|
|
217
|
+
(n, i) => te`${te.dangerousKey(n)}: ${te.literal(i)}`,
|
|
218
|
+
);
|
|
219
|
+
const obj = te`{ ${te.join(keysAndValues, ", ")} }`;
|
|
220
|
+
// obj = { a: 0, b: 1, c: 2, d: 3 }
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### `te.identifier(name)`
|
|
224
|
+
|
|
225
|
+
Takes `name` (string) and returns a `TE` node for it if it could be a reasonable
|
|
226
|
+
name for a variable. If it doesn't seem a reasonable name then it will instead
|
|
227
|
+
throw an error, so be warned! This means that it will throw an error if any JS
|
|
228
|
+
reserved words are used, or if the name is potentially confusing (e.g. `async`).
|
|
229
|
+
For a full list of the _current_ reserved words, see
|
|
230
|
+
[reservedWords.ts](./src/reservedWords.ts), but not that these words may change
|
|
231
|
+
in a minor release.
|
|
232
|
+
|
|
233
|
+
This is not intended to be used with untrusted user data, it's just a
|
|
234
|
+
convenience method to use for example if you want to map the (string) keys of an
|
|
235
|
+
object into variable name TE nodes without using `te.raw`. Normally you'd just
|
|
236
|
+
use `` te`myVarNameHere` `` to define a variable name (as just regular code).
|
|
237
|
+
|
|
238
|
+
### `te.dangerousKey(ident, forceQuotes = false)`
|
|
239
|
+
|
|
240
|
+
Takes `ident` and turns it into the representation of a safely escaped
|
|
241
|
+
JavaScript object key (to be used in an object definition). We do our best to
|
|
242
|
+
not put quote marks around the key unless necessary (or `forceQuotes` is set),
|
|
243
|
+
so that the output code is more pleasant to read.
|
|
244
|
+
|
|
245
|
+
We'll throw an error if you pass an `ident` that contains unexpected characters,
|
|
246
|
+
this is intended to be used with relatively straightforward strings
|
|
247
|
+
(`/[$@A-Za-z0-9_.-]+$/`). We also forbid common attack vectors such as
|
|
248
|
+
`__proto__`, `constructor`, `hasOwnProperty`, etc. (For the full list, evaluate
|
|
249
|
+
`Object.getOwnPropertyNames(Object.prototype)`.)
|
|
250
|
+
|
|
251
|
+
**IMPORTANT**: It's strongly recommended that instead of defining an object via
|
|
252
|
+
`const obj = { ${te.dangerousKey(untrustedKey)}: value }` you instead use
|
|
253
|
+
`const obj = Object.create(null);` and then set the properties on the resulting
|
|
254
|
+
object via `${obj}[${te.lit(untrustedKey)}] = value;` - this prevents attacks
|
|
255
|
+
such as **prototype polution** since properties like `__proto__` are not special
|
|
256
|
+
on null-prototype objects, whereas they can cause havok in regular `{}` objects.
|
|
257
|
+
|
|
258
|
+
### `te.get(key)`
|
|
259
|
+
|
|
260
|
+
Returns an expression for accessing the property `key` (which could be a string,
|
|
261
|
+
symbol or number) of the preceding expression; will return code like `.foo` or
|
|
262
|
+
`["foo"]` as appropriate.
|
|
263
|
+
|
|
264
|
+
### `te.optionalGet(key)`
|
|
265
|
+
|
|
266
|
+
As with `te.get` except using optional chaining - the expression will be `?.foo`
|
|
267
|
+
or `?.["foo"]` as appropriate.
|
|
268
|
+
|
|
269
|
+
### `te.set(key, hasNullPrototype)`
|
|
270
|
+
|
|
271
|
+
As with `te.get`, except since it's for setting a key we'll perform checks to
|
|
272
|
+
ensure you're not writing to unsafe keys (such as `__proto__`) unless you
|
|
273
|
+
specify that `hasNullPrototype` is true (because any key can bet written safely
|
|
274
|
+
to `Object.create(null)`).
|
|
275
|
+
|
|
276
|
+
### `te.tempVar(symbol = Symbol())`
|
|
277
|
+
|
|
278
|
+
**EXPERIMENTAL**
|
|
279
|
+
|
|
280
|
+
Creates a temporary variable (or returns the existing temp var if the same
|
|
281
|
+
symbol is passed again) that can be used in expressions and statements.
|
|
282
|
+
|
|
283
|
+
### `te.tmp(obj, callback)`
|
|
284
|
+
|
|
285
|
+
(**ADVANCED**)
|
|
286
|
+
|
|
287
|
+
If `obj` is potentially expensive code and you need to reference it multiple
|
|
288
|
+
times (e.g. `` te`(${obj}.foo === 3 ? ${obj}.bar : ${obj}.baz)` ``) then you
|
|
289
|
+
can use `tmp` to create a temporary variable that stores reference to it and
|
|
290
|
+
return the result of calling `callback` passing this temporary reference. E.g.
|
|
291
|
+
`` te.tmp(obj, tmp => te`(${tmp}.foo === 3 ? ${tmp}.bar : ${tmp}.baz)`) `` means
|
|
292
|
+
that the potentially expensive expression in the original `obj` variable only
|
|
293
|
+
need to be evaluated once, not 3 times.
|
|
294
|
+
|
|
295
|
+
### `te.run(fragment)` (alias: eval)
|
|
296
|
+
|
|
297
|
+
Evaluates the TE fragment and returns the result.
|
|
298
|
+
|
|
299
|
+
```js
|
|
300
|
+
const fragment = te`return 1 + 2`;
|
|
301
|
+
const result = te.run(fragment);
|
|
302
|
+
// result = 3;
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### `te.compile(fragment)`
|
|
306
|
+
|
|
307
|
+
Builds the TE fragment into a string ready to be evaluated, but does not
|
|
308
|
+
evaluate it. Returns an object containing the `string` and any `refs`. Useful
|
|
309
|
+
for debugging, or tests.
|
|
310
|
+
|
|
311
|
+
```js
|
|
312
|
+
const fragment = te`return ${te.ref(1)} + ${te.ref(2)}`;
|
|
313
|
+
const result = te.compile(fragment);
|
|
314
|
+
// result = { string: `return _$_ref1 + _$_ref2`, refs: { _$_ref1: 1, _$_ref2: 2 } }
|
|
315
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { reservedWords } from "./reservedWords.js";
|
|
2
|
+
/**
|
|
3
|
+
* This is the secret to our safety; since this is a symbol it cannot be faked
|
|
4
|
+
* in a JSON payload and it cannot be constructed with a new Symbol (even with
|
|
5
|
+
* the same argument), so external data cannot make itself trusted.
|
|
6
|
+
*/
|
|
7
|
+
declare const $$type: unique symbol;
|
|
8
|
+
/**
|
|
9
|
+
* Represents raw TE, the text will be output verbatim into the compiled code.
|
|
10
|
+
*/
|
|
11
|
+
export interface TERawNode {
|
|
12
|
+
readonly [$$type]: "RAW";
|
|
13
|
+
/** text */
|
|
14
|
+
readonly t: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Represents an TE value that will be replaced with a closure variable in the
|
|
18
|
+
* compiled TE statement.
|
|
19
|
+
*/
|
|
20
|
+
export interface TERefNode {
|
|
21
|
+
readonly [$$type]: "REF";
|
|
22
|
+
/** value */
|
|
23
|
+
readonly v: any;
|
|
24
|
+
}
|
|
25
|
+
export interface TETemporaryVariableNode {
|
|
26
|
+
readonly [$$type]: "VARIABLE";
|
|
27
|
+
/** symbol */
|
|
28
|
+
readonly s: symbol;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Represents that the TE inside this should be indented when pretty printed.
|
|
32
|
+
*/
|
|
33
|
+
export interface TEIndentNode {
|
|
34
|
+
readonly [$$type]: "INDENT";
|
|
35
|
+
/** content */
|
|
36
|
+
readonly c: TEQuery;
|
|
37
|
+
}
|
|
38
|
+
/** @internal */
|
|
39
|
+
export declare type TENode = TERawNode | TERefNode | TETemporaryVariableNode | TEIndentNode;
|
|
40
|
+
/** @internal */
|
|
41
|
+
export interface TEQuery {
|
|
42
|
+
readonly [$$type]: "QUERY";
|
|
43
|
+
/** nodes */
|
|
44
|
+
readonly n: ReadonlyArray<TENode>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Representation of TE, identifiers, values, etc; to generate a query that
|
|
48
|
+
* can be issued to the database it needs to be fed to `te.compile`.
|
|
49
|
+
*/
|
|
50
|
+
export declare type TE = TENode | TEQuery;
|
|
51
|
+
declare function isTE(node: unknown): node is TE;
|
|
52
|
+
/**
|
|
53
|
+
* Accepts an te`...` expression and compiles it out to TE text with
|
|
54
|
+
* placeholders, and the values to substitute for these values.
|
|
55
|
+
*/
|
|
56
|
+
declare function compile(fragment: TE): {
|
|
57
|
+
string: string;
|
|
58
|
+
refs: {
|
|
59
|
+
[key: string]: any;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Creates a TE item for a raw code string. Just plain ol‘ raw code. This
|
|
64
|
+
* method is dangerous though because it involves no escaping, so proceed with
|
|
65
|
+
* caution! It's very very rarely warranted - there is likely a safer way of
|
|
66
|
+
* achieving your goal. DO NOT USE THIS WITH UNTRUSTED INPUT!
|
|
67
|
+
*/
|
|
68
|
+
declare function raw(text: string): TE;
|
|
69
|
+
/**
|
|
70
|
+
* Creates a TE item for a value that will be included in our final query.
|
|
71
|
+
* This value will be added in a way which avoids TE injection.
|
|
72
|
+
*/
|
|
73
|
+
declare function ref(val: any): TE;
|
|
74
|
+
declare const undefinedNode: TERawNode;
|
|
75
|
+
export declare function stringifyString(value: string): string;
|
|
76
|
+
export declare const toJSON: (value: any) => string;
|
|
77
|
+
/**
|
|
78
|
+
* If the value is simple will inline it into the query, otherwise will defer
|
|
79
|
+
* to `te.ref`.
|
|
80
|
+
*/
|
|
81
|
+
declare function lit(val: any): TE;
|
|
82
|
+
/**
|
|
83
|
+
* If you're building a string and you want to inject untrusted content into it
|
|
84
|
+
* without opening yourself to code injection attacks, this is the method for
|
|
85
|
+
* you. Example:
|
|
86
|
+
*
|
|
87
|
+
* ```js
|
|
88
|
+
* const code = te`const str = "abc${te.substring(untrusted, '"')}123";`
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
declare function substring(text: string, stringType: "'" | '"' | "`"): TE;
|
|
92
|
+
/**
|
|
93
|
+
* Escapes `content` so that it can be safely embedded in a multiline comment.
|
|
94
|
+
*/
|
|
95
|
+
declare function subcomment(content: string | number | null | undefined): TERawNode;
|
|
96
|
+
/**
|
|
97
|
+
* Is safe to set as the key of a POJO (without a null prototype).
|
|
98
|
+
*/
|
|
99
|
+
export declare const isSafeObjectPropertyName: (key: string | symbol | number) => boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Can represent as an identifier rather than a string key
|
|
102
|
+
*
|
|
103
|
+
* @remarks
|
|
104
|
+
* Doesn't allow it to start with two underscores.
|
|
105
|
+
*/
|
|
106
|
+
export declare const canRepresentAsIdentifier: (key: string | symbol | number) => key is string | number;
|
|
107
|
+
declare function identifier(name: string): TERawNode;
|
|
108
|
+
/**
|
|
109
|
+
* IMPORTANT: It's strongly recommended that instead of defining an object via
|
|
110
|
+
* `const obj = { ${te.dangerousKey(untrustedKey)}: value }` you instead use
|
|
111
|
+
* `const obj = Object.create(null);` and then set the properties on the resulting
|
|
112
|
+
* object via `${obj}[${te.lit(untrustedKey)}] = value;` - this prevents attacks such as
|
|
113
|
+
* **prototype polution** since properties like `__proto__` are not special on
|
|
114
|
+
* null-prototype objects, whereas they can cause havok in regular `{}` objects.
|
|
115
|
+
*/
|
|
116
|
+
declare function dangerousKey(key: string | symbol | number): TE;
|
|
117
|
+
/**
|
|
118
|
+
* Accesses the key of an object either via `.` or `[]` as appropriate;
|
|
119
|
+
* `obj${te.get(key)}` would become `obj.foo` or `obj["1foo"]` as
|
|
120
|
+
* appropriate.
|
|
121
|
+
*/
|
|
122
|
+
declare function get(key: string | symbol | number): TE;
|
|
123
|
+
/**
|
|
124
|
+
* Accesses the key of an object via optional-chaining:
|
|
125
|
+
* `obj${te.optionalGet(key)}` would become `obj?.foo` or `obj?.["1foo"]` as
|
|
126
|
+
* appropriate.
|
|
127
|
+
*/
|
|
128
|
+
declare function optionalGet(key: string | symbol | number): TE;
|
|
129
|
+
/**
|
|
130
|
+
* Sets the key of an object either via `.` or `[]` as appropriate;
|
|
131
|
+
* `obj${te.set(key)}` would become `obj.foo` or `obj["1foo"]` as
|
|
132
|
+
* appropriate.
|
|
133
|
+
*
|
|
134
|
+
* If the object you're setting properties on has a `null` prototype
|
|
135
|
+
* (`Object.create(null)`) then you can set `hasNullPrototype` to true and all
|
|
136
|
+
* keys are allowed. If this is not the case, then an error will be thrown on
|
|
137
|
+
* certain potentially dangerous keys such as `__proto__` or `constructor`.
|
|
138
|
+
*/
|
|
139
|
+
declare function set(key: string | symbol | number, hasNullPrototype?: boolean): TE;
|
|
140
|
+
/**
|
|
141
|
+
* @experimental
|
|
142
|
+
*/
|
|
143
|
+
declare function tempVar(symbol?: symbol): TE;
|
|
144
|
+
declare function tmp(obj: TE, callback: (tmp: TE) => TE): TE;
|
|
145
|
+
declare function run<TResult>(fragment: TE): TResult;
|
|
146
|
+
declare function run<TResult>(strings: TemplateStringsArray, ...values: TE[]): TResult;
|
|
147
|
+
/**
|
|
148
|
+
* Join some TE items together, optionally separated by a string. Useful when
|
|
149
|
+
* dealing with lists of TE items, for example a dynamic list of columns or
|
|
150
|
+
* variadic TE function arguments.
|
|
151
|
+
*/
|
|
152
|
+
declare function join(items: Array<TE>, separator?: string): TE;
|
|
153
|
+
/**
|
|
154
|
+
* WARNING: all lines will be indented, without any parsing, so if there are
|
|
155
|
+
* template literals that contain newlines, spaces will be added inside these
|
|
156
|
+
* too.
|
|
157
|
+
*/
|
|
158
|
+
declare function indent(fragment: TE): TE;
|
|
159
|
+
declare function indent(strings: TemplateStringsArray, ...values: Array<TE>): TE;
|
|
160
|
+
declare function indentIf(condition: boolean, fragment: TE): TE;
|
|
161
|
+
declare const te: TamedEvil;
|
|
162
|
+
export default te;
|
|
163
|
+
export { compile, dangerousKey, run as eval, get, identifier, isTE, join, lit, lit as literal, optionalGet, ref, reservedWords, run, set, subcomment, substring, te, tempVar, tmp, undefinedNode as undefined, raw, };
|
|
164
|
+
export interface TamedEvil {
|
|
165
|
+
(strings: TemplateStringsArray, ...values: Array<TE>): TE;
|
|
166
|
+
te: TamedEvil;
|
|
167
|
+
ref: typeof ref;
|
|
168
|
+
reference: typeof ref;
|
|
169
|
+
lit: typeof lit;
|
|
170
|
+
literal: typeof lit;
|
|
171
|
+
substring: typeof substring;
|
|
172
|
+
subcomment: typeof subcomment;
|
|
173
|
+
join: typeof join;
|
|
174
|
+
identifier: typeof identifier;
|
|
175
|
+
dangerousKey: typeof dangerousKey;
|
|
176
|
+
get: typeof get;
|
|
177
|
+
optionalGet: typeof optionalGet;
|
|
178
|
+
set: typeof set;
|
|
179
|
+
tmp: typeof tmp;
|
|
180
|
+
tempVar: typeof tempVar;
|
|
181
|
+
run: {
|
|
182
|
+
<TResult>(fragment: TE): TResult;
|
|
183
|
+
<TResult>(strings: TemplateStringsArray, ...values: TE[]): TResult;
|
|
184
|
+
};
|
|
185
|
+
eval: {
|
|
186
|
+
<TResult>(fragment: TE): TResult;
|
|
187
|
+
<TResult>(strings: TemplateStringsArray, ...values: TE[]): TResult;
|
|
188
|
+
};
|
|
189
|
+
compile: typeof compile;
|
|
190
|
+
indent: typeof indent;
|
|
191
|
+
indentIf: typeof indentIf;
|
|
192
|
+
undefined: TE;
|
|
193
|
+
blank: TE;
|
|
194
|
+
isTE: typeof isTE;
|
|
195
|
+
reservedWords: typeof reservedWords;
|
|
196
|
+
raw: typeof raw;
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|