@zvndev/powdb-client 0.3.2 → 0.3.5
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 +48 -0
- package/LICENSE +21 -0
- package/README.md +14 -6
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/protocol.d.ts +4 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +35 -7
- package/dist/protocol.js.map +1 -1
- package/package.json +28 -4
- package/src/errors.ts +0 -54
- package/src/escape.ts +0 -141
- package/src/index.ts +0 -658
- package/src/pool.ts +0 -375
- package/src/protocol.ts +0 -234
- package/src/typed.ts +0 -148
package/src/escape.ts
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Safe PowQL composition helpers: literal and identifier escaping, plus a
|
|
3
|
-
* tagged-template convenience for building queries without string splicing.
|
|
4
|
-
*
|
|
5
|
-
* const q = powql`insert ${ident("User")} { name := ${userName}, age := ${age} }`;
|
|
6
|
-
* await client.query(q);
|
|
7
|
-
*
|
|
8
|
-
* Security model:
|
|
9
|
-
* - Literals are rendered with quoting/escaping so interpolated values
|
|
10
|
-
* cannot break out of the surrounding literal.
|
|
11
|
-
* - Identifiers are validated against `^[A-Za-z_][A-Za-z0-9_]*$` and passed
|
|
12
|
-
* through unchanged. Anything else throws a `TypeError`.
|
|
13
|
-
*
|
|
14
|
-
* PowQL string-escape rules (verified against `crates/query/src/lexer.rs`):
|
|
15
|
-
* - Strings are delimited by `"`.
|
|
16
|
-
* - `\\` → `\`, `\"` → `"`, `\n` → newline, `\t` → tab.
|
|
17
|
-
* - For any other `\X`, the backslash is dropped and `X` is kept literally.
|
|
18
|
-
* - A bare `"` terminates the string, so `"` inside must be `\"` and any
|
|
19
|
-
* literal backslash must be `\\` (otherwise it would swallow the next char).
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
const IDENT_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
23
|
-
|
|
24
|
-
/** Wrapper marking a string as an identifier (vs a literal) for `powql` tagged templates. */
|
|
25
|
-
export class PowqlIdent {
|
|
26
|
-
constructor(public readonly name: string) {}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** Factory for {@link PowqlIdent}. Prefer this over `new PowqlIdent(...)` at call sites. */
|
|
30
|
-
export function ident(name: string): PowqlIdent {
|
|
31
|
-
return new PowqlIdent(name);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Validate a PowQL identifier (table name, field name, alias). Returns the
|
|
36
|
-
* identifier unchanged on success; throws `TypeError` on any invalid input
|
|
37
|
-
* (non-string, empty, or containing characters outside `[A-Za-z_][A-Za-z0-9_]*`).
|
|
38
|
-
*/
|
|
39
|
-
export function escapeIdent(name: string): string {
|
|
40
|
-
if (typeof name !== "string") {
|
|
41
|
-
throw new TypeError(
|
|
42
|
-
`escapeIdent: expected string, got ${typeof name}`
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
if (name.length === 0) {
|
|
46
|
-
throw new TypeError("escapeIdent: identifier must not be empty");
|
|
47
|
-
}
|
|
48
|
-
if (!IDENT_RE.test(name)) {
|
|
49
|
-
throw new TypeError(
|
|
50
|
-
`escapeIdent: invalid identifier ${JSON.stringify(name)} (must match /^[A-Za-z_][A-Za-z0-9_]*$/)`
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
return name;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Render a JS value as a PowQL literal. Supports `string`, `number`, `bigint`,
|
|
58
|
-
* `boolean`, and `null`. Rejects `NaN`/`±Infinity`, `undefined`, symbols,
|
|
59
|
-
* objects, and arrays with `TypeError`.
|
|
60
|
-
*
|
|
61
|
-
* - string → `"..."` with `\` and `"` backslash-escaped (C-style, per the
|
|
62
|
-
* PowQL lexer). Backslash must be escaped first to avoid double-processing.
|
|
63
|
-
* - number → decimal; rejects non-finite
|
|
64
|
-
* - bigint → decimal digits
|
|
65
|
-
* - boolean → `true` / `false`
|
|
66
|
-
* - null → `null`
|
|
67
|
-
*/
|
|
68
|
-
export function escapeLiteral(
|
|
69
|
-
value: string | number | bigint | boolean | null
|
|
70
|
-
): string {
|
|
71
|
-
if (value === null) return "null";
|
|
72
|
-
|
|
73
|
-
const t = typeof value;
|
|
74
|
-
|
|
75
|
-
if (t === "string") {
|
|
76
|
-
const escaped = (value as string)
|
|
77
|
-
.replace(/\\/g, "\\\\")
|
|
78
|
-
.replace(/"/g, '\\"');
|
|
79
|
-
return `"${escaped}"`;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (t === "number") {
|
|
83
|
-
const n = value as number;
|
|
84
|
-
if (!Number.isFinite(n)) {
|
|
85
|
-
throw new TypeError(
|
|
86
|
-
`escapeLiteral: non-finite number ${String(n)} cannot be represented as a PowQL literal`
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
return String(n);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (t === "bigint") {
|
|
93
|
-
return (value as bigint).toString(10);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (t === "boolean") {
|
|
97
|
-
return value ? "true" : "false";
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
throw new TypeError(`escapeLiteral: unsupported type ${describe(value)}`);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Tagged template for safe PowQL composition. Each interpolated value is
|
|
105
|
-
* escaped as a literal by default; wrap it in `ident(...)` to interpolate as
|
|
106
|
-
* an identifier.
|
|
107
|
-
*
|
|
108
|
-
* const q = powql`insert ${ident(table)} { name := ${userName} }`;
|
|
109
|
-
*/
|
|
110
|
-
export function powql(
|
|
111
|
-
strings: TemplateStringsArray,
|
|
112
|
-
...values: unknown[]
|
|
113
|
-
): string {
|
|
114
|
-
let out = strings[0] ?? "";
|
|
115
|
-
for (let i = 0; i < values.length; i++) {
|
|
116
|
-
out += renderInterpolation(values[i]);
|
|
117
|
-
out += strings[i + 1] ?? "";
|
|
118
|
-
}
|
|
119
|
-
return out;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// ──────────────────────────────────────────────────────────
|
|
123
|
-
// internals
|
|
124
|
-
// ──────────────────────────────────────────────────────────
|
|
125
|
-
|
|
126
|
-
function renderInterpolation(value: unknown): string {
|
|
127
|
-
if (value instanceof PowqlIdent) {
|
|
128
|
-
return escapeIdent(value.name);
|
|
129
|
-
}
|
|
130
|
-
// `escapeLiteral` enforces the allowed set — for anything else it throws.
|
|
131
|
-
return escapeLiteral(value as string | number | bigint | boolean | null);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function describe(value: unknown): string {
|
|
135
|
-
if (value === undefined) return "undefined";
|
|
136
|
-
if (value === null) return "null";
|
|
137
|
-
if (Array.isArray(value)) return "array";
|
|
138
|
-
const t = typeof value;
|
|
139
|
-
if (t === "object") return "object";
|
|
140
|
-
return t;
|
|
141
|
-
}
|