stitchkit 0.114.0 → 0.114.2
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 +37 -0
- package/README.md +1 -1
- package/dist/browser/client-url.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/coding-tools.js +1 -1
- package/dist/entrypoints/agent-runtime/harness.js +4 -4
- package/dist/entrypoints/agent-runtime/realtime.js +2 -2
- package/dist/entrypoints/agent-runtime/sandbox.js +3 -3
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +3 -3
- package/dist/entrypoints/agent-runtime/sqlite/node.js +3 -3
- package/dist/entrypoints/agent-runtime/testing.js +4 -4
- package/dist/entrypoints/agent-runtime.js +12 -12
- package/dist/entrypoints/application/directory-inbox.js +3 -3
- package/dist/entrypoints/application.js +4 -4
- package/dist/entrypoints/cli/publish.js +1 -1
- package/dist/entrypoints/cli.js +4 -4
- package/dist/entrypoints/contract.js +2 -2
- package/dist/entrypoints/http.js +2 -2
- package/dist/entrypoints/index.js +5 -5
- package/dist/entrypoints/node.js +3 -3
- package/dist/entrypoints/observability.js +3 -3
- package/dist/entrypoints/react/keyboard/testing.d.ts +2 -0
- package/dist/entrypoints/react/keyboard/testing.d.ts.map +1 -0
- package/dist/entrypoints/react/keyboard/testing.js +127 -0
- package/dist/entrypoints/react/keyboard.d.ts +4 -2
- package/dist/entrypoints/react/keyboard.d.ts.map +1 -1
- package/dist/entrypoints/react/keyboard.js +83 -319
- package/dist/entrypoints/react.js +15 -3
- package/dist/entrypoints/realtime.js +1 -1
- package/dist/entrypoints/remote.js +1 -1
- package/dist/entrypoints/server.js +18 -18
- package/dist/entrypoints/telegram/grammy.d.ts +2 -0
- package/dist/entrypoints/telegram/grammy.d.ts.map +1 -0
- package/dist/entrypoints/telegram/grammy.js +50 -0
- package/dist/entrypoints/telegram/screens.js +1 -1
- package/dist/entrypoints/telegram.js +16 -10
- package/dist/entrypoints/testing.js +3 -3
- package/dist/entrypoints/tools/connections.js +10 -10
- package/dist/entrypoints/tools.js +19 -19
- package/dist/entrypoints/tracking.js +1 -1
- package/dist/{index-hs35ss3p.js → index-61hve0ez.js} +4 -25
- package/dist/index-6j725ez5.js +25 -0
- package/dist/{index-1csp1hwm.js → index-6p3frkv5.js} +1 -1
- package/dist/{index-erv5shjq.js → index-912sza5h.js} +1 -1
- package/dist/{index-fy4av0hq.js → index-9bwcthxw.js} +1 -1
- package/dist/{index-523tq7y4.js → index-a3462dqf.js} +1 -1
- package/dist/{index-506kd458.js → index-aw6zahv1.js} +1 -1
- package/dist/{index-tpwbct8j.js → index-dc9ere5p.js} +1 -1
- package/dist/{index-cxpcdswt.js → index-mgb7r8b8.js} +123 -63
- package/dist/{index-7fc0c2np.js → index-n3v695sb.js} +1 -1
- package/dist/index-p02zgk8x.js +351 -0
- package/dist/{index-vtann8bz.js → index-p0rf7sq9.js} +8 -8
- package/dist/{index-aykhzcnf.js → index-qj1sy4ep.js} +1 -1
- package/dist/{index-k7z3j3hr.js → index-tnxsq7cw.js} +4 -4
- package/dist/{index-c5at3ykd.js → index-tsngj2b5.js} +22 -10
- package/dist/internal/pinned-http.d.ts +27 -0
- package/dist/internal/pinned-http.d.ts.map +1 -0
- package/dist/internal/secure-fetch.d.ts +26 -6
- package/dist/internal/secure-fetch.d.ts.map +1 -1
- package/dist/react/entity-cache.d.ts +24 -2
- package/dist/react/entity-cache.d.ts.map +1 -1
- package/dist/react/keyboard/hooks.d.ts +41 -10
- package/dist/react/keyboard/hooks.d.ts.map +1 -1
- package/dist/react/keyboard/layers.d.ts +27 -8
- package/dist/react/keyboard/layers.d.ts.map +1 -1
- package/dist/react/keyboard/modality.d.ts +21 -0
- package/dist/react/keyboard/modality.d.ts.map +1 -0
- package/dist/react/keyboard/refs.d.ts +13 -0
- package/dist/react/keyboard/refs.d.ts.map +1 -0
- package/dist/react/keyboard/testing.d.ts +80 -0
- package/dist/react/keyboard/testing.d.ts.map +1 -0
- package/dist/react/keyboard/zone.d.ts +60 -10
- package/dist/react/keyboard/zone.d.ts.map +1 -1
- package/dist/telegram/budget-transformer.d.ts +35 -0
- package/dist/telegram/budget-transformer.d.ts.map +1 -0
- package/dist/telegram/outbound-budget.d.ts +4 -2
- package/dist/telegram/outbound-budget.d.ts.map +1 -1
- package/llms/react-keyboard-testing.txt +24 -0
- package/llms/react-keyboard.txt +264 -4
- package/llms/react.txt +1 -1
- package/llms/server.3.txt +31 -0
- package/llms/stitchkit.2.txt +118 -0
- package/llms/stitchkit.txt +4 -118
- package/llms/telegram-grammy.txt +22 -0
- package/llms/telegram.txt +19 -7
- package/llms-full.txt +345 -12
- package/llms.txt +7 -5
- package/package.json +9 -1
- package/dist/{index-616xh7f2.js → index-4qnzda76.js} +0 -0
- package/dist/{index-fsw1ybf3.js → index-d9hq291n.js} +3 -3
- package/dist/{index-bjcjqj46.js → index-m8a44e64.js} +3 -3
- package/dist/{index-5efrpfmj.js → index-qndsr7f0.js} +3 -3
- package/dist/{index-zktz242w.js → index-s47ac8zt.js} +3 -3
- package/dist/{index-56yx8dxp.js → index-tvtacc9a.js} +3 -3
- /package/dist/{index-v1tswj0z.js → index-txg1npmg.js} +0 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
// src/react/keyboard/layers.ts
|
|
2
|
+
var RANK = {
|
|
3
|
+
overlay: 4,
|
|
4
|
+
local: 3,
|
|
5
|
+
route: 2,
|
|
6
|
+
zone: 1,
|
|
7
|
+
global: 0
|
|
8
|
+
};
|
|
9
|
+
var KEY_FIELD_SELECTOR = [
|
|
10
|
+
"input:not([type=button],[type=submit],[type=reset],[type=checkbox],[type=image])",
|
|
11
|
+
"textarea",
|
|
12
|
+
"select",
|
|
13
|
+
"[contenteditable]:not([contenteditable=false])",
|
|
14
|
+
"[role=textbox]",
|
|
15
|
+
"[role=combobox]",
|
|
16
|
+
"[role=slider]",
|
|
17
|
+
"[role=spinbutton]",
|
|
18
|
+
"[data-local-keys]"
|
|
19
|
+
].join(",");
|
|
20
|
+
function hasClosest(target) {
|
|
21
|
+
return typeof target === "object" && target !== null && "closest" in target && typeof target.closest === "function";
|
|
22
|
+
}
|
|
23
|
+
function closestFromTarget(target, selectors) {
|
|
24
|
+
return hasClosest(target) ? target.closest(selectors) : null;
|
|
25
|
+
}
|
|
26
|
+
function isKeyFieldTarget2(target) {
|
|
27
|
+
const field = closestFromTarget(target, KEY_FIELD_SELECTOR);
|
|
28
|
+
return field !== null && field !== undefined;
|
|
29
|
+
}
|
|
30
|
+
function liveScope(entry) {
|
|
31
|
+
const read = entry.state.scope;
|
|
32
|
+
if (read === undefined)
|
|
33
|
+
return "unscoped";
|
|
34
|
+
const element = read();
|
|
35
|
+
if (element === null || !element.isConnected)
|
|
36
|
+
return null;
|
|
37
|
+
const inert = element.closest("[inert]");
|
|
38
|
+
if (inert !== null && inert !== undefined)
|
|
39
|
+
return null;
|
|
40
|
+
if (element.checkVisibility !== undefined && !element.checkVisibility())
|
|
41
|
+
return null;
|
|
42
|
+
return element;
|
|
43
|
+
}
|
|
44
|
+
function askingOrder(entries) {
|
|
45
|
+
const live = [];
|
|
46
|
+
for (const entry of entries) {
|
|
47
|
+
if (entry.state.active === false)
|
|
48
|
+
continue;
|
|
49
|
+
const scope = liveScope(entry);
|
|
50
|
+
if (scope !== null)
|
|
51
|
+
live.push({ entry, scope, depth: 0 });
|
|
52
|
+
}
|
|
53
|
+
for (const layer of live) {
|
|
54
|
+
const own = layer.scope;
|
|
55
|
+
if (own === "unscoped")
|
|
56
|
+
continue;
|
|
57
|
+
layer.depth = live.filter((other) => other !== layer && other.entry.state.kind === layer.entry.state.kind && other.scope !== "unscoped" && other.scope !== own && other.scope.contains(own)).length;
|
|
58
|
+
}
|
|
59
|
+
return live.sort((left, right) => RANK[right.entry.state.kind] - RANK[left.entry.state.kind] || right.depth - left.depth || right.entry.order - left.entry.order);
|
|
60
|
+
}
|
|
61
|
+
function createKeyLayerStack2(target) {
|
|
62
|
+
const entries = new Set;
|
|
63
|
+
let activations = 0;
|
|
64
|
+
const bubbling = (event) => {
|
|
65
|
+
dispatch(event, "bubble");
|
|
66
|
+
};
|
|
67
|
+
const capturing = (event) => {
|
|
68
|
+
dispatch(event, "capture");
|
|
69
|
+
};
|
|
70
|
+
const attached = { bubble: false, capture: false };
|
|
71
|
+
const phaseOf = (state) => state.phase ?? "bubble";
|
|
72
|
+
function sync() {
|
|
73
|
+
for (const phase of ["bubble", "capture"]) {
|
|
74
|
+
const wanted = [...entries].some((entry) => phaseOf(entry.state) === phase);
|
|
75
|
+
if (wanted === attached[phase])
|
|
76
|
+
continue;
|
|
77
|
+
attached[phase] = wanted;
|
|
78
|
+
const listener = phase === "capture" ? capturing : bubbling;
|
|
79
|
+
if (wanted)
|
|
80
|
+
target.addEventListener("keydown", listener, phase === "capture");
|
|
81
|
+
else
|
|
82
|
+
target.removeEventListener("keydown", listener, phase === "capture");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function refuseUnlessLocal(state) {
|
|
86
|
+
if (phaseOf(state) === "capture" && state.kind !== "local") {
|
|
87
|
+
throw new Error(`A ${state.kind} layer cannot listen in the capture phase; only a local layer can`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function dispatch(event, phase = "bubble") {
|
|
91
|
+
if (event.defaultPrevented || event.isComposing)
|
|
92
|
+
return false;
|
|
93
|
+
const isEscape = event.key === "Escape";
|
|
94
|
+
if (isEscape && event.repeat)
|
|
95
|
+
return false;
|
|
96
|
+
const inField = !isEscape && isKeyFieldTarget2(event.target);
|
|
97
|
+
let behindOverlay = false;
|
|
98
|
+
for (const { entry } of askingOrder(entries)) {
|
|
99
|
+
const { kind } = entry.state;
|
|
100
|
+
if (behindOverlay && kind !== "overlay")
|
|
101
|
+
break;
|
|
102
|
+
if (kind === "overlay")
|
|
103
|
+
behindOverlay = true;
|
|
104
|
+
if (phaseOf(entry.state) !== phase)
|
|
105
|
+
continue;
|
|
106
|
+
if (inField && entry.state.fields !== "include")
|
|
107
|
+
continue;
|
|
108
|
+
if (entry.state.onKey(event)) {
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
if (phase === "capture")
|
|
111
|
+
event.stopPropagation?.();
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
function add(state) {
|
|
118
|
+
refuseUnlessLocal(state);
|
|
119
|
+
const entry = { state, order: ++activations };
|
|
120
|
+
entries.add(entry);
|
|
121
|
+
sync();
|
|
122
|
+
return {
|
|
123
|
+
update(next) {
|
|
124
|
+
refuseUnlessLocal(next);
|
|
125
|
+
const reactivated = entry.state.active === false && next.active !== false;
|
|
126
|
+
const moved = phaseOf(entry.state) !== phaseOf(next);
|
|
127
|
+
entry.state = next;
|
|
128
|
+
if (reactivated)
|
|
129
|
+
entry.order = ++activations;
|
|
130
|
+
if (moved)
|
|
131
|
+
sync();
|
|
132
|
+
},
|
|
133
|
+
remove() {
|
|
134
|
+
if (!entries.delete(entry))
|
|
135
|
+
return;
|
|
136
|
+
sync();
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return { add, dispatch };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/react/keyboard/zone.ts
|
|
144
|
+
var ZONE_ATTRIBUTE = "data-keyboard-zone";
|
|
145
|
+
function nextZoneIndex2({
|
|
146
|
+
length,
|
|
147
|
+
index,
|
|
148
|
+
move,
|
|
149
|
+
loop
|
|
150
|
+
}) {
|
|
151
|
+
if (length <= 0)
|
|
152
|
+
return move === "previous" || move === "first" ? "before-start" : "after-end";
|
|
153
|
+
if (move === "first")
|
|
154
|
+
return 0;
|
|
155
|
+
if (move === "last")
|
|
156
|
+
return length - 1;
|
|
157
|
+
if (index < 0 || index >= length)
|
|
158
|
+
return move === "next" ? 0 : length - 1;
|
|
159
|
+
const target = move === "next" ? index + 1 : index - 1;
|
|
160
|
+
if (target >= 0 && target < length)
|
|
161
|
+
return target;
|
|
162
|
+
if (loop)
|
|
163
|
+
return target < 0 ? length - 1 : 0;
|
|
164
|
+
return target < 0 ? "before-start" : "after-end";
|
|
165
|
+
}
|
|
166
|
+
function zoneIntent(event, orientation) {
|
|
167
|
+
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
|
|
168
|
+
return null;
|
|
169
|
+
const vertical = orientation === "vertical";
|
|
170
|
+
switch (event.key) {
|
|
171
|
+
case (vertical ? "ArrowDown" : "ArrowRight"):
|
|
172
|
+
return { type: "move", move: "next" };
|
|
173
|
+
case (vertical ? "ArrowUp" : "ArrowLeft"):
|
|
174
|
+
return { type: "move", move: "previous" };
|
|
175
|
+
case (vertical ? "ArrowRight" : "ArrowDown"):
|
|
176
|
+
return { type: "enter" };
|
|
177
|
+
case (vertical ? "ArrowLeft" : "ArrowUp"):
|
|
178
|
+
return { type: "exit" };
|
|
179
|
+
case "Home":
|
|
180
|
+
return { type: "move", move: "first" };
|
|
181
|
+
case "End":
|
|
182
|
+
return { type: "move", move: "last" };
|
|
183
|
+
case "Enter":
|
|
184
|
+
return { type: "confirm" };
|
|
185
|
+
default:
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function resolveZoneIndex(items, value, pointed) {
|
|
190
|
+
if (pointed !== null) {
|
|
191
|
+
const index = items.indexOf(pointed);
|
|
192
|
+
if (index >= 0)
|
|
193
|
+
return index;
|
|
194
|
+
}
|
|
195
|
+
if (value !== null) {
|
|
196
|
+
const index = items.indexOf(value);
|
|
197
|
+
if (index >= 0)
|
|
198
|
+
return index;
|
|
199
|
+
}
|
|
200
|
+
return items.length > 0 ? 0 : -1;
|
|
201
|
+
}
|
|
202
|
+
function isFieldInside(target, zone) {
|
|
203
|
+
const field = closestFromTarget(target, KEY_FIELD_SELECTOR);
|
|
204
|
+
if (field === null || field === undefined || field === zone)
|
|
205
|
+
return false;
|
|
206
|
+
return closestFromTarget(field, `[${ZONE_ATTRIBUTE}]`) === zone;
|
|
207
|
+
}
|
|
208
|
+
function createNavZone2(initial) {
|
|
209
|
+
let options = initial;
|
|
210
|
+
let pointed = null;
|
|
211
|
+
let awaiting = null;
|
|
212
|
+
const elements = new Map;
|
|
213
|
+
const listeners = new Set;
|
|
214
|
+
const point = (id) => {
|
|
215
|
+
if (pointed === id)
|
|
216
|
+
return;
|
|
217
|
+
pointed = id;
|
|
218
|
+
for (const listener of listeners)
|
|
219
|
+
listener();
|
|
220
|
+
};
|
|
221
|
+
const chosenValue = () => options.value ?? null;
|
|
222
|
+
function currentIndex() {
|
|
223
|
+
return resolveZoneIndex(options.items, chosenValue(), pointed);
|
|
224
|
+
}
|
|
225
|
+
function current() {
|
|
226
|
+
return options.items[currentIndex()] ?? null;
|
|
227
|
+
}
|
|
228
|
+
function focusElement(element) {
|
|
229
|
+
element.focus({ preventScroll: true });
|
|
230
|
+
element.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
231
|
+
}
|
|
232
|
+
function focus(id) {
|
|
233
|
+
const target = id ?? current();
|
|
234
|
+
if (target === null)
|
|
235
|
+
return false;
|
|
236
|
+
point(target);
|
|
237
|
+
const element = elements.get(target);
|
|
238
|
+
if (element === undefined) {
|
|
239
|
+
awaiting = target;
|
|
240
|
+
options.onReveal?.(target);
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
awaiting = null;
|
|
244
|
+
focusElement(element);
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
const taken = (answer) => answer !== false;
|
|
248
|
+
function choose(id, cause) {
|
|
249
|
+
if (options.mode !== "focus")
|
|
250
|
+
options.onChange(id, cause);
|
|
251
|
+
}
|
|
252
|
+
function apply(intent) {
|
|
253
|
+
const { items, mode = "select", loop = false } = options;
|
|
254
|
+
const index = currentIndex();
|
|
255
|
+
const id = items[index] ?? null;
|
|
256
|
+
switch (intent.type) {
|
|
257
|
+
case "move": {
|
|
258
|
+
const landed = nextZoneIndex2({ length: items.length, index, move: intent.move, loop });
|
|
259
|
+
if (typeof landed !== "number") {
|
|
260
|
+
if (options.onBoundary === undefined)
|
|
261
|
+
return false;
|
|
262
|
+
return taken(options.onBoundary(landed === "before-start" ? "start" : "end"));
|
|
263
|
+
}
|
|
264
|
+
const next = items[landed];
|
|
265
|
+
if (next === undefined)
|
|
266
|
+
return false;
|
|
267
|
+
focus(next);
|
|
268
|
+
if (mode === "select" && next !== chosenValue())
|
|
269
|
+
choose(next, "arrow");
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
case "enter":
|
|
273
|
+
return id !== null && options.onEnter !== undefined && taken(options.onEnter(id));
|
|
274
|
+
case "exit":
|
|
275
|
+
return options.onExit !== undefined && taken(options.onExit());
|
|
276
|
+
case "confirm":
|
|
277
|
+
if (id === null || mode === "focus")
|
|
278
|
+
return false;
|
|
279
|
+
if (mode === "highlight") {
|
|
280
|
+
choose(id, "confirm");
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
return options.onEnter !== undefined && taken(options.onEnter(id));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
update(next) {
|
|
288
|
+
const changed = (next.value ?? null) !== chosenValue();
|
|
289
|
+
options = next;
|
|
290
|
+
if (changed)
|
|
291
|
+
point(null);
|
|
292
|
+
},
|
|
293
|
+
get options() {
|
|
294
|
+
return options;
|
|
295
|
+
},
|
|
296
|
+
pointedItem: () => pointed,
|
|
297
|
+
current,
|
|
298
|
+
keyDown(event, zone) {
|
|
299
|
+
if (event.defaultPrevented || event.isComposing || isFieldInside(event.target, zone)) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
if (closestFromTarget(event.target, `[${ZONE_ATTRIBUTE}]`) !== zone)
|
|
303
|
+
return false;
|
|
304
|
+
const intent = zoneIntent(event, options.orientation ?? "vertical");
|
|
305
|
+
if (intent === null || options.ignore?.(event) === true)
|
|
306
|
+
return false;
|
|
307
|
+
const landsOnCurrent = event.target === zone && intent.type === "move" && (intent.move === "next" || intent.move === "previous");
|
|
308
|
+
if (!(landsOnCurrent ? focus() : apply(intent)))
|
|
309
|
+
return false;
|
|
310
|
+
event.preventDefault();
|
|
311
|
+
return true;
|
|
312
|
+
},
|
|
313
|
+
keyFromOutside(event) {
|
|
314
|
+
if (closestFromTarget(event.target, `[${ZONE_ATTRIBUTE}]`) !== null)
|
|
315
|
+
return false;
|
|
316
|
+
const intent = zoneIntent(event, options.orientation ?? "vertical");
|
|
317
|
+
if (intent?.type !== "move" || intent.move !== "next" && intent.move !== "previous") {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
if (options.ignore?.(event) === true)
|
|
321
|
+
return false;
|
|
322
|
+
return options.outside === "move" ? apply(intent) : focus();
|
|
323
|
+
},
|
|
324
|
+
focused(id) {
|
|
325
|
+
if (id !== pointed && !options.items.includes(id))
|
|
326
|
+
return;
|
|
327
|
+
awaiting = null;
|
|
328
|
+
point(id);
|
|
329
|
+
},
|
|
330
|
+
focus,
|
|
331
|
+
setItemElement(id, element) {
|
|
332
|
+
if (element === null) {
|
|
333
|
+
elements.delete(id);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
elements.set(id, element);
|
|
337
|
+
if (id === awaiting) {
|
|
338
|
+
awaiting = null;
|
|
339
|
+
focusElement(element);
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
subscribe(listener) {
|
|
343
|
+
listeners.add(listener);
|
|
344
|
+
return () => {
|
|
345
|
+
listeners.delete(listener);
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export { KEY_FIELD_SELECTOR, isKeyFieldTarget2, createKeyLayerStack2, ZONE_ATTRIBUTE, nextZoneIndex2, resolveZoneIndex, createNavZone2 };
|
|
@@ -27,14 +27,6 @@ import {
|
|
|
27
27
|
bindContract,
|
|
28
28
|
mediaTypeEssence
|
|
29
29
|
} from "./index-cqmqyjax.js";
|
|
30
|
-
import {
|
|
31
|
-
readBoundedChunks,
|
|
32
|
-
concatChunks,
|
|
33
|
-
readBoundedBody2
|
|
34
|
-
} from "./index-5efrpfmj.js";
|
|
35
|
-
import {
|
|
36
|
-
assertPositiveSafeInteger
|
|
37
|
-
} from "./index-0s4xebbg.js";
|
|
38
30
|
import {
|
|
39
31
|
assertCorsConfig,
|
|
40
32
|
isOriginAllowed,
|
|
@@ -59,6 +51,11 @@ import {
|
|
|
59
51
|
getClientInfo2,
|
|
60
52
|
parseQueryParams
|
|
61
53
|
} from "./index-kw1ws0cs.js";
|
|
54
|
+
import {
|
|
55
|
+
readBoundedChunks,
|
|
56
|
+
concatChunks,
|
|
57
|
+
readBoundedBody2
|
|
58
|
+
} from "./index-qndsr7f0.js";
|
|
62
59
|
import {
|
|
63
60
|
abortReason,
|
|
64
61
|
untilAborted
|
|
@@ -67,6 +64,9 @@ import {
|
|
|
67
64
|
isUnsafeKey,
|
|
68
65
|
safeJsonParse
|
|
69
66
|
} from "./index-zsarb5xp.js";
|
|
67
|
+
import {
|
|
68
|
+
assertPositiveSafeInteger
|
|
69
|
+
} from "./index-0s4xebbg.js";
|
|
70
70
|
import {
|
|
71
71
|
AppError2,
|
|
72
72
|
badRequest2,
|
|
@@ -23,19 +23,19 @@ import {
|
|
|
23
23
|
createToolRunner,
|
|
24
24
|
formatToolError
|
|
25
25
|
} from "./index-htxh46ej.js";
|
|
26
|
+
import {
|
|
27
|
+
collectToolSurface
|
|
28
|
+
} from "./index-86nbfysb.js";
|
|
26
29
|
import {
|
|
27
30
|
fetchGuarded,
|
|
28
31
|
readCapped
|
|
29
|
-
} from "./index-
|
|
32
|
+
} from "./index-mgb7r8b8.js";
|
|
30
33
|
import {
|
|
31
34
|
isWithinDir2
|
|
32
35
|
} from "./index-5cc6r990.js";
|
|
33
36
|
import {
|
|
34
37
|
sleep
|
|
35
38
|
} from "./index-eemvahkc.js";
|
|
36
|
-
import {
|
|
37
|
-
collectToolSurface
|
|
38
|
-
} from "./index-86nbfysb.js";
|
|
39
39
|
import {
|
|
40
40
|
isUnsafeKey,
|
|
41
41
|
safeJsonParse
|
|
@@ -336,6 +336,8 @@ function escapeRegex(value) {
|
|
|
336
336
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
337
337
|
}
|
|
338
338
|
function decodePathSegment(value) {
|
|
339
|
+
if (!value.includes("%"))
|
|
340
|
+
return value;
|
|
339
341
|
try {
|
|
340
342
|
return decodeURIComponent(value);
|
|
341
343
|
} catch {
|
|
@@ -356,28 +358,38 @@ function createClientRouteMatcher(endpoint, contractPrefix, config) {
|
|
|
356
358
|
const wildcard = patternSegments.at(-1)?.startsWith("*") === true;
|
|
357
359
|
const fixedCount = wildcard ? patternSegments.length - 1 : patternSegments.length;
|
|
358
360
|
const markers = Object.values(markerByKey);
|
|
361
|
+
const segmentTests = patternSegments.slice(0, fixedCount).map((pattern) => compileSegmentTest(pattern, markers));
|
|
359
362
|
return (pathname) => {
|
|
360
|
-
const actualSegments = pathname.split("/").filter(Boolean)
|
|
363
|
+
const actualSegments = pathname.split("/").filter(Boolean);
|
|
361
364
|
if (wildcard ? actualSegments.length < fixedCount : actualSegments.length !== fixedCount) {
|
|
362
365
|
return false;
|
|
363
366
|
}
|
|
364
367
|
for (let index = 0;index < fixedCount; index += 1) {
|
|
365
|
-
const
|
|
368
|
+
const test = segmentTests[index];
|
|
366
369
|
const actual = actualSegments[index];
|
|
367
|
-
if (
|
|
370
|
+
if (test === undefined || actual === undefined)
|
|
368
371
|
return false;
|
|
369
|
-
if (
|
|
370
|
-
continue;
|
|
371
|
-
let source = escapeRegex(pattern);
|
|
372
|
-
for (const marker of markers) {
|
|
373
|
-
source = source.replaceAll(escapeRegex(marker), "[^/]+");
|
|
374
|
-
}
|
|
375
|
-
if (!new RegExp(`^${source}$`).test(actual))
|
|
372
|
+
if (test !== null && !test(decodePathSegment(actual)))
|
|
376
373
|
return false;
|
|
377
374
|
}
|
|
378
375
|
return true;
|
|
379
376
|
};
|
|
380
377
|
}
|
|
378
|
+
function compileSegmentTest(pattern, markers) {
|
|
379
|
+
if (pattern.startsWith(":"))
|
|
380
|
+
return null;
|
|
381
|
+
let source = escapeRegex(pattern);
|
|
382
|
+
let marked = false;
|
|
383
|
+
for (const marker of markers) {
|
|
384
|
+
const next = source.replaceAll(escapeRegex(marker), "[^/]+");
|
|
385
|
+
marked ||= next !== source;
|
|
386
|
+
source = next;
|
|
387
|
+
}
|
|
388
|
+
if (!marked)
|
|
389
|
+
return (actual) => actual === pattern;
|
|
390
|
+
const expression = new RegExp(`^${source}$`);
|
|
391
|
+
return (actual) => expression.test(actual);
|
|
392
|
+
}
|
|
381
393
|
function extractParamNames(path) {
|
|
382
394
|
const matches = path.match(/:(\w+)/g);
|
|
383
395
|
const names = matches ? matches.map((match) => match.slice(1)) : [];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One hop over a socket opened to the address the guard validated.
|
|
3
|
+
*
|
|
4
|
+
* The address is given, never looked up here: that is what makes a validated
|
|
5
|
+
* answer the one the connection uses. The `Host` header keeps the URL's host
|
|
6
|
+
* and, over TLS, the certificate is verified against it (`servername`), so a
|
|
7
|
+
* pinned connection is not a weaker one. The body is a Fetch stream over the
|
|
8
|
+
* socket, with backpressure and cancellation preserved.
|
|
9
|
+
*/
|
|
10
|
+
import type { IncomingMessage } from 'node:http';
|
|
11
|
+
/** One hop, already resolved: open the connection to exactly `address`. */
|
|
12
|
+
export type PinnedTransport = (url: URL, resolved: {
|
|
13
|
+
address: string;
|
|
14
|
+
family: 4 | 6;
|
|
15
|
+
}, signal: AbortSignal | undefined) => Promise<Response>;
|
|
16
|
+
/**
|
|
17
|
+
* One hop over a socket opened to `resolved.address`: the `Host` header keeps
|
|
18
|
+
* the URL's host and, for TLS, the certificate is verified against it
|
|
19
|
+
* (`servername`), so a pinned connection is not a weaker connection.
|
|
20
|
+
*/
|
|
21
|
+
export declare function requestPinned(url: URL, resolved: {
|
|
22
|
+
address: string;
|
|
23
|
+
family: 4 | 6;
|
|
24
|
+
}, signal: AbortSignal | undefined, headers?: Record<string, string>): Promise<Response>;
|
|
25
|
+
/** An `IncomingMessage` as a streaming Fetch response, keeping backpressure and cancellation. */
|
|
26
|
+
export declare function pinnedResponse(incoming: IncomingMessage): Response;
|
|
27
|
+
//# sourceMappingURL=pinned-http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pinned-http.d.ts","sourceRoot":"","sources":["../../src/internal/pinned-http.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAIjD,2EAA2E;AAC3E,MAAM,MAAM,eAAe,GAAG,CAC5B,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAA;CAAE,EAC5C,MAAM,EAAE,WAAW,GAAG,SAAS,KAC5B,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvB;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAA;CAAE,EAC5C,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACnC,OAAO,CAAC,QAAQ,CAAC,CAgCnB;AAED,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,QAAQ,CA6ClE"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PinnedTransport } from './pinned-http.js';
|
|
1
2
|
/** True unless the literal belongs to the globally routable unicast Internet. */
|
|
2
3
|
export declare function isPrivateIp(ip: string): boolean;
|
|
3
4
|
/**
|
|
@@ -14,13 +15,21 @@ export declare function assertPublicUrl(url: URL, signal?: AbortSignal): Promise
|
|
|
14
15
|
/**
|
|
15
16
|
* Fetch a URL with the SSRF guard enforced on the initial URL and on every
|
|
16
17
|
* redirect hop — a public host can otherwise `302` to an internal address or a
|
|
17
|
-
* non-http(s) scheme
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*
|
|
18
|
+
* non-http(s) scheme — and with the connection pinned to the address that
|
|
19
|
+
* passed the check, so a resolver cannot answer public and then connect
|
|
20
|
+
* somewhere private.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* The resolver seam: one `lookup` call per hop. Production uses `node:dns`;
|
|
24
|
+
* a test supplies a controlled answer to prove which address the socket went
|
|
25
|
+
* to, and that a second answer cannot open another one.
|
|
23
26
|
*/
|
|
27
|
+
export type GuardedDnsLookup = (host: string, options: {
|
|
28
|
+
all: true;
|
|
29
|
+
}) => Promise<Array<{
|
|
30
|
+
address: string;
|
|
31
|
+
family: number;
|
|
32
|
+
}>>;
|
|
24
33
|
export interface GuardedFetchOptions {
|
|
25
34
|
/**
|
|
26
35
|
* Deadline for producing the FINAL response headers — DNS, connects and every
|
|
@@ -36,6 +45,17 @@ export interface GuardedFetchOptions {
|
|
|
36
45
|
bodyTimeoutMs?: number;
|
|
37
46
|
/** Optional caller cancellation, combined with both deadlines. */
|
|
38
47
|
signal?: AbortSignal;
|
|
48
|
+
/**
|
|
49
|
+
* Test seam: the resolver whose answer the connection is pinned to. Default
|
|
50
|
+
* `node:dns`. It replaces the name lookup, never the address check.
|
|
51
|
+
*/
|
|
52
|
+
dns?: GuardedDnsLookup;
|
|
53
|
+
/**
|
|
54
|
+
* Test seam: how one resolved hop is opened. Default the pinned
|
|
55
|
+
* `http`/`https` request. Only the redirect tests replace it; production and
|
|
56
|
+
* the rebinding test use the default, which is where pinning happens.
|
|
57
|
+
*/
|
|
58
|
+
transport?: PinnedTransport;
|
|
39
59
|
}
|
|
40
60
|
export declare function fetchGuarded(start: URL, allowPrivate: boolean, options?: GuardedFetchOptions): Promise<Response>;
|
|
41
61
|
export interface PinnedDocumentFetchOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secure-fetch.d.ts","sourceRoot":"","sources":["../../src/internal/secure-fetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"secure-fetch.d.ts","sourceRoot":"","sources":["../../src/internal/secure-fetch.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAmDrD,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CA8D/C;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnF;AAED;;;;;;GAMG;AACH;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;IAAE,GAAG,EAAE,IAAI,CAAA;CAAE,KACnB,OAAO,CAAC,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAAC;AAQzD,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,GAAG,CAAC,EAAE,gBAAgB,CAAC;IACvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,GAAG,EACV,YAAY,EAAE,OAAO,EACrB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,QAAQ,CAAC,CAuDnB;AAqBD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,EAAE,GAAG,CAAC;CACV;AAED;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,2BAA2B;CACzC;AA+CD;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,GAAG,EACV,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,sBAAsB,CAAC,CA2CjC;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGnF"}
|
|
@@ -47,7 +47,16 @@ export interface EntityCacheTotalPolicy<TData> {
|
|
|
47
47
|
/** What to do when an unseen id makes the delta unknowable. Default `preserve`. */
|
|
48
48
|
unknown?: 'preserve' | 'invalidate';
|
|
49
49
|
}
|
|
50
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* List envelope, scoped key and explicit CRUD policies. It stays an interface,
|
|
52
|
+
* not a union of shapes: a consumer's config is often a value of this type, and
|
|
53
|
+
* a union turns `compare` and `insertCompare` into a discriminated choice the
|
|
54
|
+
* compiler cannot narrow from the fields alone.
|
|
55
|
+
*
|
|
56
|
+
* At most one of `compare` and `insertCompare` is set — a list has one answer to
|
|
57
|
+
* "what order is this?". `createEntityCacheHandlers` refuses both at creation.
|
|
58
|
+
* With neither, a create goes to the `createAt` edge and every other row stays.
|
|
59
|
+
*/
|
|
51
60
|
export interface EntityCacheListConfig<TData, TListItem> {
|
|
52
61
|
/** Static query-key prefix or an event-aware scoped key factory. */
|
|
53
62
|
key: EntityCacheKey<TData>;
|
|
@@ -55,8 +64,21 @@ export interface EntityCacheListConfig<TData, TListItem> {
|
|
|
55
64
|
createAt: 'start' | 'end';
|
|
56
65
|
/** Explicit behavior when an update's id is absent from every cached page. */
|
|
57
66
|
updateMissing: 'skip' | 'insert';
|
|
58
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* Backend-equivalent ordering of each affected logical item array: it is
|
|
69
|
+
* sorted again after every create and update. Only for an order the row
|
|
70
|
+
* itself determines; never together with `insertCompare`.
|
|
71
|
+
*/
|
|
59
72
|
compare?: (left: TListItem, right: TListItem) => number;
|
|
73
|
+
/**
|
|
74
|
+
* Where a row that is *entering* the list goes: before the first row it sorts
|
|
75
|
+
* ahead of, with ties broken by `createAt` (`'start'`: before equal rows,
|
|
76
|
+
* `'end'`: after them). On a list already in this order the result is the one
|
|
77
|
+
* `compare` gives; on a list that is not — an order the server decides with
|
|
78
|
+
* facts the row does not carry — no other row moves, and a row that is already
|
|
79
|
+
* there is replaced in place. Never together with `compare`.
|
|
80
|
+
*/
|
|
81
|
+
insertCompare?: (incoming: TListItem, existing: TListItem) => number;
|
|
60
82
|
/** Cached data envelope; no runtime shape inference is performed. */
|
|
61
83
|
shape: EntityCacheListShape;
|
|
62
84
|
/** Optional per-query filter membership. Omit for the envelope-preserving legacy path. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-cache.d.ts","sourceRoot":"","sources":["../../src/react/entity-cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAgB,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGpE,OAAO,KAAK,EAAsB,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAE7E,qEAAqE;AACrE,MAAM,MAAM,cAAc,CAAC,KAAK,IAAI,KAAK,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,qEAAqE;AACrE,MAAM,MAAM,gBAAgB,CAAC,KAAK,IAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE,+DAA+D;AAC/D,MAAM,MAAM,cAAc,CAAC,KAAK,IAAI,QAAQ,GAAG,CAAC,CAAC,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,CAAC;AAE9F,MAAM,MAAM,oBAAoB,GAC5B,OAAO,GACP,WAAW,GACX,gBAAgB,GAChB,oBAAoB,CAAC;AAEzB,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEtE,MAAM,WAAW,2BAA2B,CAAC,KAAK;IAChD,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,qBAAqB,CAAC;IACpF,6EAA6E;IAC7E,OAAO,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;CACrC;AAED,MAAM,WAAW,0BAA0B,CAAC,KAAK;IAC/C,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,qBAAqB,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB,CAAC,KAAK;IAC3C,uEAAuE;IACvE,IAAI,EAAE,WAAW,CAAC;IAClB,2FAA2F;IAC3F,KAAK,CAAC,CAAC,KAAK,EAAE,0BAA0B,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;IACrE,mFAAmF;IACnF,OAAO,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;CACrC;AAED
|
|
1
|
+
{"version":3,"file":"entity-cache.d.ts","sourceRoot":"","sources":["../../src/react/entity-cache.ts"],"names":[],"mappings":"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"}
|