@evolu/common 6.0.1-preview.25 → 6.0.1-preview.26
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/dist/src/Assert.d.ts +0 -13
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +0 -15
- package/dist/src/Cache.d.ts +44 -0
- package/dist/src/Cache.d.ts.map +1 -0
- package/dist/src/Cache.js +52 -0
- package/dist/src/Evolu/Db.d.ts +6 -6
- package/dist/src/Evolu/Db.d.ts.map +1 -1
- package/dist/src/Evolu/Db.js +4 -0
- package/dist/src/Evolu/LocalAuth.d.ts +2 -2
- package/dist/src/Evolu/LocalAuth.d.ts.map +1 -1
- package/dist/src/Evolu/Owner.d.ts +116 -86
- package/dist/src/Evolu/Owner.d.ts.map +1 -1
- package/dist/src/Evolu/Owner.js +48 -45
- package/dist/src/Evolu/Relay.d.ts +6 -5
- package/dist/src/Evolu/Relay.d.ts.map +1 -1
- package/dist/src/Evolu/Relay.js +40 -39
- package/dist/src/Evolu/Storage.d.ts +6 -11
- package/dist/src/Evolu/Storage.d.ts.map +1 -1
- package/dist/src/Evolu/Storage.js +30 -9
- package/dist/src/Evolu/Sync.d.ts +5 -5
- package/dist/src/Evolu/Sync.d.ts.map +1 -1
- package/dist/src/Evolu/Sync.js +3 -5
- package/dist/src/Evolu/Timestamp.d.ts +24 -0
- package/dist/src/Evolu/Timestamp.d.ts.map +1 -1
- package/dist/src/Evolu/Timestamp.js +24 -0
- package/dist/src/Identicon.d.ts +35 -0
- package/dist/src/Identicon.d.ts.map +1 -0
- package/dist/src/Identicon.js +143 -0
- package/dist/src/ManyToManyMap.d.ts +0 -3
- package/dist/src/ManyToManyMap.d.ts.map +1 -1
- package/dist/src/Result.d.ts +13 -6
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Sqlite.d.ts +36 -1
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +56 -3
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +36 -0
- package/dist/src/Type.d.ts +5 -8
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +10 -10
- package/dist/src/Types.d.ts +1 -1
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +2 -7
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/package.json +1 -1
- package/src/Assert.ts +0 -19
- package/src/Cache.ts +85 -0
- package/src/Evolu/Db.ts +11 -7
- package/src/Evolu/LocalAuth.ts +19 -7
- package/src/Evolu/Owner.ts +140 -103
- package/src/Evolu/Relay.ts +52 -48
- package/src/Evolu/Storage.ts +47 -23
- package/src/Evolu/Sync.ts +11 -12
- package/src/Evolu/Timestamp.ts +24 -0
- package/src/Identicon.ts +197 -0
- package/src/ManyToManyMap.ts +0 -3
- package/src/Result.ts +13 -6
- package/src/Sqlite.ts +68 -5
- package/src/Task.ts +41 -0
- package/src/Type.ts +11 -14
- package/src/Types.ts +1 -1
- package/src/WebSocket.ts +6 -10
- package/src/index.ts +2 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { idToIdBytes } from "./Type.js";
|
|
2
|
+
import { md5 } from "@noble/hashes/legacy.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a deterministic identicon SVG from an {@link Id}.
|
|
5
|
+
*
|
|
6
|
+
* Works with any {@link Id} including branded IDs like `OwnerId`, etc.
|
|
7
|
+
*
|
|
8
|
+
* Available styles:
|
|
9
|
+
*
|
|
10
|
+
* - `"github"` (default): 5x5 grid with horizontal mirroring (GitHub-style)
|
|
11
|
+
* - `"quadrant"`: 2x2 grid with direct RGB color mapping from bytes
|
|
12
|
+
* - `"gradient"`: Diagonal stripes with smooth color gradients
|
|
13
|
+
* - `"sutnar"`: Three compositional variants with adaptive colors
|
|
14
|
+
*
|
|
15
|
+
* ### Example
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* const svg = createIdenticon(id);
|
|
19
|
+
* const quadrantStyle = createIdenticon(id, "quadrant");
|
|
20
|
+
* const gradientStyle = createIdenticon(id, "gradient");
|
|
21
|
+
* const sutnarStyle = createIdenticon(id, "sutnar");
|
|
22
|
+
*
|
|
23
|
+
* // Works with branded IDs
|
|
24
|
+
* const ownerSvg = createIdenticon(ownerId);
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export const createIdenticon = (id, style = "github") => {
|
|
28
|
+
const bytes = idToIdBytes(id);
|
|
29
|
+
switch (style) {
|
|
30
|
+
case "github": {
|
|
31
|
+
// GitHub-style identicon: MD5 hash the bytes first
|
|
32
|
+
const hashedBytes = md5(bytes);
|
|
33
|
+
// Map function for value ranges
|
|
34
|
+
const map = (value, inMin, inMax, outMin, outMax) => ((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
|
|
35
|
+
// Extract 12-bit hue from bytes[12] (lower 4 bits) + bytes[13]
|
|
36
|
+
const h = ((hashedBytes[12] & 0x0f) << 8) | hashedBytes[13];
|
|
37
|
+
const hue = map(h, 0, 4095, 0, 360);
|
|
38
|
+
const saturation = 65 - map(hashedBytes[14], 0, 255, 0, 20);
|
|
39
|
+
const lightness = 75 - map(hashedBytes[15], 0, 255, 0, 20);
|
|
40
|
+
const fgColor = `hsl(${hue},${saturation}%,${lightness}%)`;
|
|
41
|
+
const bgColor = `hsl(${hue},${saturation}%,90%)`;
|
|
42
|
+
let rects = `<rect width="5" height="5" fill="${bgColor}"/>`;
|
|
43
|
+
// Extract nibbles and generate pattern
|
|
44
|
+
let nibbleIndex = 0;
|
|
45
|
+
for (let x = 2; x >= 0; x--) {
|
|
46
|
+
for (let y = 0; y < 5; y++) {
|
|
47
|
+
const byte = hashedBytes[Math.floor(nibbleIndex / 2)];
|
|
48
|
+
const nibble = nibbleIndex % 2 === 0 ? byte >> 4 : byte & 0x0f;
|
|
49
|
+
const paint = nibble % 2 === 0;
|
|
50
|
+
nibbleIndex++;
|
|
51
|
+
if (paint) {
|
|
52
|
+
rects += `<rect x="${x}" y="${y}" width="1" height="1" fill="${fgColor}"/>`;
|
|
53
|
+
const mx = 4 - x;
|
|
54
|
+
if (mx !== x) {
|
|
55
|
+
rects += `<rect x="${mx}" y="${y}" width="1" height="1" fill="${fgColor}"/>`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 5 5" shape-rendering="crispEdges">${rects}</svg>`;
|
|
61
|
+
}
|
|
62
|
+
case "quadrant": {
|
|
63
|
+
const toHex = (b) => b.toString(16).padStart(2, "0");
|
|
64
|
+
let rects = "";
|
|
65
|
+
for (let i = 0; i < 4; i++) {
|
|
66
|
+
const x = i % 2;
|
|
67
|
+
const y = Math.floor(i / 2);
|
|
68
|
+
const r = bytes[i * 3];
|
|
69
|
+
const g = bytes[i * 3 + 1];
|
|
70
|
+
const b = bytes[i * 3 + 2];
|
|
71
|
+
const color = `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
72
|
+
rects += `<rect x="${x}" y="${y}" width="1" height="1" fill="${color}"/>`;
|
|
73
|
+
}
|
|
74
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2">${rects}</svg>`;
|
|
75
|
+
}
|
|
76
|
+
case "gradient": {
|
|
77
|
+
// Smooth color gradients with diagonal stripes.
|
|
78
|
+
const toHex = (b) => b.toString(16).padStart(2, "0");
|
|
79
|
+
// Generate colors from bytes.
|
|
80
|
+
const color1 = `#${toHex(bytes[0])}${toHex(bytes[1])}${toHex(bytes[2])}`;
|
|
81
|
+
const color2 = `#${toHex(bytes[3])}${toHex(bytes[4])}${toHex(bytes[5])}`;
|
|
82
|
+
const color3 = `#${toHex(bytes[6])}${toHex(bytes[7])}${toHex(bytes[8])}`;
|
|
83
|
+
let defs = "";
|
|
84
|
+
let shapes = "";
|
|
85
|
+
// Diagonal stripes with gradient.
|
|
86
|
+
defs += `<linearGradient id="grad1-${id}" x1="0%" y1="0%" x2="0%" y2="100%">`;
|
|
87
|
+
defs += `<stop offset="0%" style="stop-color:${color1};stop-opacity:1" />`;
|
|
88
|
+
defs += `<stop offset="100%" style="stop-color:${color2};stop-opacity:1" />`;
|
|
89
|
+
defs += `</linearGradient>`;
|
|
90
|
+
defs += `<linearGradient id="grad2-${id}" x1="0%" y1="0%" x2="0%" y2="100%">`;
|
|
91
|
+
defs += `<stop offset="0%" style="stop-color:${color2};stop-opacity:1" />`;
|
|
92
|
+
defs += `<stop offset="100%" style="stop-color:${color3};stop-opacity:1" />`;
|
|
93
|
+
defs += `</linearGradient>`;
|
|
94
|
+
shapes += `<rect width="100" height="100" fill="url(#grad1-${id})"/>`;
|
|
95
|
+
const stripeWidth = 15 + (bytes[9] / 255) * 20;
|
|
96
|
+
const angle = 30 + (bytes[10] / 255) * 60;
|
|
97
|
+
shapes += `<rect x="20" y="-50" width="${stripeWidth}" height="200" fill="url(#grad2-${id})" transform="rotate(${angle} 50 50)" opacity="0.7"/>`;
|
|
98
|
+
shapes += `<rect x="60" y="-50" width="${stripeWidth}" height="200" fill="url(#grad2-${id})" transform="rotate(${angle} 50 50)" opacity="0.5"/>`;
|
|
99
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs>${defs}</defs>${shapes}</svg>`;
|
|
100
|
+
}
|
|
101
|
+
case "sutnar": {
|
|
102
|
+
// Three compositional variants with adaptive colors.
|
|
103
|
+
const hue = (bytes[0] / 255) * 360;
|
|
104
|
+
const saturation = 50 + (bytes[1] / 255) * 30;
|
|
105
|
+
const lightness = 50 + (bytes[2] / 255) * 20;
|
|
106
|
+
// Generate palette from base hue with variations
|
|
107
|
+
const toHsl = (h, s, l) => `hsl(${h},${s}%,${l}%)`;
|
|
108
|
+
const color1 = toHsl(hue, saturation, lightness);
|
|
109
|
+
const color2 = toHsl((hue + 120) % 360, saturation, lightness);
|
|
110
|
+
const color3 = toHsl((hue + 240) % 360, saturation, lightness);
|
|
111
|
+
const color4 = toHsl(hue, saturation * 0.3, lightness * 0.5);
|
|
112
|
+
const color5 = toHsl(hue, saturation * 0.5, Math.min(lightness * 1.3, 90));
|
|
113
|
+
const palette = [color1, color2, color3, color4, color5];
|
|
114
|
+
// Layout variant based on first byte.
|
|
115
|
+
const variant = bytes[3] % 3;
|
|
116
|
+
let shapes = "";
|
|
117
|
+
// Almost white background with subtle tint.
|
|
118
|
+
shapes += `<rect width="100" height="100" fill="${toHsl(hue, 10, 95)}"/>`;
|
|
119
|
+
if (variant === 0) {
|
|
120
|
+
// Composition A: Circle + horizontal bar.
|
|
121
|
+
const circleColor = palette[bytes[4] % palette.length];
|
|
122
|
+
const barColor = palette[(bytes[4] + 1) % palette.length];
|
|
123
|
+
shapes += `<circle cx="30" cy="50" r="22" fill="${circleColor}"/>`;
|
|
124
|
+
shapes += `<rect x="60" y="40" width="35" height="20" fill="${barColor}"/>`;
|
|
125
|
+
}
|
|
126
|
+
else if (variant === 1) {
|
|
127
|
+
// Composition B: Vertical bar + circle.
|
|
128
|
+
const barColor = palette[bytes[5] % palette.length];
|
|
129
|
+
const circleColor = palette[(bytes[5] + 1) % palette.length];
|
|
130
|
+
shapes += `<rect x="15" y="10" width="18" height="80" fill="${barColor}"/>`;
|
|
131
|
+
shapes += `<circle cx="70" cy="50" r="15" fill="${circleColor}"/>`;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// Composition C: Square + circle.
|
|
135
|
+
const squareColor = palette[bytes[6] % palette.length];
|
|
136
|
+
const circleColor = palette[(bytes[6] + 1) % palette.length];
|
|
137
|
+
shapes += `<rect x="20" y="20" width="30" height="30" fill="${squareColor}"/>`;
|
|
138
|
+
shapes += `<circle cx="70" cy="70" r="18" fill="${circleColor}"/>`;
|
|
139
|
+
}
|
|
140
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">${shapes}</svg>`;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
@@ -20,9 +20,6 @@
|
|
|
20
20
|
* - `deleteKey` and `deleteValue` are O(d) where d is the number of associated
|
|
21
21
|
* values / keys (the degree). This is optimal because every associated pair
|
|
22
22
|
* must be touched once.
|
|
23
|
-
* - In the Relay use case a socket (value) typically has only dozens of owners
|
|
24
|
-
* (degree small), and connection closes (triggering deleteValue) are
|
|
25
|
-
* relatively infrequent, so O(d) is acceptable.
|
|
26
23
|
*
|
|
27
24
|
* Object identity:
|
|
28
25
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ManyToManyMap.d.ts","sourceRoot":"","sources":["../../src/ManyToManyMap.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"ManyToManyMap.d.ts","sourceRoot":"","sources":["../../src/ManyToManyMap.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,EAAE,CAAC;IACjC;;;OAGG;IACH,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAEnC;;;OAGG;IACH,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAEtC;;;OAGG;IACH,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAElD;;;OAGG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAElD;;;OAGG;IACH,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC;IAExD;;;OAGG;IACH,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,gBAAgB,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAEpE,kDAAkD;IAClD,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAEvC,yCAAyC;IACzC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC;IAE5B,2CAA2C;IAC3C,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAEhC,0CAA0C;IAC1C,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC;IAE/B,4CAA4C;IAC5C,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAEnC,0CAA0C;IAC1C,KAAK,EAAE,MAAM,IAAI,CAAC;IAElB,iDAAiD;IACjD,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,mDAAmD;IACnD,UAAU,EAAE,MAAM,MAAM,CAAC;IACzB,iEAAiE;IACjE,SAAS,EAAE,MAAM,MAAM,CAAC;CACzB;AAED,uCAAuC;AACvC,eAAO,MAAM,mBAAmB,GAAI,CAAC,EAAE,CAAC,OAAK,aAAa,CAAC,CAAC,EAAE,CAAC,CA2I9D,CAAC"}
|
package/dist/src/Result.d.ts
CHANGED
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
* ### Naming Convention
|
|
88
88
|
*
|
|
89
89
|
* - For values: `const user = getUser()`
|
|
90
|
-
* - For void
|
|
91
|
-
* - For
|
|
90
|
+
* - For a single void operation: `const result = foo()`
|
|
91
|
+
* - For multiple void operations: use descriptive names for all
|
|
92
92
|
*
|
|
93
93
|
* ```ts
|
|
94
94
|
* const processUser = () => {
|
|
@@ -96,13 +96,20 @@
|
|
|
96
96
|
* const user = getUser();
|
|
97
97
|
* if (!user.ok) return user;
|
|
98
98
|
*
|
|
99
|
-
* // void operation
|
|
99
|
+
* // single void operation
|
|
100
100
|
* const result = saveToDatabase(user.value);
|
|
101
101
|
* if (!result.ok) return result;
|
|
102
102
|
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
103
|
+
* return ok();
|
|
104
|
+
* };
|
|
105
|
+
*
|
|
106
|
+
* const setupDatabase = () => {
|
|
107
|
+
* // multiple void operations - use descriptive names
|
|
108
|
+
* const baseTables = createBaseTables();
|
|
109
|
+
* if (!baseTables.ok) return baseTables;
|
|
110
|
+
*
|
|
111
|
+
* const relayTables = createRelayTables();
|
|
112
|
+
* if (!relayTables.ok) return relayTables;
|
|
106
113
|
*
|
|
107
114
|
* return ok();
|
|
108
115
|
* };
|
package/dist/src/Result.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Result.d.ts","sourceRoot":"","sources":["../../src/Result.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"Result.d.ts","sourceRoot":"","sources":["../../src/Result.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgVG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;AAE1C,mCAAmC;AACnC,MAAM,WAAW,EAAE,CAAC,CAAC;IACnB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,WAAW,GAAG,CAAC,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAC5C,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEpC;;;;GAIG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAC7C,CAAC,SAAS,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAErC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;AAC/B,2DAA2D;AAC3D,wBAAgB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AAKvC;;;;;;;;;GASG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,GAAG,CAAC,CAAC,CAA2B,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,CAMvD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,CAAC,GAAG,IAC1B,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,CAAC,EAC1B,IAAI,MAAM,CAAC,EACX,UAAU,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,KAC9B,MAAM,CAAC,CAAC,EAAE,CAAC,CAMb,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,eAAO,MAAM,QAAQ,GAAU,CAAC,EAAE,CAAC,EACjC,WAAW,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,UAAU,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,KAC9B,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAIpB,CAAC"}
|
package/dist/src/Sqlite.d.ts
CHANGED
|
@@ -111,13 +111,48 @@ export interface RawSql {
|
|
|
111
111
|
sql: string;
|
|
112
112
|
}
|
|
113
113
|
export type SqlTemplateParam = SqliteValue | SqlIdentifier | RawSql;
|
|
114
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* Creates a safe SQL query using a tagged template literal.
|
|
116
|
+
*
|
|
117
|
+
* Parameters are automatically escaped and bound as SQLite values. Use
|
|
118
|
+
* `sql.identifier` for column/table names and `sql.raw` for unescaped SQL.
|
|
119
|
+
*
|
|
120
|
+
* ### Example
|
|
121
|
+
*
|
|
122
|
+
* ```ts
|
|
123
|
+
* const id = 42;
|
|
124
|
+
* const name = "Alice";
|
|
125
|
+
*
|
|
126
|
+
* const result = sqlite.exec(sql`
|
|
127
|
+
* select *
|
|
128
|
+
* from users
|
|
129
|
+
* where id = ${id} and name = ${name};
|
|
130
|
+
* `);
|
|
131
|
+
*
|
|
132
|
+
* // For identifiers
|
|
133
|
+
* const tableName = "users";
|
|
134
|
+
* sqlite.exec(sql`
|
|
135
|
+
* create table ${sql.identifier(tableName)} (
|
|
136
|
+
* "id" text primary key,
|
|
137
|
+
* "name" text not null
|
|
138
|
+
* );
|
|
139
|
+
* `);
|
|
140
|
+
*
|
|
141
|
+
* // For raw SQL (use with caution)
|
|
142
|
+
* const orderBy = "created_at desc";
|
|
143
|
+
* sqlite.exec(sql`select * from users order by ${sql.raw(orderBy)};`);
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
115
146
|
export declare const sql: {
|
|
116
147
|
(strings: TemplateStringsArray, ...parameters: Array<SqlTemplateParam>): SqliteQuery;
|
|
117
148
|
identifier(identifier: string): SqlIdentifier;
|
|
118
149
|
raw(raw: string): RawSql;
|
|
119
150
|
prepared(strings: TemplateStringsArray, ...parameters: Array<SqlTemplateParam>): SqliteQuery;
|
|
120
151
|
};
|
|
152
|
+
/**
|
|
153
|
+
* Checks if a SQL string contains mutation keywords (insert, update, delete,
|
|
154
|
+
* etc.). Results are cached for performance.
|
|
155
|
+
*/
|
|
121
156
|
export declare const isSqlMutation: Predicate<string>;
|
|
122
157
|
export interface SqliteQueryPlanRow {
|
|
123
158
|
id: number;
|
package/dist/src/Sqlite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sqlite.d.ts","sourceRoot":"","sources":["../../src/Sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"Sqlite.d.ts","sourceRoot":"","sources":["../../src/Sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAA2B,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAW,MAAM,EAAqB,MAAM,aAAa,CAAC;AACjE,OAAO,EAIL,UAAU,EAIX,MAAM,WAAW,CAAC;AACnB,OAAO,EAAoB,SAAS,EAAE,MAAM,YAAY,CAAC;AAEzD;;;GAGG;AACH,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,KAAK,gBAAgB,CAAC;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,UAAU,CAAC;CACnC;AAED,MAAM,MAAM,kBAAkB,GAAG,CAC/B,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE,mBAAmB,KAC1B,OAAO,CAAC,YAAY,CAAC,CAAC;AAE3B,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CACjD;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAC3C;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,MAAO,SAAQ,UAAU;IACxC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAC7C,KAAK,EAAE,WAAW,KACf,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAE9C;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EACzB,QAAQ,EAAE,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,KACvC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC;IAEhC,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;CACvC;AAED,kDAAkD;AAClD,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAExD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,wlBAA0C,CAAC;AACnE,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAC;AAElD,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEzC;;;;;;OAMG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAEvC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IAC/D,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,mEAAmE;AACnE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;CAC5C;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,YAAY,GACtB,MAAM,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,MAEhD,MAAM,UAAU,EAChB,UAAU,mBAAmB,KAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CA+Ff,CAAC;AAyB1B,MAAM,WAAW,kBAAkB,CAAC,CAAC,CAAE,SAAQ,UAAU;IACvD,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,SAAS,OAAO,EAC9B,KAAK,EAAE,WAAW,EAClB,aAAa,CAAC,EAAE,CAAC,KACd,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;CACpC;AAED,eAAO,MAAM,6BAA6B,GAAI,CAAC,EAC7C,SAAS,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,EAC5B,WAAW,CAAC,SAAS,EAAE,CAAC,KAAK,IAAI,KAChC,kBAAkB,CAAC,CAAC,CAuBtB,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,eAAe,CAAC;IACtB,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,aAAa,GAAG,MAAM,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,GAAG;cACL,oBAAoB,iBACd,KAAK,CAAC,gBAAgB,CAAC,GACrC,WAAW;2BAoBgB,MAAM,GAAG,aAAa;aAcpC,MAAM,GAAG,MAAM;sBAGpB,oBAAoB,iBACd,KAAK,CAAC,gBAAgB,CAAC,GACrC,WAAW;CArBb,CAAC;AA0BF;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAa3C,CAAC;AAyDF,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,sBAAsB,GAChC,MAAM,SAAS,MACf,OAAO,WAAW,KAAG,MAAM,CAAC,IAAI,EAAE,WAAW,CAiB7C,CAAC;AAoBJ;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,yGAAc,CAAC;AACzC,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAC;AAEtD;;;;GAIG;AACH,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B;;;;GAIG;AACH,eAAO,MAAM,WAAW,IAAI,CAAC"}
|
package/dist/src/Sqlite.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { createLruCache } from "./Cache.js";
|
|
1
2
|
import { createTransferableError } from "./Error.js";
|
|
2
3
|
import { err, ok, tryAsync, trySync } from "./Result.js";
|
|
3
|
-
import { Null, Number, String, Uint8Array, union } from "./Type.js";
|
|
4
|
+
import { Null, Number, PositiveInt, String, Uint8Array, union, } from "./Type.js";
|
|
4
5
|
/**
|
|
5
6
|
* A value that can be stored in Sqlite.
|
|
6
7
|
*
|
|
@@ -121,7 +122,38 @@ export const createPreparedStatementsCache = (factory, disposeFn) => {
|
|
|
121
122
|
},
|
|
122
123
|
};
|
|
123
124
|
};
|
|
124
|
-
/**
|
|
125
|
+
/**
|
|
126
|
+
* Creates a safe SQL query using a tagged template literal.
|
|
127
|
+
*
|
|
128
|
+
* Parameters are automatically escaped and bound as SQLite values. Use
|
|
129
|
+
* `sql.identifier` for column/table names and `sql.raw` for unescaped SQL.
|
|
130
|
+
*
|
|
131
|
+
* ### Example
|
|
132
|
+
*
|
|
133
|
+
* ```ts
|
|
134
|
+
* const id = 42;
|
|
135
|
+
* const name = "Alice";
|
|
136
|
+
*
|
|
137
|
+
* const result = sqlite.exec(sql`
|
|
138
|
+
* select *
|
|
139
|
+
* from users
|
|
140
|
+
* where id = ${id} and name = ${name};
|
|
141
|
+
* `);
|
|
142
|
+
*
|
|
143
|
+
* // For identifiers
|
|
144
|
+
* const tableName = "users";
|
|
145
|
+
* sqlite.exec(sql`
|
|
146
|
+
* create table ${sql.identifier(tableName)} (
|
|
147
|
+
* "id" text primary key,
|
|
148
|
+
* "name" text not null
|
|
149
|
+
* );
|
|
150
|
+
* `);
|
|
151
|
+
*
|
|
152
|
+
* // For raw SQL (use with caution)
|
|
153
|
+
* const orderBy = "created_at desc";
|
|
154
|
+
* sqlite.exec(sql`select * from users order by ${sql.raw(orderBy)};`);
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
125
157
|
export const sql = (strings, ...parameters) => {
|
|
126
158
|
let sql = "";
|
|
127
159
|
const values = [];
|
|
@@ -158,6 +190,25 @@ sql.prepared = (strings, ...parameters) => {
|
|
|
158
190
|
const query = sql(strings, ...parameters);
|
|
159
191
|
return { ...query, options: { prepare: true } };
|
|
160
192
|
};
|
|
193
|
+
/**
|
|
194
|
+
* Checks if a SQL string contains mutation keywords (insert, update, delete,
|
|
195
|
+
* etc.). Results are cached for performance.
|
|
196
|
+
*/
|
|
197
|
+
export const isSqlMutation = (sql) => {
|
|
198
|
+
/**
|
|
199
|
+
* Without cache, "insert 1_000_000" Storage test dropped from 57742
|
|
200
|
+
* inserts/sec to 34k. Regex we used was fast, but CodeQL flagged it as a
|
|
201
|
+
* potential ReDoS vulnerability, so manual comment removal was the only
|
|
202
|
+
* option. LRU cache restores performance.
|
|
203
|
+
*/
|
|
204
|
+
const cached = isSqlMutationCache.get(sql);
|
|
205
|
+
if (cached !== undefined)
|
|
206
|
+
return cached;
|
|
207
|
+
const result = isSqlMutationRegEx.test(removeSqlComments(sql));
|
|
208
|
+
isSqlMutationCache.set(sql, result);
|
|
209
|
+
return result;
|
|
210
|
+
};
|
|
211
|
+
const isSqlMutationCache = createLruCache(PositiveInt.orThrow(10_000));
|
|
161
212
|
const isSqlMutationRegEx = new RegExp(`\\b(${[
|
|
162
213
|
"alter",
|
|
163
214
|
"create",
|
|
@@ -177,6 +228,9 @@ const isSqlMutationRegEx = new RegExp(`\\b(${[
|
|
|
177
228
|
* ReDoS vulnerabilities.
|
|
178
229
|
*/
|
|
179
230
|
const removeSqlComments = (sql) => {
|
|
231
|
+
// Fast path: if there are no comments, return the original string
|
|
232
|
+
if (!sql.includes("--"))
|
|
233
|
+
return sql;
|
|
180
234
|
let result = "";
|
|
181
235
|
let i = 0;
|
|
182
236
|
while (i < sql.length) {
|
|
@@ -200,7 +254,6 @@ const removeSqlComments = (sql) => {
|
|
|
200
254
|
}
|
|
201
255
|
return result;
|
|
202
256
|
};
|
|
203
|
-
export const isSqlMutation = (sql) => isSqlMutationRegEx.test(removeSqlComments(sql));
|
|
204
257
|
export const explainSqliteQueryPlan = (deps) => (query) => {
|
|
205
258
|
const result = deps.sqlite.exec({
|
|
206
259
|
...query,
|
package/dist/src/Task.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Task.d.ts","sourceRoot":"","sources":["../../src/Task.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,MAAM,EAAW,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAA4B,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAkB,WAAW,EAAE,MAAM,WAAW,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2IG;AACH,MAAM,WAAW,IAAI,CAAC,CAAC,EAAE,CAAC;IACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IAEH,CAAC,QAAQ,SAAS,WAAW,GAAG,SAAS,GAAG,SAAS,EACnD,OAAO,CAAC,EAAE,QAAQ,GACjB,OAAO,CACR,MAAM,CAAC,CAAC,EAAE,QAAQ,SAAS;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE,GAAG,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC,CACzE,CAAC;CACH;AAED,wDAAwD;AACxD,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,uEAAuE;AACvE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"Task.d.ts","sourceRoot":"","sources":["../../src/Task.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Task.js
CHANGED
|
@@ -11,6 +11,28 @@ import { PositiveInt } from "./Type.js";
|
|
|
11
11
|
const isAbortError = (error) => typeof error === "object" &&
|
|
12
12
|
error !== null &&
|
|
13
13
|
error.type === "AbortError";
|
|
14
|
+
// For React Native
|
|
15
|
+
if (typeof AbortSignal.any !== "function") {
|
|
16
|
+
AbortSignal.any = function (signals) {
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
const onAbort = (event) => {
|
|
19
|
+
controller.abort(event.target.reason);
|
|
20
|
+
cleanup();
|
|
21
|
+
};
|
|
22
|
+
const cleanup = () => {
|
|
23
|
+
for (const s of signals)
|
|
24
|
+
s.removeEventListener("abort", onAbort);
|
|
25
|
+
};
|
|
26
|
+
for (const s of signals) {
|
|
27
|
+
if (s.aborted) {
|
|
28
|
+
controller.abort(s.reason);
|
|
29
|
+
return controller.signal;
|
|
30
|
+
}
|
|
31
|
+
s.addEventListener("abort", onAbort);
|
|
32
|
+
}
|
|
33
|
+
return controller.signal;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
14
36
|
/**
|
|
15
37
|
* Combines user signal from context with an internal signal.
|
|
16
38
|
*
|
|
@@ -80,6 +102,20 @@ export const toTask = (fn) =>
|
|
|
80
102
|
}),
|
|
81
103
|
]);
|
|
82
104
|
});
|
|
105
|
+
// For React Native
|
|
106
|
+
if (typeof AbortSignal.timeout !== "function") {
|
|
107
|
+
AbortSignal.timeout = function (ms) {
|
|
108
|
+
const controller = new AbortController();
|
|
109
|
+
const id = setTimeout(() => {
|
|
110
|
+
controller.abort();
|
|
111
|
+
}, ms);
|
|
112
|
+
// clear timeout if aborted early
|
|
113
|
+
controller.signal.addEventListener("abort", () => {
|
|
114
|
+
clearTimeout(id);
|
|
115
|
+
});
|
|
116
|
+
return controller.signal;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
83
119
|
/**
|
|
84
120
|
* Creates a {@link Task} that waits for the specified duration.
|
|
85
121
|
*
|
package/dist/src/Type.d.ts
CHANGED
|
@@ -238,7 +238,6 @@ ParentError extends TypeError = Error> extends StandardSchemaV1<Input, T> {
|
|
|
238
238
|
*
|
|
239
239
|
* - When you need to convert a validation result to a nullable value
|
|
240
240
|
* - When the error is not important and you just want the value or nothing
|
|
241
|
-
* - APIs that expect `T | null`
|
|
242
241
|
*
|
|
243
242
|
* ### Example
|
|
244
243
|
*
|
|
@@ -345,8 +344,6 @@ ParentError extends TypeError = Error> extends StandardSchemaV1<Input, T> {
|
|
|
345
344
|
*/
|
|
346
345
|
readonly ParentError: ParentError;
|
|
347
346
|
/**
|
|
348
|
-
* Error | ParentError
|
|
349
|
-
*
|
|
350
347
|
* ### Example
|
|
351
348
|
*
|
|
352
349
|
* ```ts
|
|
@@ -415,7 +412,7 @@ export type InferParent<A extends AnyType> = A extends Type<any, any, any, any,
|
|
|
415
412
|
*/
|
|
416
413
|
export type InferParentError<A extends AnyType> = A extends Type<any, any, any, any, any, infer ParentError> ? ParentError : never;
|
|
417
414
|
/**
|
|
418
|
-
* Extracts all error types
|
|
415
|
+
* Extracts all error types from a {@link Type}.
|
|
419
416
|
*
|
|
420
417
|
* @category Utilities
|
|
421
418
|
*/
|
|
@@ -1129,7 +1126,7 @@ export declare const idBytesTypeValueLength: NonNegativeInt;
|
|
|
1129
1126
|
export declare const idToIdBytes: (id: Id) => IdBytes;
|
|
1130
1127
|
export declare const idBytesToId: (idBytes: IdBytes) => Id;
|
|
1131
1128
|
/**
|
|
1132
|
-
* Positive number.
|
|
1129
|
+
* Positive number (> 0).
|
|
1133
1130
|
*
|
|
1134
1131
|
* ### Example
|
|
1135
1132
|
*
|
|
@@ -1147,7 +1144,7 @@ export interface PositiveError extends TypeError<"Positive"> {
|
|
|
1147
1144
|
}
|
|
1148
1145
|
export declare const formatPositiveError: TypeErrorFormatter<PositiveError>;
|
|
1149
1146
|
/**
|
|
1150
|
-
* Negative number.
|
|
1147
|
+
* Negative number (< 0).
|
|
1151
1148
|
*
|
|
1152
1149
|
* ### Example
|
|
1153
1150
|
*
|
|
@@ -1162,7 +1159,7 @@ export interface NegativeError extends TypeError<"Negative"> {
|
|
|
1162
1159
|
}
|
|
1163
1160
|
export declare const formatNegativeError: TypeErrorFormatter<NegativeError>;
|
|
1164
1161
|
/**
|
|
1165
|
-
* Non-positive number.
|
|
1162
|
+
* Non-positive number (≤ 0).
|
|
1166
1163
|
*
|
|
1167
1164
|
* ### Example
|
|
1168
1165
|
*
|
|
@@ -1177,7 +1174,7 @@ export interface NonPositiveError extends TypeError<"NonPositive"> {
|
|
|
1177
1174
|
}
|
|
1178
1175
|
export declare const formatNonPositiveError: TypeErrorFormatter<NonPositiveError>;
|
|
1179
1176
|
/**
|
|
1180
|
-
* Non-negative number.
|
|
1177
|
+
* Non-negative number (≥ 0).
|
|
1181
1178
|
*
|
|
1182
1179
|
* ### Example
|
|
1183
1180
|
*
|