@ansight/capacitor 1.0.2-preview.6
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/AnsightCapacitor.podspec +14 -0
- package/LICENSE +200 -0
- package/Package.swift +38 -0
- package/README.md +139 -0
- package/android/build.gradle +52 -0
- package/android/settings.gradle +20 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/kotlin/ai/ansight/capacitor/AnsightCapacitorPlugin.kt +1131 -0
- package/dist/esm/definitions.d.ts +521 -0
- package/dist/esm/definitions.d.ts.map +1 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/dom.d.ts +9 -0
- package/dist/esm/dom.d.ts.map +1 -0
- package/dist/esm/dom.js +237 -0
- package/dist/esm/dom.js.map +1 -0
- package/dist/esm/index.d.ts +156 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +576 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/options.d.ts +57 -0
- package/dist/esm/options.d.ts.map +1 -0
- package/dist/esm/options.js +294 -0
- package/dist/esm/options.js.map +1 -0
- package/dist/esm/standalone.d.ts +5 -0
- package/dist/esm/standalone.d.ts.map +1 -0
- package/dist/esm/standalone.js +18 -0
- package/dist/esm/standalone.js.map +1 -0
- package/dist/plugin.cjs.js +1176 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +1179 -0
- package/dist/plugin.js.map +1 -0
- package/dist/standalone.js +1764 -0
- package/dist/standalone.js.map +1 -0
- package/ios/Sources/AnsightCapacitorPlugin/AnsightCapacitorPlugin.swift +1144 -0
- package/package.json +81 -0
|
@@ -0,0 +1,1764 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/*! Capacitor: https://capacitorjs.com/ - MIT License */
|
|
5
|
+
var ExceptionCode;
|
|
6
|
+
(function (ExceptionCode) {
|
|
7
|
+
/**
|
|
8
|
+
* API is not implemented.
|
|
9
|
+
*
|
|
10
|
+
* This usually means the API can't be used because it is not implemented for
|
|
11
|
+
* the current platform.
|
|
12
|
+
*/
|
|
13
|
+
ExceptionCode["Unimplemented"] = "UNIMPLEMENTED";
|
|
14
|
+
/**
|
|
15
|
+
* API is not available.
|
|
16
|
+
*
|
|
17
|
+
* This means the API can't be used right now because:
|
|
18
|
+
* - it is currently missing a prerequisite, such as network connectivity
|
|
19
|
+
* - it requires a particular platform or browser version
|
|
20
|
+
*/
|
|
21
|
+
ExceptionCode["Unavailable"] = "UNAVAILABLE";
|
|
22
|
+
})(ExceptionCode || (ExceptionCode = {}));
|
|
23
|
+
class CapacitorException extends Error {
|
|
24
|
+
constructor(message, code, data) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.message = message;
|
|
27
|
+
this.code = code;
|
|
28
|
+
this.data = data;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const getPlatformId = (win) => {
|
|
32
|
+
var _a, _b;
|
|
33
|
+
if (win === null || win === void 0 ? void 0 : win.androidBridge) {
|
|
34
|
+
return 'android';
|
|
35
|
+
}
|
|
36
|
+
else if ((_b = (_a = win === null || win === void 0 ? void 0 : win.webkit) === null || _a === void 0 ? void 0 : _a.messageHandlers) === null || _b === void 0 ? void 0 : _b.bridge) {
|
|
37
|
+
return 'ios';
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
return 'web';
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const createCapacitor = (win) => {
|
|
45
|
+
const capCustomPlatform = win.CapacitorCustomPlatform || null;
|
|
46
|
+
const cap = win.Capacitor || {};
|
|
47
|
+
const Plugins = (cap.Plugins = cap.Plugins || {});
|
|
48
|
+
const getPlatform = () => {
|
|
49
|
+
return capCustomPlatform !== null ? capCustomPlatform.name : getPlatformId(win);
|
|
50
|
+
};
|
|
51
|
+
const isNativePlatform = () => getPlatform() !== 'web';
|
|
52
|
+
const isPluginAvailable = (pluginName) => {
|
|
53
|
+
const plugin = registeredPlugins.get(pluginName);
|
|
54
|
+
if (plugin === null || plugin === void 0 ? void 0 : plugin.platforms.has(getPlatform())) {
|
|
55
|
+
// JS implementation available for the current platform.
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (getPluginHeader(pluginName)) {
|
|
59
|
+
// Native implementation available.
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
};
|
|
64
|
+
const getPluginHeader = (pluginName) => { var _a; return (_a = cap.PluginHeaders) === null || _a === void 0 ? void 0 : _a.find((h) => h.name === pluginName); };
|
|
65
|
+
const handleError = (err) => win.console.error(err);
|
|
66
|
+
const registeredPlugins = new Map();
|
|
67
|
+
const registerPlugin = (pluginName, jsImplementations = {}) => {
|
|
68
|
+
const registeredPlugin = registeredPlugins.get(pluginName);
|
|
69
|
+
if (registeredPlugin) {
|
|
70
|
+
console.warn(`Capacitor plugin "${pluginName}" already registered. Cannot register plugins twice.`);
|
|
71
|
+
return registeredPlugin.proxy;
|
|
72
|
+
}
|
|
73
|
+
const platform = getPlatform();
|
|
74
|
+
const pluginHeader = getPluginHeader(pluginName);
|
|
75
|
+
let jsImplementation;
|
|
76
|
+
const loadPluginImplementation = async () => {
|
|
77
|
+
if (!jsImplementation && platform in jsImplementations) {
|
|
78
|
+
jsImplementation =
|
|
79
|
+
typeof jsImplementations[platform] === 'function'
|
|
80
|
+
? (jsImplementation = await jsImplementations[platform]())
|
|
81
|
+
: (jsImplementation = jsImplementations[platform]);
|
|
82
|
+
}
|
|
83
|
+
else if (capCustomPlatform !== null && !jsImplementation && 'web' in jsImplementations) {
|
|
84
|
+
jsImplementation =
|
|
85
|
+
typeof jsImplementations['web'] === 'function'
|
|
86
|
+
? (jsImplementation = await jsImplementations['web']())
|
|
87
|
+
: (jsImplementation = jsImplementations['web']);
|
|
88
|
+
}
|
|
89
|
+
return jsImplementation;
|
|
90
|
+
};
|
|
91
|
+
const createPluginMethod = (impl, prop) => {
|
|
92
|
+
var _a, _b;
|
|
93
|
+
if (pluginHeader) {
|
|
94
|
+
const methodHeader = pluginHeader === null || pluginHeader === void 0 ? void 0 : pluginHeader.methods.find((m) => prop === m.name);
|
|
95
|
+
if (methodHeader) {
|
|
96
|
+
if (methodHeader.rtype === 'promise') {
|
|
97
|
+
return (options) => cap.nativePromise(pluginName, prop.toString(), options);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return (options, callback) => cap.nativeCallback(pluginName, prop.toString(), options, callback);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (impl) {
|
|
104
|
+
return (_a = impl[prop]) === null || _a === void 0 ? void 0 : _a.bind(impl);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else if (impl) {
|
|
108
|
+
return (_b = impl[prop]) === null || _b === void 0 ? void 0 : _b.bind(impl);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
throw new CapacitorException(`"${pluginName}" plugin is not implemented on ${platform}`, ExceptionCode.Unimplemented);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const createPluginMethodWrapper = (prop) => {
|
|
115
|
+
let remove;
|
|
116
|
+
const wrapper = (...args) => {
|
|
117
|
+
const p = loadPluginImplementation().then((impl) => {
|
|
118
|
+
const fn = createPluginMethod(impl, prop);
|
|
119
|
+
if (fn) {
|
|
120
|
+
const p = fn(...args);
|
|
121
|
+
remove = p === null || p === void 0 ? void 0 : p.remove;
|
|
122
|
+
return p;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
throw new CapacitorException(`"${pluginName}.${prop}()" is not implemented on ${platform}`, ExceptionCode.Unimplemented);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
if (prop === 'addListener') {
|
|
129
|
+
p.remove = async () => remove();
|
|
130
|
+
}
|
|
131
|
+
return p;
|
|
132
|
+
};
|
|
133
|
+
// Some flair ✨
|
|
134
|
+
wrapper.toString = () => `${prop.toString()}() { [capacitor code] }`;
|
|
135
|
+
Object.defineProperty(wrapper, 'name', {
|
|
136
|
+
value: prop,
|
|
137
|
+
writable: false,
|
|
138
|
+
configurable: false,
|
|
139
|
+
});
|
|
140
|
+
return wrapper;
|
|
141
|
+
};
|
|
142
|
+
const addListener = createPluginMethodWrapper('addListener');
|
|
143
|
+
const removeListener = createPluginMethodWrapper('removeListener');
|
|
144
|
+
const addListenerNative = (eventName, callback) => {
|
|
145
|
+
const call = addListener({ eventName }, callback);
|
|
146
|
+
const remove = async () => {
|
|
147
|
+
const callbackId = await call;
|
|
148
|
+
removeListener({
|
|
149
|
+
eventName,
|
|
150
|
+
callbackId,
|
|
151
|
+
}, callback);
|
|
152
|
+
};
|
|
153
|
+
const p = new Promise((resolve) => call.then(() => resolve({ remove })));
|
|
154
|
+
p.remove = async () => {
|
|
155
|
+
console.warn(`Using addListener() without 'await' is deprecated.`);
|
|
156
|
+
await remove();
|
|
157
|
+
};
|
|
158
|
+
return p;
|
|
159
|
+
};
|
|
160
|
+
const proxy = new Proxy({}, {
|
|
161
|
+
get(_, prop) {
|
|
162
|
+
switch (prop) {
|
|
163
|
+
// https://github.com/facebook/react/issues/20030
|
|
164
|
+
case '$$typeof':
|
|
165
|
+
return undefined;
|
|
166
|
+
case 'toJSON':
|
|
167
|
+
return () => ({});
|
|
168
|
+
case 'addListener':
|
|
169
|
+
return pluginHeader ? addListenerNative : addListener;
|
|
170
|
+
case 'removeListener':
|
|
171
|
+
return removeListener;
|
|
172
|
+
default:
|
|
173
|
+
return createPluginMethodWrapper(prop);
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
Plugins[pluginName] = proxy;
|
|
178
|
+
registeredPlugins.set(pluginName, {
|
|
179
|
+
name: pluginName,
|
|
180
|
+
proxy,
|
|
181
|
+
platforms: new Set([...Object.keys(jsImplementations), ...(pluginHeader ? [platform] : [])]),
|
|
182
|
+
});
|
|
183
|
+
return proxy;
|
|
184
|
+
};
|
|
185
|
+
// Add in convertFileSrc for web, it will already be available in native context
|
|
186
|
+
if (!cap.convertFileSrc) {
|
|
187
|
+
cap.convertFileSrc = (filePath) => filePath;
|
|
188
|
+
}
|
|
189
|
+
cap.getPlatform = getPlatform;
|
|
190
|
+
cap.handleError = handleError;
|
|
191
|
+
cap.isNativePlatform = isNativePlatform;
|
|
192
|
+
cap.isPluginAvailable = isPluginAvailable;
|
|
193
|
+
cap.registerPlugin = registerPlugin;
|
|
194
|
+
cap.Exception = CapacitorException;
|
|
195
|
+
cap.DEBUG = !!cap.DEBUG;
|
|
196
|
+
cap.isLoggingEnabled = !!cap.isLoggingEnabled;
|
|
197
|
+
return cap;
|
|
198
|
+
};
|
|
199
|
+
const initCapacitorGlobal = (win) => (win.Capacitor = createCapacitor(win));
|
|
200
|
+
|
|
201
|
+
const Capacitor = /*#__PURE__*/ initCapacitorGlobal(typeof globalThis !== 'undefined'
|
|
202
|
+
? globalThis
|
|
203
|
+
: typeof self !== 'undefined'
|
|
204
|
+
? self
|
|
205
|
+
: typeof window !== 'undefined'
|
|
206
|
+
? window
|
|
207
|
+
: typeof global !== 'undefined'
|
|
208
|
+
? global
|
|
209
|
+
: {});
|
|
210
|
+
const registerPlugin = Capacitor.registerPlugin;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Base class web plugins should extend.
|
|
214
|
+
*/
|
|
215
|
+
class WebPlugin {
|
|
216
|
+
constructor() {
|
|
217
|
+
this.listeners = {};
|
|
218
|
+
this.retainedEventArguments = {};
|
|
219
|
+
this.windowListeners = {};
|
|
220
|
+
}
|
|
221
|
+
addListener(eventName, listenerFunc) {
|
|
222
|
+
let firstListener = false;
|
|
223
|
+
const listeners = this.listeners[eventName];
|
|
224
|
+
if (!listeners) {
|
|
225
|
+
this.listeners[eventName] = [];
|
|
226
|
+
firstListener = true;
|
|
227
|
+
}
|
|
228
|
+
this.listeners[eventName].push(listenerFunc);
|
|
229
|
+
// If we haven't added a window listener for this event and it requires one,
|
|
230
|
+
// go ahead and add it
|
|
231
|
+
const windowListener = this.windowListeners[eventName];
|
|
232
|
+
if (windowListener && !windowListener.registered) {
|
|
233
|
+
this.addWindowListener(windowListener);
|
|
234
|
+
}
|
|
235
|
+
if (firstListener) {
|
|
236
|
+
this.sendRetainedArgumentsForEvent(eventName);
|
|
237
|
+
}
|
|
238
|
+
const remove = async () => this.removeListener(eventName, listenerFunc);
|
|
239
|
+
const p = Promise.resolve({ remove });
|
|
240
|
+
return p;
|
|
241
|
+
}
|
|
242
|
+
async removeAllListeners() {
|
|
243
|
+
this.listeners = {};
|
|
244
|
+
for (const listener in this.windowListeners) {
|
|
245
|
+
this.removeWindowListener(this.windowListeners[listener]);
|
|
246
|
+
}
|
|
247
|
+
this.windowListeners = {};
|
|
248
|
+
}
|
|
249
|
+
notifyListeners(eventName, data, retainUntilConsumed) {
|
|
250
|
+
const listeners = this.listeners[eventName];
|
|
251
|
+
if (!listeners) {
|
|
252
|
+
if (retainUntilConsumed) {
|
|
253
|
+
let args = this.retainedEventArguments[eventName];
|
|
254
|
+
if (!args) {
|
|
255
|
+
args = [];
|
|
256
|
+
}
|
|
257
|
+
args.push(data);
|
|
258
|
+
this.retainedEventArguments[eventName] = args;
|
|
259
|
+
}
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
listeners.forEach((listener) => listener(data));
|
|
263
|
+
}
|
|
264
|
+
hasListeners(eventName) {
|
|
265
|
+
var _a;
|
|
266
|
+
return !!((_a = this.listeners[eventName]) === null || _a === void 0 ? void 0 : _a.length);
|
|
267
|
+
}
|
|
268
|
+
registerWindowListener(windowEventName, pluginEventName) {
|
|
269
|
+
this.windowListeners[pluginEventName] = {
|
|
270
|
+
registered: false,
|
|
271
|
+
windowEventName,
|
|
272
|
+
pluginEventName,
|
|
273
|
+
handler: (event) => {
|
|
274
|
+
this.notifyListeners(pluginEventName, event);
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
unimplemented(msg = 'not implemented') {
|
|
279
|
+
return new Capacitor.Exception(msg, ExceptionCode.Unimplemented);
|
|
280
|
+
}
|
|
281
|
+
unavailable(msg = 'not available') {
|
|
282
|
+
return new Capacitor.Exception(msg, ExceptionCode.Unavailable);
|
|
283
|
+
}
|
|
284
|
+
async removeListener(eventName, listenerFunc) {
|
|
285
|
+
const listeners = this.listeners[eventName];
|
|
286
|
+
if (!listeners) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const index = listeners.indexOf(listenerFunc);
|
|
290
|
+
this.listeners[eventName].splice(index, 1);
|
|
291
|
+
// If there are no more listeners for this type of event,
|
|
292
|
+
// remove the window listener
|
|
293
|
+
if (!this.listeners[eventName].length) {
|
|
294
|
+
this.removeWindowListener(this.windowListeners[eventName]);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
addWindowListener(handle) {
|
|
298
|
+
window.addEventListener(handle.windowEventName, handle.handler);
|
|
299
|
+
handle.registered = true;
|
|
300
|
+
}
|
|
301
|
+
removeWindowListener(handle) {
|
|
302
|
+
if (!handle) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
window.removeEventListener(handle.windowEventName, handle.handler);
|
|
306
|
+
handle.registered = false;
|
|
307
|
+
}
|
|
308
|
+
sendRetainedArgumentsForEvent(eventName) {
|
|
309
|
+
const args = this.retainedEventArguments[eventName];
|
|
310
|
+
if (!args) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
delete this.retainedEventArguments[eventName];
|
|
314
|
+
args.forEach((arg) => {
|
|
315
|
+
this.notifyListeners(eventName, arg);
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/******** END WEB VIEW PLUGIN ********/
|
|
320
|
+
/******** COOKIES PLUGIN ********/
|
|
321
|
+
/**
|
|
322
|
+
* Safely web encode a string value (inspired by js-cookie)
|
|
323
|
+
* @param str The string value to encode
|
|
324
|
+
*/
|
|
325
|
+
const encode = (str) => encodeURIComponent(str)
|
|
326
|
+
.replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)
|
|
327
|
+
.replace(/[()]/g, escape);
|
|
328
|
+
/**
|
|
329
|
+
* Safely web decode a string value (inspired by js-cookie)
|
|
330
|
+
* @param str The string value to decode
|
|
331
|
+
*/
|
|
332
|
+
const decode = (str) => str.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
|
|
333
|
+
class CapacitorCookiesPluginWeb extends WebPlugin {
|
|
334
|
+
async getCookies() {
|
|
335
|
+
const cookies = document.cookie;
|
|
336
|
+
const cookieMap = {};
|
|
337
|
+
cookies.split(';').forEach((cookie) => {
|
|
338
|
+
if (cookie.length <= 0)
|
|
339
|
+
return;
|
|
340
|
+
// Replace first "=" with CAP_COOKIE to prevent splitting on additional "="
|
|
341
|
+
let [key, value] = cookie.replace(/=/, 'CAP_COOKIE').split('CAP_COOKIE');
|
|
342
|
+
key = decode(key).trim();
|
|
343
|
+
value = decode(value).trim();
|
|
344
|
+
cookieMap[key] = value;
|
|
345
|
+
});
|
|
346
|
+
return cookieMap;
|
|
347
|
+
}
|
|
348
|
+
async setCookie(options) {
|
|
349
|
+
try {
|
|
350
|
+
// Safely Encoded Key/Value
|
|
351
|
+
const encodedKey = encode(options.key);
|
|
352
|
+
const encodedValue = encode(options.value);
|
|
353
|
+
// Clean & sanitize options
|
|
354
|
+
const expires = options.expires ? `; expires=${options.expires.replace('expires=', '')}` : '';
|
|
355
|
+
const path = (options.path || '/').replace('path=', ''); // Default is "path=/"
|
|
356
|
+
const domain = options.url != null && options.url.length > 0 ? `domain=${options.url}` : '';
|
|
357
|
+
document.cookie = `${encodedKey}=${encodedValue || ''}${expires}; path=${path}; ${domain};`;
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
return Promise.reject(error);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
async deleteCookie(options) {
|
|
364
|
+
try {
|
|
365
|
+
document.cookie = `${options.key}=; Max-Age=0`;
|
|
366
|
+
}
|
|
367
|
+
catch (error) {
|
|
368
|
+
return Promise.reject(error);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
async clearCookies() {
|
|
372
|
+
try {
|
|
373
|
+
const cookies = document.cookie.split(';') || [];
|
|
374
|
+
for (const cookie of cookies) {
|
|
375
|
+
document.cookie = cookie.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date().toUTCString()};path=/`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
return Promise.reject(error);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
async clearAllCookies() {
|
|
383
|
+
try {
|
|
384
|
+
await this.clearCookies();
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
return Promise.reject(error);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
registerPlugin('CapacitorCookies', {
|
|
392
|
+
web: () => new CapacitorCookiesPluginWeb(),
|
|
393
|
+
});
|
|
394
|
+
// UTILITY FUNCTIONS
|
|
395
|
+
/**
|
|
396
|
+
* Read in a Blob value and return it as a base64 string
|
|
397
|
+
* @param blob The blob value to convert to a base64 string
|
|
398
|
+
*/
|
|
399
|
+
const readBlobAsBase64 = async (blob) => new Promise((resolve, reject) => {
|
|
400
|
+
const reader = new FileReader();
|
|
401
|
+
reader.onload = () => {
|
|
402
|
+
const base64String = reader.result;
|
|
403
|
+
// remove prefix "data:application/pdf;base64,"
|
|
404
|
+
resolve(base64String.indexOf(',') >= 0 ? base64String.split(',')[1] : base64String);
|
|
405
|
+
};
|
|
406
|
+
reader.onerror = (error) => reject(error);
|
|
407
|
+
reader.readAsDataURL(blob);
|
|
408
|
+
});
|
|
409
|
+
/**
|
|
410
|
+
* Normalize an HttpHeaders map by lowercasing all of the values
|
|
411
|
+
* @param headers The HttpHeaders object to normalize
|
|
412
|
+
*/
|
|
413
|
+
const normalizeHttpHeaders = (headers = {}) => {
|
|
414
|
+
const originalKeys = Object.keys(headers);
|
|
415
|
+
const loweredKeys = Object.keys(headers).map((k) => k.toLocaleLowerCase());
|
|
416
|
+
const normalized = loweredKeys.reduce((acc, key, index) => {
|
|
417
|
+
acc[key] = headers[originalKeys[index]];
|
|
418
|
+
return acc;
|
|
419
|
+
}, {});
|
|
420
|
+
return normalized;
|
|
421
|
+
};
|
|
422
|
+
/**
|
|
423
|
+
* Builds a string of url parameters that
|
|
424
|
+
* @param params A map of url parameters
|
|
425
|
+
* @param shouldEncode true if you should encodeURIComponent() the values (true by default)
|
|
426
|
+
*/
|
|
427
|
+
const buildUrlParams = (params, shouldEncode = true) => {
|
|
428
|
+
if (!params)
|
|
429
|
+
return null;
|
|
430
|
+
const output = Object.entries(params).reduce((accumulator, entry) => {
|
|
431
|
+
const [key, value] = entry;
|
|
432
|
+
let encodedValue;
|
|
433
|
+
let item;
|
|
434
|
+
if (Array.isArray(value)) {
|
|
435
|
+
item = '';
|
|
436
|
+
value.forEach((str) => {
|
|
437
|
+
encodedValue = shouldEncode ? encodeURIComponent(str) : str;
|
|
438
|
+
item += `${key}=${encodedValue}&`;
|
|
439
|
+
});
|
|
440
|
+
// last character will always be "&" so slice it off
|
|
441
|
+
item.slice(0, -1);
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
encodedValue = shouldEncode ? encodeURIComponent(value) : value;
|
|
445
|
+
item = `${key}=${encodedValue}`;
|
|
446
|
+
}
|
|
447
|
+
return `${accumulator}&${item}`;
|
|
448
|
+
}, '');
|
|
449
|
+
// Remove initial "&" from the reduce
|
|
450
|
+
return output.substr(1);
|
|
451
|
+
};
|
|
452
|
+
/**
|
|
453
|
+
* Build the RequestInit object based on the options passed into the initial request
|
|
454
|
+
* @param options The Http plugin options
|
|
455
|
+
* @param extra Any extra RequestInit values
|
|
456
|
+
*/
|
|
457
|
+
const buildRequestInit = (options, extra = {}) => {
|
|
458
|
+
const output = Object.assign({ method: options.method || 'GET', headers: options.headers }, extra);
|
|
459
|
+
// Get the content-type
|
|
460
|
+
const headers = normalizeHttpHeaders(options.headers);
|
|
461
|
+
const type = headers['content-type'] || '';
|
|
462
|
+
// If body is already a string, then pass it through as-is.
|
|
463
|
+
if (typeof options.data === 'string') {
|
|
464
|
+
output.body = options.data;
|
|
465
|
+
}
|
|
466
|
+
// Build request initializers based off of content-type
|
|
467
|
+
else if (type.includes('application/x-www-form-urlencoded')) {
|
|
468
|
+
const params = new URLSearchParams();
|
|
469
|
+
for (const [key, value] of Object.entries(options.data || {})) {
|
|
470
|
+
params.set(key, value);
|
|
471
|
+
}
|
|
472
|
+
output.body = params.toString();
|
|
473
|
+
}
|
|
474
|
+
else if (type.includes('multipart/form-data') || options.data instanceof FormData) {
|
|
475
|
+
const form = new FormData();
|
|
476
|
+
if (options.data instanceof FormData) {
|
|
477
|
+
options.data.forEach((value, key) => {
|
|
478
|
+
form.append(key, value);
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
for (const key of Object.keys(options.data)) {
|
|
483
|
+
form.append(key, options.data[key]);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
output.body = form;
|
|
487
|
+
const headers = new Headers(output.headers);
|
|
488
|
+
headers.delete('content-type'); // content-type will be set by `window.fetch` to includy boundary
|
|
489
|
+
output.headers = headers;
|
|
490
|
+
}
|
|
491
|
+
else if (type.includes('application/json') || typeof options.data === 'object') {
|
|
492
|
+
output.body = JSON.stringify(options.data);
|
|
493
|
+
}
|
|
494
|
+
return output;
|
|
495
|
+
};
|
|
496
|
+
// WEB IMPLEMENTATION
|
|
497
|
+
class CapacitorHttpPluginWeb extends WebPlugin {
|
|
498
|
+
/**
|
|
499
|
+
* Perform an Http request given a set of options
|
|
500
|
+
* @param options Options to build the HTTP request
|
|
501
|
+
*/
|
|
502
|
+
async request(options) {
|
|
503
|
+
const requestInit = buildRequestInit(options, options.webFetchExtra);
|
|
504
|
+
const urlParams = buildUrlParams(options.params, options.shouldEncodeUrlParams);
|
|
505
|
+
const url = urlParams ? `${options.url}?${urlParams}` : options.url;
|
|
506
|
+
const response = await fetch(url, requestInit);
|
|
507
|
+
const contentType = response.headers.get('content-type') || '';
|
|
508
|
+
// Default to 'text' responseType so no parsing happens
|
|
509
|
+
let { responseType = 'text' } = response.ok ? options : {};
|
|
510
|
+
// If the response content-type is json, force the response to be json
|
|
511
|
+
if (contentType.includes('application/json')) {
|
|
512
|
+
responseType = 'json';
|
|
513
|
+
}
|
|
514
|
+
let data;
|
|
515
|
+
let blob;
|
|
516
|
+
switch (responseType) {
|
|
517
|
+
case 'arraybuffer':
|
|
518
|
+
case 'blob':
|
|
519
|
+
blob = await response.blob();
|
|
520
|
+
data = await readBlobAsBase64(blob);
|
|
521
|
+
break;
|
|
522
|
+
case 'json':
|
|
523
|
+
data = await response.json();
|
|
524
|
+
break;
|
|
525
|
+
case 'document':
|
|
526
|
+
case 'text':
|
|
527
|
+
default:
|
|
528
|
+
data = await response.text();
|
|
529
|
+
}
|
|
530
|
+
// Convert fetch headers to Capacitor HttpHeaders
|
|
531
|
+
const headers = {};
|
|
532
|
+
response.headers.forEach((value, key) => {
|
|
533
|
+
headers[key] = value;
|
|
534
|
+
});
|
|
535
|
+
return {
|
|
536
|
+
data,
|
|
537
|
+
headers,
|
|
538
|
+
status: response.status,
|
|
539
|
+
url: response.url,
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Perform an Http GET request given a set of options
|
|
544
|
+
* @param options Options to build the HTTP request
|
|
545
|
+
*/
|
|
546
|
+
async get(options) {
|
|
547
|
+
return this.request(Object.assign(Object.assign({}, options), { method: 'GET' }));
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Perform an Http POST request given a set of options
|
|
551
|
+
* @param options Options to build the HTTP request
|
|
552
|
+
*/
|
|
553
|
+
async post(options) {
|
|
554
|
+
return this.request(Object.assign(Object.assign({}, options), { method: 'POST' }));
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Perform an Http PUT request given a set of options
|
|
558
|
+
* @param options Options to build the HTTP request
|
|
559
|
+
*/
|
|
560
|
+
async put(options) {
|
|
561
|
+
return this.request(Object.assign(Object.assign({}, options), { method: 'PUT' }));
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Perform an Http PATCH request given a set of options
|
|
565
|
+
* @param options Options to build the HTTP request
|
|
566
|
+
*/
|
|
567
|
+
async patch(options) {
|
|
568
|
+
return this.request(Object.assign(Object.assign({}, options), { method: 'PATCH' }));
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Perform an Http DELETE request given a set of options
|
|
572
|
+
* @param options Options to build the HTTP request
|
|
573
|
+
*/
|
|
574
|
+
async delete(options) {
|
|
575
|
+
return this.request(Object.assign(Object.assign({}, options), { method: 'DELETE' }));
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
registerPlugin('CapacitorHttp', {
|
|
579
|
+
web: () => new CapacitorHttpPluginWeb(),
|
|
580
|
+
});
|
|
581
|
+
/******** END HTTP PLUGIN ********/
|
|
582
|
+
/******** SYSTEM BARS PLUGIN ********/
|
|
583
|
+
/**
|
|
584
|
+
* Available status bar styles.
|
|
585
|
+
*/
|
|
586
|
+
var SystemBarsStyle;
|
|
587
|
+
(function (SystemBarsStyle) {
|
|
588
|
+
/**
|
|
589
|
+
* Light system bar content on a dark background.
|
|
590
|
+
*
|
|
591
|
+
* @since 8.0.0
|
|
592
|
+
*/
|
|
593
|
+
SystemBarsStyle["Dark"] = "DARK";
|
|
594
|
+
/**
|
|
595
|
+
* For dark system bar content on a light background.
|
|
596
|
+
*
|
|
597
|
+
* @since 8.0.0
|
|
598
|
+
*/
|
|
599
|
+
SystemBarsStyle["Light"] = "LIGHT";
|
|
600
|
+
/**
|
|
601
|
+
* The style is based on the device appearance or the underlying content.
|
|
602
|
+
* If the device is using Dark mode, the system bars content will be light.
|
|
603
|
+
* If the device is using Light mode, the system bars content will be dark.
|
|
604
|
+
*
|
|
605
|
+
* @since 8.0.0
|
|
606
|
+
*/
|
|
607
|
+
SystemBarsStyle["Default"] = "DEFAULT";
|
|
608
|
+
})(SystemBarsStyle || (SystemBarsStyle = {}));
|
|
609
|
+
/**
|
|
610
|
+
* Available system bar types.
|
|
611
|
+
*/
|
|
612
|
+
var SystemBarType;
|
|
613
|
+
(function (SystemBarType) {
|
|
614
|
+
/**
|
|
615
|
+
* The top status bar on both Android and iOS.
|
|
616
|
+
*
|
|
617
|
+
* @since 8.0.0
|
|
618
|
+
*/
|
|
619
|
+
SystemBarType["StatusBar"] = "StatusBar";
|
|
620
|
+
/**
|
|
621
|
+
* The navigation bar (or gesture bar on iOS) on both Android and iOS.
|
|
622
|
+
*
|
|
623
|
+
* @since 8.0.0
|
|
624
|
+
*/
|
|
625
|
+
SystemBarType["NavigationBar"] = "NavigationBar";
|
|
626
|
+
})(SystemBarType || (SystemBarType = {}));
|
|
627
|
+
class SystemBarsPluginWeb extends WebPlugin {
|
|
628
|
+
async setStyle() {
|
|
629
|
+
this.unavailable('not available for web');
|
|
630
|
+
}
|
|
631
|
+
async setAnimation() {
|
|
632
|
+
this.unavailable('not available for web');
|
|
633
|
+
}
|
|
634
|
+
async show() {
|
|
635
|
+
this.unavailable('not available for web');
|
|
636
|
+
}
|
|
637
|
+
async hide() {
|
|
638
|
+
this.unavailable('not available for web');
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
registerPlugin('SystemBars', {
|
|
642
|
+
web: () => new SystemBarsPluginWeb(),
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
const nodeIds = new WeakMap();
|
|
646
|
+
let nextNodeId = 1;
|
|
647
|
+
function nodeId(element) {
|
|
648
|
+
const existing = nodeIds.get(element);
|
|
649
|
+
if (existing)
|
|
650
|
+
return existing;
|
|
651
|
+
const id = `dom.${nextNodeId++}`;
|
|
652
|
+
nodeIds.set(element, id);
|
|
653
|
+
return id;
|
|
654
|
+
}
|
|
655
|
+
function isVisible(element, style, bounds) {
|
|
656
|
+
return (style.display !== "none" &&
|
|
657
|
+
style.visibility !== "hidden" &&
|
|
658
|
+
style.opacity !== "0" &&
|
|
659
|
+
bounds.width > 0 &&
|
|
660
|
+
bounds.height > 0);
|
|
661
|
+
}
|
|
662
|
+
function accessibleLabel(element, includeText) {
|
|
663
|
+
const labelledBy = element.getAttribute("aria-labelledby");
|
|
664
|
+
const referenced = labelledBy
|
|
665
|
+
?.split(/\s+/)
|
|
666
|
+
.map((id) => document.getElementById(id)?.textContent?.trim())
|
|
667
|
+
.filter(Boolean)
|
|
668
|
+
.join(" ");
|
|
669
|
+
const label = element.getAttribute("aria-label") ??
|
|
670
|
+
referenced ??
|
|
671
|
+
element.getAttribute("alt") ??
|
|
672
|
+
element.getAttribute("title") ??
|
|
673
|
+
(includeText
|
|
674
|
+
? element.textContent?.replace(/\s+/g, " ").trim().slice(0, 240)
|
|
675
|
+
: undefined);
|
|
676
|
+
return label || undefined;
|
|
677
|
+
}
|
|
678
|
+
function attributes(element) {
|
|
679
|
+
return Object.fromEntries(Array.from(element.attributes, ({ name, value }) => [
|
|
680
|
+
name,
|
|
681
|
+
value.slice(0, 500),
|
|
682
|
+
]));
|
|
683
|
+
}
|
|
684
|
+
function captureNode(element, options, depth, limits) {
|
|
685
|
+
if (limits.count >= limits.maxNodes || depth > limits.maxDepth)
|
|
686
|
+
return null;
|
|
687
|
+
const style = getComputedStyle(element);
|
|
688
|
+
const rect = element.getBoundingClientRect();
|
|
689
|
+
const visible = isVisible(element, style, rect);
|
|
690
|
+
if (!visible && !options.includeHidden)
|
|
691
|
+
return null;
|
|
692
|
+
limits.count += 1;
|
|
693
|
+
const children = Array.from(element.children)
|
|
694
|
+
.map((child) => captureNode(child, options, depth + 1, limits))
|
|
695
|
+
.filter((child) => child !== null);
|
|
696
|
+
const htmlElement = element;
|
|
697
|
+
const disabled = element.hasAttribute("disabled") ||
|
|
698
|
+
element.getAttribute("aria-disabled") === "true";
|
|
699
|
+
return {
|
|
700
|
+
id: nodeId(element),
|
|
701
|
+
type: element.tagName.toLowerCase(),
|
|
702
|
+
label: accessibleLabel(element, options.includeText),
|
|
703
|
+
visible,
|
|
704
|
+
enabled: !disabled,
|
|
705
|
+
focusable: htmlElement.tabIndex >= 0 ||
|
|
706
|
+
["A", "BUTTON", "INPUT", "SELECT", "TEXTAREA", "SUMMARY"].includes(element.tagName),
|
|
707
|
+
childCount: children.length,
|
|
708
|
+
bounds: {
|
|
709
|
+
x: rect.x,
|
|
710
|
+
y: rect.y,
|
|
711
|
+
width: rect.width,
|
|
712
|
+
height: rect.height,
|
|
713
|
+
},
|
|
714
|
+
properties: {
|
|
715
|
+
id: element.id || undefined,
|
|
716
|
+
role: element.getAttribute("role") ?? undefined,
|
|
717
|
+
className: element.getAttribute("class") ?? undefined,
|
|
718
|
+
value: element instanceof HTMLInputElement ||
|
|
719
|
+
element instanceof HTMLSelectElement ||
|
|
720
|
+
element instanceof HTMLTextAreaElement
|
|
721
|
+
? element.value
|
|
722
|
+
: undefined,
|
|
723
|
+
checked: element instanceof HTMLInputElement ? element.checked : undefined,
|
|
724
|
+
attributes: options.includeAttributes ? attributes(element) : undefined,
|
|
725
|
+
},
|
|
726
|
+
children,
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
function findElement(id) {
|
|
730
|
+
return Array.from(document.querySelectorAll("*")).find((element) => nodeId(element) === id);
|
|
731
|
+
}
|
|
732
|
+
function successful(result, message) {
|
|
733
|
+
return { success: true, message, result };
|
|
734
|
+
}
|
|
735
|
+
function installDomTools$1(registerTool, input = {}) {
|
|
736
|
+
const options = {
|
|
737
|
+
source: input.source ?? "capacitor-dom",
|
|
738
|
+
includeHidden: input.includeHidden ?? false,
|
|
739
|
+
maxDepth: input.maxDepth ?? 30,
|
|
740
|
+
maxNodes: input.maxNodes ?? 1500,
|
|
741
|
+
includeText: input.includeText ?? true,
|
|
742
|
+
includeAttributes: input.includeAttributes ?? true,
|
|
743
|
+
allowActions: input.allowActions ?? false,
|
|
744
|
+
};
|
|
745
|
+
const registrations = [
|
|
746
|
+
registerTool({
|
|
747
|
+
id: "dom.get_document",
|
|
748
|
+
name: "Get DOM document",
|
|
749
|
+
description: "Returns the accessible HTML DOM tree rendered inside the Capacitor WebView.",
|
|
750
|
+
category: "UI",
|
|
751
|
+
scope: "read",
|
|
752
|
+
security: { level: "low", summary: "Reads the current app DOM." },
|
|
753
|
+
}, async () => {
|
|
754
|
+
const root = document.documentElement;
|
|
755
|
+
const limits = {
|
|
756
|
+
maxDepth: options.maxDepth,
|
|
757
|
+
maxNodes: options.maxNodes,
|
|
758
|
+
count: 0,
|
|
759
|
+
};
|
|
760
|
+
const tree = captureNode(root, options, 0, limits);
|
|
761
|
+
return successful({
|
|
762
|
+
platform: "web",
|
|
763
|
+
source: options.source,
|
|
764
|
+
adapter: "@ansight/capacitor",
|
|
765
|
+
capturedAtUtc: new Date().toISOString(),
|
|
766
|
+
truncated: limits.count >= limits.maxNodes,
|
|
767
|
+
root: tree,
|
|
768
|
+
}, "DOM document captured.");
|
|
769
|
+
}),
|
|
770
|
+
registerTool({
|
|
771
|
+
id: "dom.inspect_node",
|
|
772
|
+
name: "Inspect DOM node",
|
|
773
|
+
description: "Returns the current state of a DOM node captured by dom.get_document.",
|
|
774
|
+
category: "UI",
|
|
775
|
+
scope: "read",
|
|
776
|
+
argumentsSchema: {
|
|
777
|
+
type: "object",
|
|
778
|
+
required: ["nodeId"],
|
|
779
|
+
properties: { nodeId: { type: "string" } },
|
|
780
|
+
},
|
|
781
|
+
}, ({ nodeId: id }) => {
|
|
782
|
+
const element = findElement(id);
|
|
783
|
+
if (!element) {
|
|
784
|
+
return {
|
|
785
|
+
success: false,
|
|
786
|
+
message: `DOM node '${id}' was not found.`,
|
|
787
|
+
errorCode: "dom_node_not_found",
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
const limits = { maxDepth: 0, maxNodes: 1, count: 0 };
|
|
791
|
+
return successful(captureNode(element, options, 0, limits), "DOM node captured.");
|
|
792
|
+
}),
|
|
793
|
+
registerTool({
|
|
794
|
+
id: "dom.query_selector",
|
|
795
|
+
name: "Query DOM",
|
|
796
|
+
description: "Finds DOM nodes using a CSS selector.",
|
|
797
|
+
category: "UI",
|
|
798
|
+
scope: "read",
|
|
799
|
+
argumentsSchema: {
|
|
800
|
+
type: "object",
|
|
801
|
+
required: ["selector"],
|
|
802
|
+
properties: { selector: { type: "string" } },
|
|
803
|
+
},
|
|
804
|
+
}, ({ selector }) => {
|
|
805
|
+
try {
|
|
806
|
+
const matches = Array.from(document.querySelectorAll(selector)).slice(0, 200);
|
|
807
|
+
return successful(matches.map((element) => ({
|
|
808
|
+
id: nodeId(element),
|
|
809
|
+
type: element.tagName.toLowerCase(),
|
|
810
|
+
label: accessibleLabel(element, true),
|
|
811
|
+
})), `Matched ${matches.length} DOM node(s).`);
|
|
812
|
+
}
|
|
813
|
+
catch (error) {
|
|
814
|
+
return {
|
|
815
|
+
success: false,
|
|
816
|
+
message: error instanceof Error ? error.message : "Invalid CSS selector.",
|
|
817
|
+
errorCode: "dom_selector_invalid",
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
}),
|
|
821
|
+
];
|
|
822
|
+
if (options.allowActions) {
|
|
823
|
+
registrations.push(registerTool({
|
|
824
|
+
id: "dom.invoke_action",
|
|
825
|
+
name: "Invoke DOM action",
|
|
826
|
+
description: "Clicks, focuses, blurs, or changes a DOM node.",
|
|
827
|
+
category: "UI",
|
|
828
|
+
scope: "write",
|
|
829
|
+
argumentsSchema: {
|
|
830
|
+
type: "object",
|
|
831
|
+
required: ["nodeId", "action"],
|
|
832
|
+
properties: {
|
|
833
|
+
nodeId: { type: "string" },
|
|
834
|
+
action: { enum: ["click", "focus", "blur", "setValue"] },
|
|
835
|
+
value: { type: "string" },
|
|
836
|
+
},
|
|
837
|
+
},
|
|
838
|
+
security: {
|
|
839
|
+
level: "high",
|
|
840
|
+
summary: "Can interact with controls inside the app WebView.",
|
|
841
|
+
},
|
|
842
|
+
}, ({ nodeId: id, action, value }) => {
|
|
843
|
+
const element = findElement(id);
|
|
844
|
+
if (!element) {
|
|
845
|
+
return {
|
|
846
|
+
success: false,
|
|
847
|
+
message: `DOM node '${id}' was not found.`,
|
|
848
|
+
errorCode: "dom_node_not_found",
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
if (action === "click")
|
|
852
|
+
element.click();
|
|
853
|
+
else if (action === "focus")
|
|
854
|
+
element.focus();
|
|
855
|
+
else if (action === "blur")
|
|
856
|
+
element.blur();
|
|
857
|
+
else if (action === "setValue" &&
|
|
858
|
+
(element instanceof HTMLInputElement ||
|
|
859
|
+
element instanceof HTMLTextAreaElement ||
|
|
860
|
+
element instanceof HTMLSelectElement)) {
|
|
861
|
+
element.value = value ?? "";
|
|
862
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
863
|
+
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
864
|
+
}
|
|
865
|
+
else {
|
|
866
|
+
return {
|
|
867
|
+
success: false,
|
|
868
|
+
message: `Unsupported action '${action}'.`,
|
|
869
|
+
errorCode: "dom_action_unsupported",
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
return successful({ nodeId: id, action }, `DOM action '${action}' invoked.`);
|
|
873
|
+
}));
|
|
874
|
+
}
|
|
875
|
+
return {
|
|
876
|
+
ids: registrations.map(({ id }) => id),
|
|
877
|
+
ready: Promise.all(registrations.map(({ ready }) => ready)),
|
|
878
|
+
unregister: () => Promise.all(registrations.map((registration) => registration.unregister())),
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
function cloneOptions(options) {
|
|
883
|
+
return JSON.parse(JSON.stringify(options));
|
|
884
|
+
}
|
|
885
|
+
class AnsightOptionsBuilder {
|
|
886
|
+
options;
|
|
887
|
+
constructor(options = {}) {
|
|
888
|
+
this.options = cloneOptions(options);
|
|
889
|
+
}
|
|
890
|
+
withAnsightDefaults() {
|
|
891
|
+
this.options = {
|
|
892
|
+
...this.options,
|
|
893
|
+
useNativeAllInOneDefaults: true,
|
|
894
|
+
sampleFrequencyMilliseconds: 400,
|
|
895
|
+
retentionPeriodSeconds: 120,
|
|
896
|
+
enableFramesPerSecond: true,
|
|
897
|
+
enableBatteryLevel: false,
|
|
898
|
+
sessionJpegCapture: {
|
|
899
|
+
intervalMilliseconds: 2000,
|
|
900
|
+
quality: 60,
|
|
901
|
+
maxWidth: 480,
|
|
902
|
+
},
|
|
903
|
+
touchCapture: {},
|
|
904
|
+
toolGuard: "readOnly",
|
|
905
|
+
hostAutoProbe: {
|
|
906
|
+
...this.options.hostAutoProbe,
|
|
907
|
+
enabled: true,
|
|
908
|
+
},
|
|
909
|
+
};
|
|
910
|
+
return this;
|
|
911
|
+
}
|
|
912
|
+
withNativeAllInOneDefaults() {
|
|
913
|
+
return this.withAnsightDefaults();
|
|
914
|
+
}
|
|
915
|
+
withAnsightSdk(configure) {
|
|
916
|
+
this.withAnsightDefaults().withAllToolAccess();
|
|
917
|
+
configure?.(this);
|
|
918
|
+
return this;
|
|
919
|
+
}
|
|
920
|
+
withSampleFrequencyMilliseconds(value) {
|
|
921
|
+
this.options.sampleFrequencyMilliseconds = value;
|
|
922
|
+
return this;
|
|
923
|
+
}
|
|
924
|
+
withFramesPerSecond() {
|
|
925
|
+
this.options.enableFramesPerSecond = true;
|
|
926
|
+
return this;
|
|
927
|
+
}
|
|
928
|
+
withoutFramesPerSecond() {
|
|
929
|
+
this.options.enableFramesPerSecond = false;
|
|
930
|
+
return this;
|
|
931
|
+
}
|
|
932
|
+
withBatteryLevel() {
|
|
933
|
+
this.options.enableBatteryLevel = true;
|
|
934
|
+
return this;
|
|
935
|
+
}
|
|
936
|
+
withoutBatteryLevel() {
|
|
937
|
+
this.options.enableBatteryLevel = false;
|
|
938
|
+
return this;
|
|
939
|
+
}
|
|
940
|
+
withRetentionPeriodSeconds(value) {
|
|
941
|
+
this.options.retentionPeriodSeconds = value;
|
|
942
|
+
return this;
|
|
943
|
+
}
|
|
944
|
+
withAdditionalChannels(channels) {
|
|
945
|
+
this.options.additionalChannels = channels.map((channel) => ({
|
|
946
|
+
...channel,
|
|
947
|
+
}));
|
|
948
|
+
return this;
|
|
949
|
+
}
|
|
950
|
+
addAdditionalChannel(channel) {
|
|
951
|
+
this.options.additionalChannels = [
|
|
952
|
+
...(this.options.additionalChannels ?? []),
|
|
953
|
+
{ ...channel },
|
|
954
|
+
];
|
|
955
|
+
return this;
|
|
956
|
+
}
|
|
957
|
+
withDefaultMemoryChannels(channels) {
|
|
958
|
+
this.options.defaultMemoryChannels = { ...channels };
|
|
959
|
+
return this;
|
|
960
|
+
}
|
|
961
|
+
withoutDefaultMemoryChannels(channels) {
|
|
962
|
+
const current = {
|
|
963
|
+
managedHeap: true,
|
|
964
|
+
javaHeap: true,
|
|
965
|
+
nativeHeap: true,
|
|
966
|
+
residentSetSize: true,
|
|
967
|
+
rss: true,
|
|
968
|
+
physicalFootprint: true,
|
|
969
|
+
...this.options.defaultMemoryChannels,
|
|
970
|
+
};
|
|
971
|
+
for (const [key, disabled] of Object.entries(channels)) {
|
|
972
|
+
if (disabled)
|
|
973
|
+
current[key] = false;
|
|
974
|
+
}
|
|
975
|
+
this.options.defaultMemoryChannels = current;
|
|
976
|
+
return this;
|
|
977
|
+
}
|
|
978
|
+
withSessionJpegCapture(optionsOrIntervalMilliseconds = {}, quality = 60, maxWidth = 480, captureGpuBackedSurfaces = true) {
|
|
979
|
+
this.options.sessionJpegCapture =
|
|
980
|
+
typeof optionsOrIntervalMilliseconds === "number"
|
|
981
|
+
? {
|
|
982
|
+
intervalMilliseconds: optionsOrIntervalMilliseconds,
|
|
983
|
+
quality,
|
|
984
|
+
maxWidth,
|
|
985
|
+
captureGpuBackedSurfaces,
|
|
986
|
+
}
|
|
987
|
+
: {
|
|
988
|
+
intervalMilliseconds: 2000,
|
|
989
|
+
quality: 60,
|
|
990
|
+
maxWidth: 480,
|
|
991
|
+
...optionsOrIntervalMilliseconds,
|
|
992
|
+
};
|
|
993
|
+
return this;
|
|
994
|
+
}
|
|
995
|
+
withoutSessionJpegCapture() {
|
|
996
|
+
this.options.sessionJpegCapture = false;
|
|
997
|
+
return this;
|
|
998
|
+
}
|
|
999
|
+
withTouchCapture(options = {}) {
|
|
1000
|
+
this.options.touchCapture = { ...options };
|
|
1001
|
+
return this;
|
|
1002
|
+
}
|
|
1003
|
+
withoutTouchCapture() {
|
|
1004
|
+
this.options.touchCapture = false;
|
|
1005
|
+
return this;
|
|
1006
|
+
}
|
|
1007
|
+
withLifecycleCapture(options = {}) {
|
|
1008
|
+
this.options.lifecycleCapture = {
|
|
1009
|
+
...options,
|
|
1010
|
+
enabled: options.enabled ?? true,
|
|
1011
|
+
};
|
|
1012
|
+
return this;
|
|
1013
|
+
}
|
|
1014
|
+
withToolGuard(toolGuard) {
|
|
1015
|
+
this.options.toolGuard = toolGuard;
|
|
1016
|
+
return this;
|
|
1017
|
+
}
|
|
1018
|
+
withToolsDisabled() {
|
|
1019
|
+
return this.withToolGuard("disabled");
|
|
1020
|
+
}
|
|
1021
|
+
withReadOnlyToolAccess() {
|
|
1022
|
+
return this.withToolGuard("readOnly");
|
|
1023
|
+
}
|
|
1024
|
+
withReadWriteToolAccess() {
|
|
1025
|
+
return this.withToolGuard("readWrite");
|
|
1026
|
+
}
|
|
1027
|
+
withAllToolAccess() {
|
|
1028
|
+
return this.withToolGuard("fullAccess");
|
|
1029
|
+
}
|
|
1030
|
+
withHostAutoProbe(options = {}) {
|
|
1031
|
+
this.options.hostAutoProbe = {
|
|
1032
|
+
...options,
|
|
1033
|
+
enabled: options.enabled ?? true,
|
|
1034
|
+
};
|
|
1035
|
+
return this;
|
|
1036
|
+
}
|
|
1037
|
+
withoutHostAutoProbe() {
|
|
1038
|
+
this.options.hostAutoProbe = {
|
|
1039
|
+
...this.options.hostAutoProbe,
|
|
1040
|
+
enabled: false,
|
|
1041
|
+
};
|
|
1042
|
+
return this;
|
|
1043
|
+
}
|
|
1044
|
+
withHostConnection(options = {}) {
|
|
1045
|
+
this.options.hostConnection = { ...options };
|
|
1046
|
+
return this;
|
|
1047
|
+
}
|
|
1048
|
+
configureHostConnection(configure) {
|
|
1049
|
+
const current = { ...this.options.hostConnection };
|
|
1050
|
+
this.options.hostConnection = configure(current) ?? current;
|
|
1051
|
+
return this;
|
|
1052
|
+
}
|
|
1053
|
+
withBundledHostConnection(options = {}) {
|
|
1054
|
+
return this.configureHostConnection((current) => ({
|
|
1055
|
+
...current,
|
|
1056
|
+
bundledDeveloperConfigJson: options.bundledDeveloperConfigJson,
|
|
1057
|
+
bundledConfigJson: options.bundledConfigJson,
|
|
1058
|
+
}));
|
|
1059
|
+
}
|
|
1060
|
+
withHostConnectionDiscoveryPort(discoveryPort) {
|
|
1061
|
+
return this.configureHostConnection((current) => ({
|
|
1062
|
+
...current,
|
|
1063
|
+
discoveryPort,
|
|
1064
|
+
}));
|
|
1065
|
+
}
|
|
1066
|
+
withHostConnectionProfileRetentionSeconds(connectionProfileRetentionSeconds) {
|
|
1067
|
+
return this.configureHostConnection((current) => ({
|
|
1068
|
+
...current,
|
|
1069
|
+
connectionProfileRetentionSeconds,
|
|
1070
|
+
}));
|
|
1071
|
+
}
|
|
1072
|
+
withSecureStorage(options = {}) {
|
|
1073
|
+
this.options.secureStorage = {
|
|
1074
|
+
...options,
|
|
1075
|
+
allowedKeys: options.allowedKeys ? [...options.allowedKeys] : undefined,
|
|
1076
|
+
allowedPrefixes: options.allowedPrefixes
|
|
1077
|
+
? [...options.allowedPrefixes]
|
|
1078
|
+
: undefined,
|
|
1079
|
+
};
|
|
1080
|
+
return this;
|
|
1081
|
+
}
|
|
1082
|
+
withRemoteTools(options = {}) {
|
|
1083
|
+
this.options.remoteTools = cloneOptions({
|
|
1084
|
+
remoteTools: options,
|
|
1085
|
+
}).remoteTools;
|
|
1086
|
+
return this;
|
|
1087
|
+
}
|
|
1088
|
+
withVisualTreeTools(options = {}) {
|
|
1089
|
+
this.options.remoteTools = {
|
|
1090
|
+
...this.options.remoteTools,
|
|
1091
|
+
visualTree: typeof options === "boolean"
|
|
1092
|
+
? options
|
|
1093
|
+
: { ...options, enabled: options.enabled ?? true },
|
|
1094
|
+
};
|
|
1095
|
+
return this;
|
|
1096
|
+
}
|
|
1097
|
+
withoutVisualTreeTools() {
|
|
1098
|
+
this.options.remoteTools = {
|
|
1099
|
+
...this.options.remoteTools,
|
|
1100
|
+
visualTree: false,
|
|
1101
|
+
};
|
|
1102
|
+
return this;
|
|
1103
|
+
}
|
|
1104
|
+
withFileSystemTools(options = {}) {
|
|
1105
|
+
this.options.remoteTools = {
|
|
1106
|
+
...this.options.remoteTools,
|
|
1107
|
+
fileSystem: cloneOptions({ remoteTools: { fileSystem: options } })
|
|
1108
|
+
.remoteTools?.fileSystem,
|
|
1109
|
+
};
|
|
1110
|
+
return this;
|
|
1111
|
+
}
|
|
1112
|
+
withDatabaseTools(options = {}) {
|
|
1113
|
+
this.options.remoteTools = {
|
|
1114
|
+
...this.options.remoteTools,
|
|
1115
|
+
database: cloneOptions({ remoteTools: { database: options } }).remoteTools
|
|
1116
|
+
?.database,
|
|
1117
|
+
};
|
|
1118
|
+
return this;
|
|
1119
|
+
}
|
|
1120
|
+
withPreferencesTools(options = {}) {
|
|
1121
|
+
this.options.remoteTools = {
|
|
1122
|
+
...this.options.remoteTools,
|
|
1123
|
+
preferences: cloneOptions({ remoteTools: { preferences: options } })
|
|
1124
|
+
.remoteTools?.preferences,
|
|
1125
|
+
};
|
|
1126
|
+
return this;
|
|
1127
|
+
}
|
|
1128
|
+
withReflectionTools(options = {}) {
|
|
1129
|
+
this.options.remoteTools = {
|
|
1130
|
+
...this.options.remoteTools,
|
|
1131
|
+
reflection: cloneOptions({ remoteTools: { reflection: options } })
|
|
1132
|
+
.remoteTools?.reflection,
|
|
1133
|
+
};
|
|
1134
|
+
return this;
|
|
1135
|
+
}
|
|
1136
|
+
withDomTools(options = {}) {
|
|
1137
|
+
this.options.domTools = { ...options };
|
|
1138
|
+
return this;
|
|
1139
|
+
}
|
|
1140
|
+
withErrorCapture(options = {}) {
|
|
1141
|
+
this.options.errorCapture = { ...options };
|
|
1142
|
+
return this;
|
|
1143
|
+
}
|
|
1144
|
+
registerCustomProperty(group, key, value) {
|
|
1145
|
+
this.options.customProperties = {
|
|
1146
|
+
...this.options.customProperties,
|
|
1147
|
+
[group]: {
|
|
1148
|
+
...this.options.customProperties?.[group],
|
|
1149
|
+
[key]: String(value),
|
|
1150
|
+
},
|
|
1151
|
+
};
|
|
1152
|
+
return this;
|
|
1153
|
+
}
|
|
1154
|
+
removeCustomProperty(group, key) {
|
|
1155
|
+
const groups = cloneOptions({ customProperties: this.options.customProperties })
|
|
1156
|
+
.customProperties ?? {};
|
|
1157
|
+
delete groups[group]?.[key];
|
|
1158
|
+
if (groups[group] && Object.keys(groups[group]).length === 0) {
|
|
1159
|
+
delete groups[group];
|
|
1160
|
+
}
|
|
1161
|
+
this.options.customProperties = groups;
|
|
1162
|
+
return this;
|
|
1163
|
+
}
|
|
1164
|
+
clearCustomProperties() {
|
|
1165
|
+
this.options.customProperties = {};
|
|
1166
|
+
return this;
|
|
1167
|
+
}
|
|
1168
|
+
build() {
|
|
1169
|
+
return cloneOptions(this.options);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
function createOptionsBuilder(options = {}) {
|
|
1173
|
+
return new AnsightOptionsBuilder(options);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
const AnsightNative = registerPlugin("Ansight");
|
|
1177
|
+
const toolHandlers = new Map();
|
|
1178
|
+
const artifactProviders = new Map();
|
|
1179
|
+
const hostConnectionListeners = new Set();
|
|
1180
|
+
const logListeners = new Set();
|
|
1181
|
+
let toolListener;
|
|
1182
|
+
let logListener;
|
|
1183
|
+
let lifecycleCleanup;
|
|
1184
|
+
let artifactToolRegistrations = [];
|
|
1185
|
+
let domToolRegistration;
|
|
1186
|
+
function normalizePairingPayload(payload) {
|
|
1187
|
+
if (payload == null)
|
|
1188
|
+
return payload;
|
|
1189
|
+
return typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
1190
|
+
}
|
|
1191
|
+
function normalizeOptions(input) {
|
|
1192
|
+
const options = JSON.parse(JSON.stringify(input));
|
|
1193
|
+
if (options.pairingConfig != null) {
|
|
1194
|
+
options.pairingConfigJson =
|
|
1195
|
+
normalizePairingPayload(options.pairingConfig) ?? undefined;
|
|
1196
|
+
delete options.pairingConfig;
|
|
1197
|
+
}
|
|
1198
|
+
if (options.bundledPairingConfig != null) {
|
|
1199
|
+
options.pairingConfigJson =
|
|
1200
|
+
normalizePairingPayload(options.bundledPairingConfig) ?? undefined;
|
|
1201
|
+
delete options.bundledPairingConfig;
|
|
1202
|
+
}
|
|
1203
|
+
delete options.domTools;
|
|
1204
|
+
delete options.errorCapture;
|
|
1205
|
+
delete options.lifecycle;
|
|
1206
|
+
return options;
|
|
1207
|
+
}
|
|
1208
|
+
function normalizeToolResult(value) {
|
|
1209
|
+
if (value && typeof value === "object" && "success" in value) {
|
|
1210
|
+
return value;
|
|
1211
|
+
}
|
|
1212
|
+
return { success: true, result: value };
|
|
1213
|
+
}
|
|
1214
|
+
function errorToolResult(error) {
|
|
1215
|
+
return {
|
|
1216
|
+
success: false,
|
|
1217
|
+
message: error instanceof Error ? error.message : String(error),
|
|
1218
|
+
errorCode: "javascript_tool_failed",
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
async function ensureToolListener() {
|
|
1222
|
+
toolListener ??= AnsightNative.addListener("ansightToolCall", (call) => {
|
|
1223
|
+
const handler = toolHandlers.get(call.toolId);
|
|
1224
|
+
void Promise.resolve(handler
|
|
1225
|
+
? handler(call.arguments ?? {}, call)
|
|
1226
|
+
: {
|
|
1227
|
+
success: false,
|
|
1228
|
+
message: `No JavaScript handler is registered for '${call.toolId}'.`,
|
|
1229
|
+
errorCode: "javascript_tool_not_registered",
|
|
1230
|
+
})
|
|
1231
|
+
.then(normalizeToolResult)
|
|
1232
|
+
.catch(errorToolResult)
|
|
1233
|
+
.then((result) => AnsightNative.resolveToolCall({ requestId: call.requestId, result }))
|
|
1234
|
+
.catch(() => undefined);
|
|
1235
|
+
});
|
|
1236
|
+
return toolListener;
|
|
1237
|
+
}
|
|
1238
|
+
async function ensureLogListener() {
|
|
1239
|
+
logListener ??= AnsightNative.addListener("ansightLog", (entry) => {
|
|
1240
|
+
for (const listener of logListeners)
|
|
1241
|
+
listener(entry);
|
|
1242
|
+
});
|
|
1243
|
+
return logListener;
|
|
1244
|
+
}
|
|
1245
|
+
async function emitHostConnectionStatus() {
|
|
1246
|
+
if (hostConnectionListeners.size === 0)
|
|
1247
|
+
return;
|
|
1248
|
+
const [status, capabilities] = await Promise.all([
|
|
1249
|
+
AnsightNative.hostConnectionStatus(),
|
|
1250
|
+
AnsightNative.hostConnectionCapabilities(),
|
|
1251
|
+
]);
|
|
1252
|
+
for (const listener of hostConnectionListeners)
|
|
1253
|
+
listener(status, capabilities);
|
|
1254
|
+
}
|
|
1255
|
+
async function afterConnectionChange(operation) {
|
|
1256
|
+
const result = await operation();
|
|
1257
|
+
await emitHostConnectionStatus();
|
|
1258
|
+
return result;
|
|
1259
|
+
}
|
|
1260
|
+
async function initialize(options = {}) {
|
|
1261
|
+
const result = await AnsightNative.initialize(normalizeOptions(options));
|
|
1262
|
+
if (options.lifecycle !== false)
|
|
1263
|
+
startLifecycleTracking();
|
|
1264
|
+
if (options.errorCapture) {
|
|
1265
|
+
installErrorHandlers(typeof options.errorCapture === "object" ? options.errorCapture : {});
|
|
1266
|
+
}
|
|
1267
|
+
if (options.domTools) {
|
|
1268
|
+
installDomTools(typeof options.domTools === "object" ? options.domTools : {});
|
|
1269
|
+
}
|
|
1270
|
+
await emitHostConnectionStatus();
|
|
1271
|
+
return result;
|
|
1272
|
+
}
|
|
1273
|
+
async function initializeAndActivate(options = {}) {
|
|
1274
|
+
const result = await AnsightNative.initializeAndActivate(normalizeOptions(options));
|
|
1275
|
+
if (options.lifecycle !== false)
|
|
1276
|
+
startLifecycleTracking();
|
|
1277
|
+
if (options.errorCapture) {
|
|
1278
|
+
installErrorHandlers(typeof options.errorCapture === "object" ? options.errorCapture : {});
|
|
1279
|
+
}
|
|
1280
|
+
if (options.domTools) {
|
|
1281
|
+
installDomTools(typeof options.domTools === "object" ? options.domTools : {});
|
|
1282
|
+
}
|
|
1283
|
+
await emitHostConnectionStatus();
|
|
1284
|
+
return result;
|
|
1285
|
+
}
|
|
1286
|
+
const activate = () => afterConnectionChange(() => AnsightNative.activate());
|
|
1287
|
+
async function deactivate() {
|
|
1288
|
+
stopLifecycleTracking();
|
|
1289
|
+
return afterConnectionChange(() => AnsightNative.deactivate());
|
|
1290
|
+
}
|
|
1291
|
+
const clear = () => afterConnectionChange(() => AnsightNative.clear());
|
|
1292
|
+
const registerMetricChannel = (channel) => AnsightNative.registerMetricChannel({ channel });
|
|
1293
|
+
const metric = (value, channel = 255) => AnsightNative.recordMetric({ value, channel });
|
|
1294
|
+
const recordMetric = metric;
|
|
1295
|
+
function event(input) {
|
|
1296
|
+
return AnsightNative.recordEvent(typeof input === "string" ? { label: input } : input);
|
|
1297
|
+
}
|
|
1298
|
+
const recordEvent = event;
|
|
1299
|
+
const screenViewed = (name, details = {}) => AnsightNative.screenViewed({ name, details });
|
|
1300
|
+
const trackRoute = screenViewed;
|
|
1301
|
+
const setAppLifecycleState = (state) => AnsightNative.setAppLifecycleState({ state });
|
|
1302
|
+
function connect(pairingPayload, options = {}) {
|
|
1303
|
+
return afterConnectionChange(() => AnsightNative.connect({
|
|
1304
|
+
...options,
|
|
1305
|
+
pairingPayload: normalizePairingPayload(pairingPayload),
|
|
1306
|
+
}));
|
|
1307
|
+
}
|
|
1308
|
+
function scanPairingQrCode(options = {}) {
|
|
1309
|
+
return afterConnectionChange(() => AnsightNative.scanPairingQrCode(options));
|
|
1310
|
+
}
|
|
1311
|
+
function openSession(pairingPayload, options = {}) {
|
|
1312
|
+
return afterConnectionChange(() => AnsightNative.openSession({
|
|
1313
|
+
...options,
|
|
1314
|
+
pairingPayload: normalizePairingPayload(pairingPayload) ?? "",
|
|
1315
|
+
}));
|
|
1316
|
+
}
|
|
1317
|
+
const disconnect = () => afterConnectionChange(() => AnsightNative.disconnect());
|
|
1318
|
+
const completeSession = () => afterConnectionChange(() => AnsightNative.completeSession());
|
|
1319
|
+
const closeSession = () => afterConnectionChange(() => AnsightNative.closeSession());
|
|
1320
|
+
const savePairingConfig = (pairingPayload, options = {}) => afterConnectionChange(() => AnsightNative.savePairingConfig({
|
|
1321
|
+
...options,
|
|
1322
|
+
pairingPayload: normalizePairingPayload(pairingPayload) ?? "",
|
|
1323
|
+
}));
|
|
1324
|
+
const clearSavedPairing = () => afterConnectionChange(() => AnsightNative.clearSavedPairing());
|
|
1325
|
+
const clearSavedPairingConfig = clearSavedPairing;
|
|
1326
|
+
const clearCachedSession = () => afterConnectionChange(() => AnsightNative.clearCachedSession());
|
|
1327
|
+
const notifyHostConnectionConfigChanged = () => afterConnectionChange(() => AnsightNative.notifyHostConnectionConfigChanged());
|
|
1328
|
+
const status = () => AnsightNative.status();
|
|
1329
|
+
const snapshot = () => AnsightNative.snapshot();
|
|
1330
|
+
const hostConnectionStatus = () => AnsightNative.hostConnectionStatus();
|
|
1331
|
+
const hostConnectionCapabilities = () => AnsightNative.hostConnectionCapabilities();
|
|
1332
|
+
const currentOptions = () => AnsightNative.currentOptions();
|
|
1333
|
+
async function recordedMetrics(limit = 0) {
|
|
1334
|
+
return (await AnsightNative.recordedMetrics({ limit })).items;
|
|
1335
|
+
}
|
|
1336
|
+
async function recordedEvents(limit = 0) {
|
|
1337
|
+
return (await AnsightNative.recordedEvents({ limit })).items;
|
|
1338
|
+
}
|
|
1339
|
+
const sendClientLog = (line) => AnsightNative.sendClientLog({ line });
|
|
1340
|
+
const captureBuiltInTelemetrySample = () => AnsightNative.captureBuiltInTelemetrySample();
|
|
1341
|
+
async function isFramesPerSecondEnabled() {
|
|
1342
|
+
return (await AnsightNative.isFramesPerSecondEnabled()).value;
|
|
1343
|
+
}
|
|
1344
|
+
const enableFramesPerSecond = () => AnsightNative.enableFramesPerSecond();
|
|
1345
|
+
const disableFramesPerSecond = () => AnsightNative.disableFramesPerSecond();
|
|
1346
|
+
const captureScreenFrame = (options = {}) => AnsightNative.captureScreenFrame(options);
|
|
1347
|
+
const enableTouchCapture = () => AnsightNative.enableTouchCapture();
|
|
1348
|
+
const disableTouchCapture = () => AnsightNative.disableTouchCapture();
|
|
1349
|
+
const updateSessionProperties = (properties) => AnsightNative.updateSessionProperties({ properties });
|
|
1350
|
+
const updateCustomProperties = updateSessionProperties;
|
|
1351
|
+
const clearSessionProperties = () => AnsightNative.clearSessionProperties();
|
|
1352
|
+
const clearCustomProperties = clearSessionProperties;
|
|
1353
|
+
const registerCustomProperty = (group, key, value) => AnsightNative.registerCustomProperty({ group, key, value });
|
|
1354
|
+
const removeCustomProperty = (group, key) => AnsightNative.removeCustomProperty({ group, key });
|
|
1355
|
+
function addHostConnectionStatusListener(listener, options = {}) {
|
|
1356
|
+
hostConnectionListeners.add(listener);
|
|
1357
|
+
if (options.emitCurrent !== false)
|
|
1358
|
+
void emitHostConnectionStatus();
|
|
1359
|
+
return {
|
|
1360
|
+
remove: () => {
|
|
1361
|
+
hostConnectionListeners.delete(listener);
|
|
1362
|
+
},
|
|
1363
|
+
};
|
|
1364
|
+
}
|
|
1365
|
+
function addLogListener(listener) {
|
|
1366
|
+
logListeners.add(listener);
|
|
1367
|
+
void ensureLogListener();
|
|
1368
|
+
return {
|
|
1369
|
+
remove: () => {
|
|
1370
|
+
logListeners.delete(listener);
|
|
1371
|
+
},
|
|
1372
|
+
};
|
|
1373
|
+
}
|
|
1374
|
+
function registerTool(definition, handler) {
|
|
1375
|
+
if (!definition?.id?.trim())
|
|
1376
|
+
throw new TypeError("registerTool requires a stable string id.");
|
|
1377
|
+
if (typeof handler !== "function")
|
|
1378
|
+
throw new TypeError("registerTool requires a handler function.");
|
|
1379
|
+
toolHandlers.set(definition.id, handler);
|
|
1380
|
+
const ready = ensureToolListener()
|
|
1381
|
+
.then(() => AnsightNative.registerCustomTool({ definition }))
|
|
1382
|
+
.catch((error) => {
|
|
1383
|
+
toolHandlers.delete(definition.id);
|
|
1384
|
+
throw error;
|
|
1385
|
+
});
|
|
1386
|
+
return {
|
|
1387
|
+
id: definition.id,
|
|
1388
|
+
ready,
|
|
1389
|
+
unregister: async () => {
|
|
1390
|
+
toolHandlers.delete(definition.id);
|
|
1391
|
+
return AnsightNative.unregisterCustomTool({ id: definition.id });
|
|
1392
|
+
},
|
|
1393
|
+
};
|
|
1394
|
+
}
|
|
1395
|
+
function unregisterTool(id) {
|
|
1396
|
+
toolHandlers.delete(id);
|
|
1397
|
+
return AnsightNative.unregisterCustomTool({ id });
|
|
1398
|
+
}
|
|
1399
|
+
const listRegisteredTools = () => [...toolHandlers.keys()];
|
|
1400
|
+
async function clearRegisteredTools() {
|
|
1401
|
+
toolHandlers.clear();
|
|
1402
|
+
artifactProviders.clear();
|
|
1403
|
+
artifactToolRegistrations = [];
|
|
1404
|
+
domToolRegistration = undefined;
|
|
1405
|
+
return AnsightNative.clearRegisteredCustomTools();
|
|
1406
|
+
}
|
|
1407
|
+
function bytesToBase64(bytes) {
|
|
1408
|
+
let binary = "";
|
|
1409
|
+
for (let offset = 0; offset < bytes.length; offset += 0x8000) {
|
|
1410
|
+
binary += String.fromCharCode(...bytes.subarray(offset, offset + 0x8000));
|
|
1411
|
+
}
|
|
1412
|
+
return btoa(binary);
|
|
1413
|
+
}
|
|
1414
|
+
function payloadBytes(payload) {
|
|
1415
|
+
if (payload instanceof Uint8Array)
|
|
1416
|
+
return payload;
|
|
1417
|
+
if (payload instanceof ArrayBuffer)
|
|
1418
|
+
return new Uint8Array(payload);
|
|
1419
|
+
if (Array.isArray(payload))
|
|
1420
|
+
return Uint8Array.from(payload);
|
|
1421
|
+
if (typeof payload === "object" && payload) {
|
|
1422
|
+
const candidate = payload.bytes ?? payload.data;
|
|
1423
|
+
if (candidate instanceof Uint8Array)
|
|
1424
|
+
return candidate;
|
|
1425
|
+
if (candidate instanceof ArrayBuffer)
|
|
1426
|
+
return new Uint8Array(candidate);
|
|
1427
|
+
if (Array.isArray(candidate))
|
|
1428
|
+
return Uint8Array.from(candidate);
|
|
1429
|
+
}
|
|
1430
|
+
return undefined;
|
|
1431
|
+
}
|
|
1432
|
+
function installArtifactTools() {
|
|
1433
|
+
if (artifactToolRegistrations.length > 0)
|
|
1434
|
+
return artifactToolRegistrations;
|
|
1435
|
+
artifactToolRegistrations = [
|
|
1436
|
+
registerTool({
|
|
1437
|
+
id: "artifacts.query",
|
|
1438
|
+
name: "Query JavaScript artifacts",
|
|
1439
|
+
description: "Lists artifacts exposed by Capacitor JavaScript providers.",
|
|
1440
|
+
category: "Artifacts",
|
|
1441
|
+
scope: "read",
|
|
1442
|
+
}, async (_args, context) => {
|
|
1443
|
+
const definitions = [];
|
|
1444
|
+
for (const provider of artifactProviders.values()) {
|
|
1445
|
+
const query = provider.queryArtifacts ?? provider.query;
|
|
1446
|
+
const artifacts = query
|
|
1447
|
+
? await query({
|
|
1448
|
+
toolRequestId: context.nativeRequestId ?? context.requestId,
|
|
1449
|
+
sessionId: context.sessionId,
|
|
1450
|
+
queriedAtUtc: new Date().toISOString(),
|
|
1451
|
+
})
|
|
1452
|
+
: [];
|
|
1453
|
+
definitions.push(...artifacts.map((artifact) => ({
|
|
1454
|
+
...artifact,
|
|
1455
|
+
providerId: provider.descriptor.id,
|
|
1456
|
+
})));
|
|
1457
|
+
}
|
|
1458
|
+
return {
|
|
1459
|
+
success: true,
|
|
1460
|
+
message: `Found ${definitions.length} artifact(s).`,
|
|
1461
|
+
result: {
|
|
1462
|
+
providers: [...artifactProviders.values()].map(({ descriptor }) => descriptor),
|
|
1463
|
+
artifacts: definitions,
|
|
1464
|
+
},
|
|
1465
|
+
};
|
|
1466
|
+
}),
|
|
1467
|
+
registerTool({
|
|
1468
|
+
id: "artifacts.request",
|
|
1469
|
+
name: "Request JavaScript artifact",
|
|
1470
|
+
description: "Creates an artifact through a Capacitor JavaScript provider.",
|
|
1471
|
+
category: "Artifacts",
|
|
1472
|
+
scope: "read",
|
|
1473
|
+
argumentsSchema: {
|
|
1474
|
+
type: "object",
|
|
1475
|
+
required: ["providerId", "artifactId"],
|
|
1476
|
+
properties: {
|
|
1477
|
+
providerId: { type: "string" },
|
|
1478
|
+
artifactId: { type: "string" },
|
|
1479
|
+
},
|
|
1480
|
+
},
|
|
1481
|
+
}, async (args, context) => {
|
|
1482
|
+
const provider = artifactProviders.get(args.providerId);
|
|
1483
|
+
const create = provider && (provider.createArtifact ?? provider.create);
|
|
1484
|
+
if (!provider || !create) {
|
|
1485
|
+
return {
|
|
1486
|
+
success: false,
|
|
1487
|
+
message: `Artifact provider '${args.providerId}' is unavailable.`,
|
|
1488
|
+
errorCode: "artifact_provider_not_found",
|
|
1489
|
+
};
|
|
1490
|
+
}
|
|
1491
|
+
const result = await create({
|
|
1492
|
+
providerId: args.providerId,
|
|
1493
|
+
artifactId: args.artifactId,
|
|
1494
|
+
arguments: args,
|
|
1495
|
+
context: {
|
|
1496
|
+
toolRequestId: context.nativeRequestId ?? context.requestId,
|
|
1497
|
+
sessionId: context.sessionId,
|
|
1498
|
+
requestedAtUtc: new Date().toISOString(),
|
|
1499
|
+
},
|
|
1500
|
+
});
|
|
1501
|
+
const bytes = payloadBytes(result.payload);
|
|
1502
|
+
if (bytes) {
|
|
1503
|
+
const transfer = await AnsightNative.queueBinaryTransfer({
|
|
1504
|
+
requestId: context.nativeRequestId ?? context.requestId,
|
|
1505
|
+
base64Data: bytesToBase64(bytes),
|
|
1506
|
+
chunkBytes: 64 * 1024,
|
|
1507
|
+
});
|
|
1508
|
+
return {
|
|
1509
|
+
success: transfer.success,
|
|
1510
|
+
message: transfer.message,
|
|
1511
|
+
result: { metadata: result.metadata, transfer },
|
|
1512
|
+
...(!transfer.success && {
|
|
1513
|
+
errorCode: "artifact_transfer_unavailable",
|
|
1514
|
+
}),
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
const payload = typeof result.payload === "object" &&
|
|
1518
|
+
result.payload &&
|
|
1519
|
+
"text" in result.payload
|
|
1520
|
+
? result.payload.text
|
|
1521
|
+
: result.payload;
|
|
1522
|
+
return {
|
|
1523
|
+
success: true,
|
|
1524
|
+
message: `Artifact '${args.artifactId}' created.`,
|
|
1525
|
+
result: { metadata: result.metadata, payload },
|
|
1526
|
+
};
|
|
1527
|
+
}),
|
|
1528
|
+
];
|
|
1529
|
+
return artifactToolRegistrations;
|
|
1530
|
+
}
|
|
1531
|
+
function registerArtifactProvider(provider) {
|
|
1532
|
+
const id = provider?.descriptor?.id?.trim();
|
|
1533
|
+
if (!id)
|
|
1534
|
+
throw new TypeError("registerArtifactProvider requires descriptor.id.");
|
|
1535
|
+
artifactProviders.set(id, provider);
|
|
1536
|
+
const registrations = installArtifactTools();
|
|
1537
|
+
return {
|
|
1538
|
+
id,
|
|
1539
|
+
ready: Promise.all(registrations.map(({ ready }) => ready)).then(() => ({
|
|
1540
|
+
success: true,
|
|
1541
|
+
message: `Artifact provider '${id}' registered.`,
|
|
1542
|
+
})),
|
|
1543
|
+
unregister: () => unregisterArtifactProvider(id),
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
const registerArtifactProviders = (providers) => providers.map(registerArtifactProvider);
|
|
1547
|
+
async function unregisterArtifactProvider(id) {
|
|
1548
|
+
artifactProviders.delete(id);
|
|
1549
|
+
if (artifactProviders.size === 0) {
|
|
1550
|
+
const registrations = artifactToolRegistrations;
|
|
1551
|
+
artifactToolRegistrations = [];
|
|
1552
|
+
await Promise.all(registrations.map(({ unregister }) => unregister()));
|
|
1553
|
+
}
|
|
1554
|
+
return { success: true, message: `Artifact provider '${id}' unregistered.` };
|
|
1555
|
+
}
|
|
1556
|
+
const listRegisteredArtifactProviders = () => [...artifactProviders.values()].map(({ descriptor }) => descriptor);
|
|
1557
|
+
async function clearArtifactProviders() {
|
|
1558
|
+
artifactProviders.clear();
|
|
1559
|
+
const registrations = artifactToolRegistrations;
|
|
1560
|
+
artifactToolRegistrations = [];
|
|
1561
|
+
await Promise.all(registrations.map(({ unregister }) => unregister()));
|
|
1562
|
+
return { success: true, message: "JavaScript artifact providers cleared." };
|
|
1563
|
+
}
|
|
1564
|
+
function installDomTools(options = {}) {
|
|
1565
|
+
domToolRegistration ??= installDomTools$1(registerTool, options);
|
|
1566
|
+
return domToolRegistration;
|
|
1567
|
+
}
|
|
1568
|
+
async function uninstallDomTools() {
|
|
1569
|
+
const registration = domToolRegistration;
|
|
1570
|
+
domToolRegistration = undefined;
|
|
1571
|
+
return registration ? registration.unregister() : [];
|
|
1572
|
+
}
|
|
1573
|
+
function startLifecycleTracking() {
|
|
1574
|
+
if (lifecycleCleanup || typeof document === "undefined")
|
|
1575
|
+
return;
|
|
1576
|
+
const update = () => void setAppLifecycleState(document.visibilityState === "visible" ? "foreground" : "background");
|
|
1577
|
+
document.addEventListener("visibilitychange", update);
|
|
1578
|
+
window.addEventListener("pageshow", update);
|
|
1579
|
+
window.addEventListener("pagehide", update);
|
|
1580
|
+
lifecycleCleanup = () => {
|
|
1581
|
+
document.removeEventListener("visibilitychange", update);
|
|
1582
|
+
window.removeEventListener("pageshow", update);
|
|
1583
|
+
window.removeEventListener("pagehide", update);
|
|
1584
|
+
};
|
|
1585
|
+
update();
|
|
1586
|
+
}
|
|
1587
|
+
function stopLifecycleTracking() {
|
|
1588
|
+
lifecycleCleanup?.();
|
|
1589
|
+
lifecycleCleanup = undefined;
|
|
1590
|
+
}
|
|
1591
|
+
const startAppStateTracking = startLifecycleTracking;
|
|
1592
|
+
const stopAppStateTracking = stopLifecycleTracking;
|
|
1593
|
+
function installErrorHandlers(options = {}) {
|
|
1594
|
+
const captureErrors = options.errors ?? true;
|
|
1595
|
+
const captureRejections = options.unhandledRejections ?? true;
|
|
1596
|
+
const captureConsole = options.consoleErrors ?? false;
|
|
1597
|
+
const onError = (eventValue) => {
|
|
1598
|
+
if (!captureErrors)
|
|
1599
|
+
return;
|
|
1600
|
+
void event({
|
|
1601
|
+
label: eventValue.message || "Unhandled JavaScript error",
|
|
1602
|
+
type: "Exception",
|
|
1603
|
+
details: JSON.stringify({
|
|
1604
|
+
filename: eventValue.filename,
|
|
1605
|
+
line: eventValue.lineno,
|
|
1606
|
+
column: eventValue.colno,
|
|
1607
|
+
stack: eventValue.error instanceof Error
|
|
1608
|
+
? eventValue.error.stack
|
|
1609
|
+
: undefined,
|
|
1610
|
+
}),
|
|
1611
|
+
}).catch(() => undefined);
|
|
1612
|
+
};
|
|
1613
|
+
const onRejection = (eventValue) => {
|
|
1614
|
+
if (!captureRejections)
|
|
1615
|
+
return;
|
|
1616
|
+
const reason = eventValue.reason;
|
|
1617
|
+
void event({
|
|
1618
|
+
label: reason instanceof Error
|
|
1619
|
+
? reason.message
|
|
1620
|
+
: "Unhandled JavaScript rejection",
|
|
1621
|
+
type: "Exception",
|
|
1622
|
+
details: JSON.stringify({
|
|
1623
|
+
reason: reason instanceof Error ? reason.stack : String(reason),
|
|
1624
|
+
}),
|
|
1625
|
+
}).catch(() => undefined);
|
|
1626
|
+
};
|
|
1627
|
+
window.addEventListener("error", onError);
|
|
1628
|
+
window.addEventListener("unhandledrejection", onRejection);
|
|
1629
|
+
const originalConsoleError = console.error;
|
|
1630
|
+
if (captureConsole) {
|
|
1631
|
+
console.error = (...args) => {
|
|
1632
|
+
originalConsoleError(...args);
|
|
1633
|
+
void event({
|
|
1634
|
+
label: "console.error",
|
|
1635
|
+
type: "Exception",
|
|
1636
|
+
details: args.map(String).join(" "),
|
|
1637
|
+
}).catch(() => undefined);
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1640
|
+
return () => {
|
|
1641
|
+
window.removeEventListener("error", onError);
|
|
1642
|
+
window.removeEventListener("unhandledrejection", onRejection);
|
|
1643
|
+
if (captureConsole)
|
|
1644
|
+
console.error = originalConsoleError;
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1647
|
+
function createRouteTracker(options = {}) {
|
|
1648
|
+
const resolveName = options.resolveName ?? ((url) => url.pathname + url.search + url.hash);
|
|
1649
|
+
const record = () => void screenViewed(resolveName(new URL(location.href)), options.details);
|
|
1650
|
+
const originalPushState = history.pushState.bind(history);
|
|
1651
|
+
const originalReplaceState = history.replaceState.bind(history);
|
|
1652
|
+
const onPopState = () => record();
|
|
1653
|
+
window.addEventListener("popstate", onPopState);
|
|
1654
|
+
window.addEventListener("hashchange", onPopState);
|
|
1655
|
+
if (options.observeHistory !== false) {
|
|
1656
|
+
history.pushState = (...args) => {
|
|
1657
|
+
originalPushState(...args);
|
|
1658
|
+
record();
|
|
1659
|
+
};
|
|
1660
|
+
history.replaceState = (...args) => {
|
|
1661
|
+
originalReplaceState(...args);
|
|
1662
|
+
record();
|
|
1663
|
+
};
|
|
1664
|
+
}
|
|
1665
|
+
record();
|
|
1666
|
+
return {
|
|
1667
|
+
remove: () => {
|
|
1668
|
+
window.removeEventListener("popstate", onPopState);
|
|
1669
|
+
window.removeEventListener("hashchange", onPopState);
|
|
1670
|
+
history.pushState = originalPushState;
|
|
1671
|
+
history.replaceState = originalReplaceState;
|
|
1672
|
+
},
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
const Ansight = {
|
|
1676
|
+
initialize,
|
|
1677
|
+
initializeAndActivate,
|
|
1678
|
+
activate,
|
|
1679
|
+
deactivate,
|
|
1680
|
+
clear,
|
|
1681
|
+
registerMetricChannel,
|
|
1682
|
+
metric,
|
|
1683
|
+
recordMetric,
|
|
1684
|
+
event,
|
|
1685
|
+
recordEvent,
|
|
1686
|
+
screenViewed,
|
|
1687
|
+
trackRoute,
|
|
1688
|
+
setAppLifecycleState,
|
|
1689
|
+
connect,
|
|
1690
|
+
scanPairingQrCode,
|
|
1691
|
+
openSession,
|
|
1692
|
+
disconnect,
|
|
1693
|
+
completeSession,
|
|
1694
|
+
closeSession,
|
|
1695
|
+
savePairingConfig,
|
|
1696
|
+
clearSavedPairing,
|
|
1697
|
+
clearSavedPairingConfig,
|
|
1698
|
+
clearCachedSession,
|
|
1699
|
+
notifyHostConnectionConfigChanged,
|
|
1700
|
+
status,
|
|
1701
|
+
snapshot,
|
|
1702
|
+
hostConnectionStatus,
|
|
1703
|
+
hostConnectionCapabilities,
|
|
1704
|
+
addHostConnectionStatusListener,
|
|
1705
|
+
currentOptions,
|
|
1706
|
+
recordedMetrics,
|
|
1707
|
+
recordedEvents,
|
|
1708
|
+
sendClientLog,
|
|
1709
|
+
addLogListener,
|
|
1710
|
+
captureBuiltInTelemetrySample,
|
|
1711
|
+
isFramesPerSecondEnabled,
|
|
1712
|
+
enableFramesPerSecond,
|
|
1713
|
+
disableFramesPerSecond,
|
|
1714
|
+
captureScreenFrame,
|
|
1715
|
+
enableTouchCapture,
|
|
1716
|
+
disableTouchCapture,
|
|
1717
|
+
updateSessionProperties,
|
|
1718
|
+
updateCustomProperties,
|
|
1719
|
+
clearSessionProperties,
|
|
1720
|
+
registerCustomProperty,
|
|
1721
|
+
removeCustomProperty,
|
|
1722
|
+
clearCustomProperties,
|
|
1723
|
+
registerTool,
|
|
1724
|
+
unregisterTool,
|
|
1725
|
+
listRegisteredTools,
|
|
1726
|
+
clearRegisteredTools,
|
|
1727
|
+
registerArtifactProvider,
|
|
1728
|
+
registerArtifactProviders,
|
|
1729
|
+
unregisterArtifactProvider,
|
|
1730
|
+
listRegisteredArtifactProviders,
|
|
1731
|
+
clearArtifactProviders,
|
|
1732
|
+
installDomTools,
|
|
1733
|
+
uninstallDomTools,
|
|
1734
|
+
installErrorHandlers,
|
|
1735
|
+
createRouteTracker,
|
|
1736
|
+
startLifecycleTracking,
|
|
1737
|
+
stopLifecycleTracking,
|
|
1738
|
+
startAppStateTracking,
|
|
1739
|
+
stopAppStateTracking,
|
|
1740
|
+
createOptionsBuilder,
|
|
1741
|
+
AnsightOptionsBuilder,
|
|
1742
|
+
native: AnsightNative,
|
|
1743
|
+
platform: Capacitor.getPlatform(),
|
|
1744
|
+
};
|
|
1745
|
+
|
|
1746
|
+
if (typeof window !== "undefined") {
|
|
1747
|
+
const options = Ansight.createOptionsBuilder(globalThis.__ANSIGHT_CAPACITOR_STANDALONE_OPTIONS__ ?? {})
|
|
1748
|
+
.withAnsightDefaults()
|
|
1749
|
+
.withAllToolAccess()
|
|
1750
|
+
.withVisualTreeTools()
|
|
1751
|
+
.withFileSystemTools()
|
|
1752
|
+
.withDatabaseTools()
|
|
1753
|
+
.withPreferencesTools()
|
|
1754
|
+
.withReflectionTools()
|
|
1755
|
+
.withDomTools()
|
|
1756
|
+
.withErrorCapture()
|
|
1757
|
+
.build();
|
|
1758
|
+
void Ansight.initializeAndActivate(options).catch((error) => {
|
|
1759
|
+
console.error("[Ansight Capacitor]", error);
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
})();
|
|
1764
|
+
//# sourceMappingURL=standalone.js.map
|