@avasapp/agent-bridge 0.4.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -14
- package/dist/adapters/ably.cjs +79 -3
- package/dist/adapters/ably.d.cts +2 -1
- package/dist/adapters/async-storage.cjs +158 -0
- package/dist/adapters/async-storage.d.cts +14 -0
- package/dist/adapters/device.cjs +1110 -0
- package/dist/adapters/device.d.cts +49 -0
- package/dist/adapters/expo-router.cjs +112 -6
- package/dist/adapters/expo-router.d.cts +1 -1
- package/dist/adapters/jotai.cjs +266 -0
- package/dist/adapters/jotai.d.cts +19 -0
- package/dist/adapters/react-native-mmkv.cjs +80 -0
- package/dist/adapters/react-native-mmkv.d.cts +3 -1
- package/dist/adapters/react-native-webview.d.cts +1 -1
- package/dist/adapters/react-navigation.cjs +293 -0
- package/dist/adapters/react-navigation.d.cts +55 -0
- package/dist/adapters/redux.cjs +322 -0
- package/dist/adapters/redux.d.cts +28 -0
- package/dist/adapters/secure-store.cjs +169 -0
- package/dist/adapters/secure-store.d.cts +28 -0
- package/dist/adapters/socket-io.cjs +77 -3
- package/dist/adapters/socket-io.d.cts +2 -1
- package/dist/adapters/tanstack-query.cjs +3 -0
- package/dist/adapters/tanstack-query.d.cts +13 -4
- package/dist/adapters/zustand.cjs +193 -22
- package/dist/adapters/zustand.d.cts +11 -15
- package/dist/{chunk-TA2OLPPT.js → chunk-Y6QFU5ON.js} +477 -165
- package/dist/cli.js +2370 -103
- package/dist/client/index.cjs +441 -136
- package/dist/client/index.d.ts +67 -4
- package/dist/client/index.js +5 -3
- package/dist/expo/index.d.cts +1 -1
- package/dist/network/index.cjs +320 -73
- package/dist/network/index.d.cts +18 -3
- package/dist/noop/async-storage.cjs +26 -0
- package/dist/noop/device.cjs +26 -0
- package/dist/noop/jotai.cjs +26 -0
- package/dist/noop/react-navigation.cjs +26 -0
- package/dist/noop/realtime.cjs +6 -1
- package/dist/noop/redux.cjs +28 -0
- package/dist/noop/secure-store.cjs +26 -0
- package/dist/realtime/index.cjs +71 -4
- package/dist/realtime/index.d.cts +21 -2
- package/dist/runtime/index.cjs +838 -128
- package/dist/runtime/index.d.cts +4 -2
- package/dist/store-common-j0cHHvBr.d.cts +23 -0
- package/dist/{types-BmpykP1P.d.cts → types-qlwdcGjt.d.cts} +22 -0
- package/entries/async-storage.cjs +9 -0
- package/entries/device.cjs +9 -0
- package/entries/jotai.cjs +9 -0
- package/entries/react-navigation.cjs +9 -0
- package/entries/redux.cjs +9 -0
- package/entries/secure-store.cjs +9 -0
- package/package.json +34 -2
- package/skills/agent-bridge/SKILL.md +70 -22
- package/skills/agent-bridge/references/device.md +21 -0
- package/skills/agent-bridge/references/flows.md +19 -8
- package/skills/agent-bridge/references/large-data.md +6 -6
- package/skills/agent-bridge/references/network.md +25 -7
- package/skills/agent-bridge/references/realtime.md +5 -5
- package/skills/agent-bridge/references/restore.md +25 -7
- package/skills/agent-bridge/references/screen.md +25 -11
- package/skills/agent-bridge/references/state.md +31 -11
- package/skills/agent-bridge/references/webview.md +9 -9
- package/skills/agent-bridge/references/writing-scenarios.md +3 -3
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { T as Tools } from '../types-qlwdcGjt.cjs';
|
|
2
|
+
import { N as NamedRedact } from '../store-common-j0cHHvBr.cjs';
|
|
3
|
+
|
|
4
|
+
/** Anything with a Redux store's shape, including Redux Toolkit's configureStore. */
|
|
5
|
+
type ReduxStoreLike = {
|
|
6
|
+
getState: () => unknown;
|
|
7
|
+
dispatch(action: {
|
|
8
|
+
type: string;
|
|
9
|
+
payload?: unknown;
|
|
10
|
+
}): unknown;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type ReduxToolsOptions = {
|
|
14
|
+
/** By slice name, as `{ auth: ['token'] }` or `{ session: true }`, or a hook `(slice, path, value)`. */
|
|
15
|
+
redact?: NamedRedact;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Wrap the root reducer so the bridge can replace the state (redux.set and
|
|
19
|
+
* restore): `bridgeReducer(rootReducer)`. With redux-persist, wrap the reducer
|
|
20
|
+
* inside persistReducer: `persistReducer(config, bridgeReducer(rootReducer))`,
|
|
21
|
+
* so the saved copy follows. Release builds get the noop stub, which returns
|
|
22
|
+
* the reducer unchanged.
|
|
23
|
+
*/
|
|
24
|
+
declare function bridgeReducer<R extends (state: any, action: any) => any>(reducer: R): R;
|
|
25
|
+
/** Read, set, dispatch to and restore a Redux store. */
|
|
26
|
+
declare function reduxTools(store: ReduxStoreLike, options?: ReduxToolsOptions): Tools;
|
|
27
|
+
|
|
28
|
+
export { NamedRedact as ReduxRedact, type ReduxStoreLike, type ReduxToolsOptions, bridgeReducer, reduxTools };
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/adapters/secure-store.ts
|
|
21
|
+
var secure_store_exports = {};
|
|
22
|
+
__export(secure_store_exports, {
|
|
23
|
+
secureStoreTools: () => secureStoreTools
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(secure_store_exports);
|
|
26
|
+
|
|
27
|
+
// src/adapters/storage-undo.ts
|
|
28
|
+
function toStored(tool, key, value) {
|
|
29
|
+
if (typeof key !== "string" || !key)
|
|
30
|
+
throw new Error(`${tool} needs the key name as a non-empty string`);
|
|
31
|
+
if (value === void 0 || value === null)
|
|
32
|
+
throw new Error(`${tool} needs a value; use the delete tool to remove "${key}"`);
|
|
33
|
+
const stored = typeof value === "string" ? value : JSON.stringify(value);
|
|
34
|
+
if (typeof stored !== "string")
|
|
35
|
+
throw new Error(`${tool} cannot store that value as JSON`);
|
|
36
|
+
return stored;
|
|
37
|
+
}
|
|
38
|
+
async function change(undo, id, io, value) {
|
|
39
|
+
let entry = undo.get(id);
|
|
40
|
+
if (!entry) {
|
|
41
|
+
const original = io.read();
|
|
42
|
+
entry = { io, original, last: null };
|
|
43
|
+
undo.set(id, entry);
|
|
44
|
+
try {
|
|
45
|
+
entry.last = await original;
|
|
46
|
+
} catch (error) {
|
|
47
|
+
if (undo.get(id) === entry) undo.delete(id);
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
await entry.original;
|
|
52
|
+
}
|
|
53
|
+
if (value === null) await io.remove();
|
|
54
|
+
else await io.write(value);
|
|
55
|
+
entry.last = value;
|
|
56
|
+
}
|
|
57
|
+
async function restore(undo, label) {
|
|
58
|
+
let restored = 0;
|
|
59
|
+
const skipped = [];
|
|
60
|
+
const failed = [];
|
|
61
|
+
for (const [id, entry] of [...undo]) {
|
|
62
|
+
try {
|
|
63
|
+
let original;
|
|
64
|
+
try {
|
|
65
|
+
original = await entry.original;
|
|
66
|
+
} catch {
|
|
67
|
+
undo.delete(id);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (await entry.io.read() !== entry.last) {
|
|
71
|
+
undo.delete(id);
|
|
72
|
+
skipped.push(label(id));
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (original === null) await entry.io.remove();
|
|
76
|
+
else await entry.io.write(original);
|
|
77
|
+
undo.delete(id);
|
|
78
|
+
restored += 1;
|
|
79
|
+
} catch {
|
|
80
|
+
failed.push(label(id));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return { restored, skipped, failed };
|
|
84
|
+
}
|
|
85
|
+
function describeRestore(r, what) {
|
|
86
|
+
if (r.failed.length)
|
|
87
|
+
throw new Error(
|
|
88
|
+
`Restored ${r.restored}, could not restore: ${r.failed.join(", ")}. ${what} stay pending; run it again.`
|
|
89
|
+
);
|
|
90
|
+
return r.skipped.length ? { restored: r.restored, skipped: r.skipped } : r.restored;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/adapters/secure-store.ts
|
|
94
|
+
var originals = /* @__PURE__ */ new WeakMap();
|
|
95
|
+
var hide = (value) => value === null ? null : `[redacted, ${value.length} chars]`;
|
|
96
|
+
function secureStoreTools(store, keys = [], options) {
|
|
97
|
+
let undo = originals.get(store);
|
|
98
|
+
if (!undo) originals.set(store, undo = /* @__PURE__ */ new Map());
|
|
99
|
+
const pending = undo;
|
|
100
|
+
const optionsFor = (key) => typeof options === "function" ? options(key) : options;
|
|
101
|
+
const guarded = (key) => optionsFor(key)?.requireAuthentication === true;
|
|
102
|
+
const idOf = (key) => {
|
|
103
|
+
const o = optionsFor(key);
|
|
104
|
+
return JSON.stringify([o?.keychainService ?? "", o?.accessGroup ?? "", key]);
|
|
105
|
+
};
|
|
106
|
+
const apply = async (key, value) => {
|
|
107
|
+
const o = optionsFor(key);
|
|
108
|
+
const io = {
|
|
109
|
+
read: () => store.getItemAsync(key, o),
|
|
110
|
+
write: (v) => store.setItemAsync(key, v, o),
|
|
111
|
+
remove: () => store.deleteItemAsync(key, o)
|
|
112
|
+
};
|
|
113
|
+
try {
|
|
114
|
+
await change(pending, idOf(key), io, value);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
if (guarded(key) && !pending.has(idOf(key)))
|
|
117
|
+
throw new Error(
|
|
118
|
+
`Could not read the protected key "${key}" to save its old value (${error instanceof Error ? error.message : String(error)}); nothing was changed.`
|
|
119
|
+
);
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
return {
|
|
124
|
+
"secureStore.list": {
|
|
125
|
+
description: "The keys the app passed to secureStoreTools, each with whether it is set and its length. Keys the app protects with requireAuthentication are not read (they would prompt): they show {authRequired:true}. SecureStore cannot list keys itself: for any other key, call secureStore.get with its name. Values are not shown.",
|
|
126
|
+
run: async () => Object.fromEntries(
|
|
127
|
+
await Promise.all(
|
|
128
|
+
keys.map(async (k) => {
|
|
129
|
+
if (guarded(k)) return [k, { authRequired: true }];
|
|
130
|
+
const v = await store.getItemAsync(k, optionsFor(k));
|
|
131
|
+
return [k, v === null ? { set: false } : { set: true, length: v.length }];
|
|
132
|
+
})
|
|
133
|
+
)
|
|
134
|
+
)
|
|
135
|
+
},
|
|
136
|
+
"secureStore.get": {
|
|
137
|
+
description: "A key's value, redacted to its length unless {full:true}; null when missing. Pass the key name: SecureStore has no key listing.",
|
|
138
|
+
run: async (key, getOptions) => {
|
|
139
|
+
const value = await store.getItemAsync(key, optionsFor(key));
|
|
140
|
+
return getOptions?.full ? value : hide(value);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"secureStore.set": {
|
|
144
|
+
description: "Set a value (a string; other values are stored as JSON). The old value is kept in memory for secureStore.restore.",
|
|
145
|
+
run: async (key, value) => {
|
|
146
|
+
await apply(key, toStored("secureStore.set", key, value));
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"secureStore.delete": {
|
|
151
|
+
description: "Delete a key.",
|
|
152
|
+
run: async (key) => {
|
|
153
|
+
if (typeof key !== "string" || !key)
|
|
154
|
+
throw new Error("secureStore.delete needs the key name as a non-empty string");
|
|
155
|
+
await apply(key, null);
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
"secureStore.restore": {
|
|
160
|
+
// Always a plain true: bridge.pending must not show key names or values.
|
|
161
|
+
pending: () => pending.size > 0,
|
|
162
|
+
description: "Undo the agent: put back keys changed with secureStore.set or secureStore.delete (with the same options), deleting ones that did not exist. Returns how many; a key the app has written since is left alone and returned in {skipped}. Lost when the JS reloads: restore before app.reload.",
|
|
163
|
+
run: async () => describeRestore(
|
|
164
|
+
await restore(pending, (id) => JSON.parse(id)[2]),
|
|
165
|
+
"Those keys"
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { T as Tools } from '../types-qlwdcGjt.cjs';
|
|
2
|
+
|
|
3
|
+
/** The options expo-secure-store takes on every call. */
|
|
4
|
+
type SecureStoreOptions = {
|
|
5
|
+
keychainService?: string;
|
|
6
|
+
keychainAccessible?: number;
|
|
7
|
+
requireAuthentication?: boolean;
|
|
8
|
+
authenticationPrompt?: string;
|
|
9
|
+
accessGroup?: string;
|
|
10
|
+
};
|
|
11
|
+
/** The expo-secure-store surface this adapter uses (`import * as SecureStore`). */
|
|
12
|
+
type SecureStoreLike = {
|
|
13
|
+
getItemAsync: (key: string, options?: SecureStoreOptions) => Promise<string | null>;
|
|
14
|
+
setItemAsync: (key: string, value: string, options?: SecureStoreOptions) => Promise<void>;
|
|
15
|
+
deleteItemAsync: (key: string, options?: SecureStoreOptions) => Promise<void>;
|
|
16
|
+
};
|
|
17
|
+
/** One options object for every key, or a function that picks them per key. */
|
|
18
|
+
type SecureStoreOptionsFor = SecureStoreOptions | ((key: string) => SecureStoreOptions | undefined);
|
|
19
|
+
/**
|
|
20
|
+
* Read and write expo-secure-store. Its values are secrets, so reads are
|
|
21
|
+
* redacted unless {full:true}. It cannot list keys: pass the ones the app
|
|
22
|
+
* knows as `keys` to let `secureStore.list` show them. `options` must match
|
|
23
|
+
* what the app passes (a `keychainService` picks a different item), as one
|
|
24
|
+
* object or a function of the key.
|
|
25
|
+
*/
|
|
26
|
+
declare function secureStoreTools(store: SecureStoreLike, keys?: readonly string[], options?: SecureStoreOptionsFor): Tools;
|
|
27
|
+
|
|
28
|
+
export { type SecureStoreLike, type SecureStoreOptions, type SecureStoreOptionsFor, secureStoreTools };
|
|
@@ -72,6 +72,21 @@ function tapListeners(tap, target, options) {
|
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
+
function tapOutgoing(tap, target, options) {
|
|
76
|
+
const methods = target;
|
|
77
|
+
for (const name of list(options.methods)) {
|
|
78
|
+
const send = methods[name];
|
|
79
|
+
if (typeof send !== "function") continue;
|
|
80
|
+
methods[name] = function(...args) {
|
|
81
|
+
try {
|
|
82
|
+
const channel = options.skip?.(this) ? void 0 : options.channel(args);
|
|
83
|
+
if (channel !== void 0) tap.sent(channel, options.describe(args));
|
|
84
|
+
} catch {
|
|
85
|
+
}
|
|
86
|
+
return send.apply(this, args);
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
75
90
|
function fakeableConnection(target, options) {
|
|
76
91
|
const methods = target;
|
|
77
92
|
const events = methods?.[options.events];
|
|
@@ -116,6 +131,46 @@ function realtimeAdapter(install) {
|
|
|
116
131
|
};
|
|
117
132
|
}
|
|
118
133
|
|
|
134
|
+
// src/network/headers.ts
|
|
135
|
+
var SECRET = /auth|cookie|token|secret|session|password|passwd|signature|api-?key|credential|jwt/i;
|
|
136
|
+
|
|
137
|
+
// src/realtime/snapshot.ts
|
|
138
|
+
var MAX_STRING = 2e3;
|
|
139
|
+
var MAX_ITEMS = 50;
|
|
140
|
+
var MAX_DEPTH = 5;
|
|
141
|
+
var isPlain = (v) => {
|
|
142
|
+
const proto = Object.getPrototypeOf(v);
|
|
143
|
+
return proto === Object.prototype || proto === null;
|
|
144
|
+
};
|
|
145
|
+
function snapshot(value, depth = 0) {
|
|
146
|
+
if (typeof value === "string")
|
|
147
|
+
return value.length > MAX_STRING ? `${value.slice(0, MAX_STRING)}\u2026 (+${value.length - MAX_STRING} chars)` : value;
|
|
148
|
+
if (typeof value === "function") return "[function]";
|
|
149
|
+
if (!value || typeof value !== "object") return value;
|
|
150
|
+
if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer)
|
|
151
|
+
return `[${value.constructor.name} ${value.byteLength} bytes]`;
|
|
152
|
+
if (depth >= MAX_DEPTH) return "[\u2026]";
|
|
153
|
+
if (Array.isArray(value)) {
|
|
154
|
+
const items = value.slice(0, MAX_ITEMS).map((v) => snapshot(v, depth + 1));
|
|
155
|
+
if (value.length > MAX_ITEMS) items.push(`\u2026 (+${value.length - MAX_ITEMS} items)`);
|
|
156
|
+
return items;
|
|
157
|
+
}
|
|
158
|
+
if (value instanceof Date) return value.toISOString();
|
|
159
|
+
if (!isPlain(value)) return `[${value.constructor?.name ?? "object"}]`;
|
|
160
|
+
const out = {};
|
|
161
|
+
for (const key of Object.keys(value).slice(0, MAX_ITEMS))
|
|
162
|
+
out[key] = snapshot(value[key], depth + 1);
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
function redact(value, depth = 0) {
|
|
166
|
+
if (!value || typeof value !== "object" || depth >= MAX_DEPTH + 1) return value;
|
|
167
|
+
if (Array.isArray(value)) return value.map((v) => redact(v, depth + 1));
|
|
168
|
+
const out = {};
|
|
169
|
+
for (const [key, v] of Object.entries(value))
|
|
170
|
+
out[key] = SECRET.test(key) ? "[redacted]" : redact(v, depth + 1);
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
173
|
+
|
|
119
174
|
// src/realtime/tap.ts
|
|
120
175
|
var LOG_SIZE = 50;
|
|
121
176
|
var ALL = "*";
|
|
@@ -159,6 +214,17 @@ function createRealtimeTap(options = {}) {
|
|
|
159
214
|
}
|
|
160
215
|
if (!dropped) entry.deliver(message, ...rest);
|
|
161
216
|
}
|
|
217
|
+
const sent = (channel, summary) => {
|
|
218
|
+
log.push({
|
|
219
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
220
|
+
channel,
|
|
221
|
+
...summary,
|
|
222
|
+
..."data" in summary && { data: snapshot(summary.data) },
|
|
223
|
+
injected: false,
|
|
224
|
+
sent: true
|
|
225
|
+
});
|
|
226
|
+
if (log.length > LOG_SIZE) log.splice(0, log.length - LOG_SIZE);
|
|
227
|
+
};
|
|
162
228
|
const wrap = (channel, listener, wrapOptions = {}) => {
|
|
163
229
|
const entry = {
|
|
164
230
|
deliver: listener,
|
|
@@ -208,11 +274,11 @@ function createRealtimeTap(options = {}) {
|
|
|
208
274
|
}))
|
|
209
275
|
},
|
|
210
276
|
[`${ns}.log`]: {
|
|
211
|
-
description: `Recent messages, real and
|
|
277
|
+
description: `Recent messages, real, injected, and ones the app sent (sent: true) (socket.emit, Ably publish), newest first (last ${LOG_SIZE}). Filter: { channel?, event?, limit?, full? }; clear: true empties the log after reading. Sent messages are copied and cut, and keys like token, password or authorization show [redacted] unless full: true.`,
|
|
212
278
|
run: (filter = {}) => {
|
|
213
279
|
const entries = log.filter(
|
|
214
280
|
(e) => (!filter.channel || e.channel === filter.channel) && (!filter.event || e.event === filter.event)
|
|
215
|
-
).reverse().slice(0, filter.limit ?? 20);
|
|
281
|
+
).reverse().slice(0, filter.limit ?? 20).map((e) => e.sent && !filter.full && "data" in e ? { ...e, data: redact(e.data) } : e);
|
|
216
282
|
if (filter.clear) log.length = 0;
|
|
217
283
|
return entries;
|
|
218
284
|
}
|
|
@@ -273,7 +339,7 @@ function createRealtimeTap(options = {}) {
|
|
|
273
339
|
return { state: faked ?? connection.state(), real: connection.state(), faked: faked !== null };
|
|
274
340
|
}
|
|
275
341
|
};
|
|
276
|
-
return { wrap, tools };
|
|
342
|
+
return { wrap, sent, tools };
|
|
277
343
|
}
|
|
278
344
|
|
|
279
345
|
// src/adapters/socket-io.ts
|
|
@@ -314,6 +380,14 @@ var socketIoTools = realtimeAdapter(
|
|
|
314
380
|
channel: ([event]) => typeof event === "string" && !RESERVED.has(event) ? event : void 0,
|
|
315
381
|
message: "args"
|
|
316
382
|
});
|
|
383
|
+
tapOutgoing(tap, socket, {
|
|
384
|
+
methods: "emit",
|
|
385
|
+
channel: ([event]) => typeof event === "string" && !RESERVED.has(event) ? event : void 0,
|
|
386
|
+
// socket.io's retry queue calls emit again for the same message.
|
|
387
|
+
skip: (target) => Boolean(target.flags?.fromQueue),
|
|
388
|
+
// Always the argument list, so emit('x', [1, 2]) and emit('x', 1, 2) differ.
|
|
389
|
+
describe: ([, ...args]) => ({ data: args.filter((a) => typeof a !== "function") })
|
|
390
|
+
});
|
|
317
391
|
return tap;
|
|
318
392
|
}
|
|
319
393
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { T as Tools } from '../types-
|
|
1
|
+
import { T as Tools } from '../types-qlwdcGjt.cjs';
|
|
2
2
|
|
|
3
3
|
type Listener = (...args: any[]) => void;
|
|
4
4
|
/** A socket.io client socket (`io(url)`), typed structurally. */
|
|
@@ -6,6 +6,7 @@ type SocketLike = {
|
|
|
6
6
|
on(event: string, listener: Listener): unknown;
|
|
7
7
|
off(event?: string, listener?: Listener): unknown;
|
|
8
8
|
connected?: boolean;
|
|
9
|
+
emit?(event: string, ...args: never[]): unknown;
|
|
9
10
|
};
|
|
10
11
|
type SocketIoToolsOptions = {
|
|
11
12
|
/** Tool name prefix. Defaults to "realtime". */
|
|
@@ -222,6 +222,9 @@ function atPath(value, path) {
|
|
|
222
222
|
return current;
|
|
223
223
|
}
|
|
224
224
|
function queryTools(queryClient) {
|
|
225
|
+
return toolsFor(queryClient);
|
|
226
|
+
}
|
|
227
|
+
function toolsFor(queryClient) {
|
|
225
228
|
const cache = queryClient.getQueryCache();
|
|
226
229
|
const state = pinStateFor(queryClient);
|
|
227
230
|
const { pins, seeded } = state;
|
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { T as Tools } from '../types-BmpykP1P.cjs';
|
|
1
|
+
import { T as Tools } from '../types-qlwdcGjt.cjs';
|
|
3
2
|
|
|
3
|
+
/** A TanStack Query `QueryClient`, e.g. from `useQueryClient()`. */
|
|
4
|
+
type QueryClientLike = {
|
|
5
|
+
getQueryCache(): object;
|
|
6
|
+
getQueryData(queryKey: readonly unknown[]): unknown;
|
|
7
|
+
setQueryData(queryKey: readonly unknown[], updater: unknown): unknown;
|
|
8
|
+
invalidateQueries(filters?: object): Promise<void>;
|
|
9
|
+
refetchQueries(filters?: object): Promise<void>;
|
|
10
|
+
resetQueries(filters?: object): Promise<void>;
|
|
11
|
+
getDefaultOptions(): object;
|
|
12
|
+
};
|
|
4
13
|
/**
|
|
5
14
|
* Read and seed the TanStack Query cache. `query.pin` keeps a seed in place:
|
|
6
15
|
* when a refetch lands with real data, the seed is put back until unpinned.
|
|
7
16
|
*/
|
|
8
|
-
declare function queryTools(queryClient:
|
|
17
|
+
declare function queryTools(queryClient: QueryClientLike): Tools;
|
|
9
18
|
|
|
10
|
-
export { queryTools };
|
|
19
|
+
export { type QueryClientLike, queryTools };
|