@flareapp/vue 1.2.0 → 2.0.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/.oxlintrc.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "../../node_modules/oxlint/configuration_schema.json",
3
+ "extends": ["../../.oxlintrc.json"],
4
+ "plugins": ["vue"],
5
+ "env": {
6
+ "browser": true
7
+ }
8
+ }
package/CHANGELOG.md CHANGED
@@ -1,12 +1,23 @@
1
- # @flareapp/vue
1
+ ## 2.0.0
2
2
 
3
- ## 1.2.0
3
+ ### Breaking changes
4
4
 
5
- ### Changed
6
- - Peer dependency on `@flareapp/js` tightened from `^1.0.0` to `^1.2.0`. Consumers must upgrade `@flareapp/js` in lock-step so the v2-wire-format mapper is present at the egress boundary.
5
+ - Bumps peer dependency `@flareapp/js` to `^2.0.0`. See its CHANGELOG for wire format changes.
6
+ - `flareVue` no longer passes a third `extraSolutionParameters` arg to `flare.report`.
7
+ - Vue error context now lands on the report as `attributes['context.custom'].vue.*` (was nested under `context.vue.*`). Key fields: `vue.info`, `vue.errorOrigin`, `vue.componentName`, `vue.componentHierarchy`, `vue.componentHierarchyFrames`, `vue.componentProps`, `vue.route`.
8
+ - `vue-router` moved from a required to an optional peer dependency.
9
+ - Dropped Vue 2 support. Only Vue 3 (`^3.0.0`) is supported.
7
10
 
8
- No functional changes in this package.
11
+ ### New
9
12
 
10
- ## 1.0.1
11
-
12
- Initial release tracked here. Prior history is in git.
13
+ - **`FlareErrorBoundary` component.** Vue equivalent of the React error boundary. Catches errors in its subtree via `onErrorCaptured`, reports to Flare with full Vue context, and renders a `#fallback` slot with `error`, `componentProps`, `componentHierarchy`, `componentHierarchyFrames`, and `resetErrorBoundary`. Supports `resetKeys` for auto-reset and `onReset` callback.
14
+ - **Lifecycle hooks on `flareVue()`.** `beforeEvaluate`, `beforeSubmit`, and `afterSubmit` options give control over the report pipeline at the app level.
15
+ - **`captureWarnings` option.** When enabled, Vue warnings are reported via `flare.reportMessage()` at `warning` level.
16
+ - **Prop serialization.** `attachProps` (boolean), `propsMaxDepth` (number), `propsDenylist` (regex), and `replaceDefaultDenylist` (boolean) control which component props are included in reports. `DEFAULT_PROPS_DENYLIST` is exported.
17
+ - **Component hierarchy frames.** Reports include structured `componentHierarchyFrames` with component name, file path, and serialized props per frame.
18
+ - Route context is automatically captured from `app.config.globalProperties.$router` when an error occurs. No explicit router option needed.
19
+ - Non-`Error` values are coerced to `Error`.
20
+ - Chains existing `app.config.errorHandler` instead of replacing it silently.
21
+ - Duplicate-install guard prevents double-reporting when `app.use(flareVue)` is called more than once.
22
+ - The package self-identifies via `flare.setSdkInfo({ name: '@flareapp/vue', version })` and `flare.setFramework({ name: 'Vue', version: app.version })` on install.
23
+ - New exported types: `ComponentHierarchyFrame`, `ErrorOrigin`, `FlareErrorBoundaryFallbackProps`, `FlareErrorBoundaryHookParams`, `FlareVueContext`, `FlareVueOptions`, `FlareVueWarningContext`, `RouteContext`, `RouteParamValue`, `RouteQueryValue`.
package/README.md CHANGED
@@ -1,5 +1,41 @@
1
- # The JavaScript client for Flare to catch frontend errors
1
+ # @flareapp/vue
2
2
 
3
- Read the JavaScript error tracking section in [the Flare documentation](https://flareapp.io/docs/javascript-error-tracking/installation) for more information.
3
+ Vue integration for [Flare](https://flareapp.io) error tracking. Installs a Vue error handler that catches component errors and reports them to Flare with Vue-specific context (component name, lifecycle info).
4
4
 
5
- Flare client: https://www.npmjs.com/package/@flareapp/js
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @flareapp/vue @flareapp/js
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ Initialize the Flare client and register the Vue error handler:
14
+
15
+ ```js
16
+ import { createApp } from 'vue';
17
+ import { flare } from '@flareapp/js';
18
+ import { flareVue } from '@flareapp/vue';
19
+
20
+ import App from './App.vue';
21
+
22
+ flare.light('YOUR_FLARE_API_KEY');
23
+
24
+ const app = createApp(App);
25
+
26
+ flareVue(app);
27
+
28
+ app.mount('#app');
29
+ ```
30
+
31
+ ## Documentation
32
+
33
+ Full documentation on the Vue error handler and its options is available at [flareapp.io/docs/vue/general/installation](https://flareapp.io/docs/vue/general/installation).
34
+
35
+ ## Compatibility
36
+
37
+ - Vue 3
38
+
39
+ ## License
40
+
41
+ The MIT License (MIT). Please see [License File](../../LICENSE.md) for more information.
package/dist/index.cjs ADDED
@@ -0,0 +1,445 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ let _flareapp_js = require("@flareapp/js");
3
+ let vue = require("vue");
4
+
5
+ //#region src/constants.ts
6
+ const PACKAGE_VERSION = typeof process !== "undefined" && typeof process.env?.PACKAGE_VERSION !== "undefined" ? process.env.PACKAGE_VERSION : "?";
7
+ const MAX_HIERARCHY_DEPTH = 50;
8
+ const DEFAULT_PROPS_DENYLIST = /password|passwd|pwd|token|secret|authorization|\bauth\b|bearer|oauth|credentials?|cookie|api[-_]?key|private[-_]?key|session|csrf|xsrf|\bpin\b|\bssn\b|card[-_]?number|\bcvv\b/i;
9
+ function resolveDenylist(custom, replaceDefault = false) {
10
+ return (0, _flareapp_js.resolveDenylist)(custom, replaceDefault, DEFAULT_PROPS_DENYLIST);
11
+ }
12
+ const MAX_PROP_STRING_LENGTH = 1e3;
13
+ const MAX_PROP_ARRAY_LENGTH = 100;
14
+ const MAX_PROP_OBJECT_KEYS = 100;
15
+ const INFO_TO_ORIGIN = {
16
+ "setup function": "setup",
17
+ "render function": "render",
18
+ "component update": "render",
19
+ "watcher getter": "watcher",
20
+ "watcher callback": "watcher",
21
+ "watcher cleanup function": "watcher",
22
+ "native event handler": "event",
23
+ "component event handler": "event",
24
+ "beforeCreate hook": "lifecycle",
25
+ "created hook": "lifecycle",
26
+ "beforeMount hook": "lifecycle",
27
+ "mounted hook": "lifecycle",
28
+ "beforeUpdate hook": "lifecycle",
29
+ "updated hook": "lifecycle",
30
+ "beforeUnmount hook": "lifecycle",
31
+ "unmounted hook": "lifecycle",
32
+ "activated hook": "lifecycle",
33
+ "deactivated hook": "lifecycle",
34
+ "errorCaptured hook": "lifecycle",
35
+ "renderTracked hook": "lifecycle",
36
+ "renderTriggered hook": "lifecycle",
37
+ "serverPrefetch hook": "lifecycle",
38
+ "vnode hook": "lifecycle",
39
+ "directive hook": "lifecycle",
40
+ "transition hook": "lifecycle",
41
+ "ref function": "setup",
42
+ "async component loader": "setup",
43
+ "scheduler flush": "render",
44
+ "app errorHandler": "lifecycle",
45
+ "app warnHandler": "lifecycle",
46
+ "app unmount cleanup function": "lifecycle",
47
+ "0": "setup",
48
+ "1": "render",
49
+ "2": "watcher",
50
+ "3": "watcher",
51
+ "4": "watcher",
52
+ "5": "event",
53
+ "6": "event",
54
+ "7": "lifecycle",
55
+ "8": "lifecycle",
56
+ "9": "lifecycle",
57
+ "10": "lifecycle",
58
+ "11": "lifecycle",
59
+ "12": "setup",
60
+ "13": "setup",
61
+ "14": "render",
62
+ "15": "render",
63
+ "16": "lifecycle",
64
+ "sp": "lifecycle",
65
+ "bc": "lifecycle",
66
+ "c": "lifecycle",
67
+ "bm": "lifecycle",
68
+ "m": "lifecycle",
69
+ "bu": "lifecycle",
70
+ "u": "lifecycle",
71
+ "bum": "lifecycle",
72
+ "um": "lifecycle",
73
+ "a": "lifecycle",
74
+ "da": "lifecycle",
75
+ "ec": "lifecycle",
76
+ "rtc": "lifecycle",
77
+ "rtg": "lifecycle"
78
+ };
79
+
80
+ //#endregion
81
+ //#region src/getComponentName.ts
82
+ function getComponentName(instance) {
83
+ if (!instance) return "AnonymousComponent";
84
+ const options = instance.$options;
85
+ return options.__name || options.name || "AnonymousComponent";
86
+ }
87
+
88
+ //#endregion
89
+ //#region src/buildComponentHierarchy.ts
90
+ function buildComponentHierarchy(instance) {
91
+ const hierarchy = [];
92
+ let current = instance;
93
+ while (current && hierarchy.length < MAX_HIERARCHY_DEPTH) {
94
+ hierarchy.push(getComponentName(current));
95
+ current = current.$parent;
96
+ }
97
+ return hierarchy;
98
+ }
99
+
100
+ //#endregion
101
+ //#region src/serializeProps.ts
102
+ function serializeProps(value, maxDepth, denylist = DEFAULT_PROPS_DENYLIST) {
103
+ return serialize(value, 0, maxDepth, /* @__PURE__ */ new WeakSet(), denylist);
104
+ }
105
+ function serialize(value, depth, maxDepth, seen, denylist) {
106
+ if (value === null) return null;
107
+ const type = typeof value;
108
+ if (type === "function") return "[Function]";
109
+ if (type === "symbol") return "[Symbol]";
110
+ if (type === "bigint") return value.toString();
111
+ if (type === "string") return truncateString(value);
112
+ if (type !== "object") return value;
113
+ if (seen.has(value)) return "[Circular]";
114
+ if (Array.isArray(value)) {
115
+ if (depth > maxDepth) return "[Array]";
116
+ seen.add(value);
117
+ const out = (value.length > MAX_PROP_ARRAY_LENGTH ? value.slice(0, MAX_PROP_ARRAY_LENGTH) : value).map((item) => serialize(item, depth + 1, maxDepth, seen, denylist));
118
+ if (value.length > MAX_PROP_ARRAY_LENGTH) out.push(`[… ${value.length - MAX_PROP_ARRAY_LENGTH} more items]`);
119
+ seen.delete(value);
120
+ return out;
121
+ }
122
+ if (!isPlainObject(value)) return "[Object]";
123
+ if (depth > maxDepth) return "[Object]";
124
+ seen.add(value);
125
+ const out = {};
126
+ const keys = Object.keys(value);
127
+ const limitedKeys = keys.length > MAX_PROP_OBJECT_KEYS ? keys.slice(0, MAX_PROP_OBJECT_KEYS) : keys;
128
+ for (const key of limitedKeys) {
129
+ if (denylist.test(key)) {
130
+ out[key] = "[redacted]";
131
+ continue;
132
+ }
133
+ out[key] = serialize(value[key], depth + 1, maxDepth, seen, denylist);
134
+ }
135
+ if (keys.length > MAX_PROP_OBJECT_KEYS) out["…"] = `[${keys.length - MAX_PROP_OBJECT_KEYS} more keys]`;
136
+ seen.delete(value);
137
+ return out;
138
+ }
139
+ function truncateString(value) {
140
+ if (value.length <= MAX_PROP_STRING_LENGTH) return value;
141
+ return `${value.slice(0, MAX_PROP_STRING_LENGTH)}…[truncated ${value.length - MAX_PROP_STRING_LENGTH} chars]`;
142
+ }
143
+ function isPlainObject(value) {
144
+ if (value === null || typeof value !== "object") return false;
145
+ const prototype = Object.getPrototypeOf(value);
146
+ return prototype === null || prototype === Object.prototype;
147
+ }
148
+
149
+ //#endregion
150
+ //#region src/buildComponentHierarchyFrames.ts
151
+ function buildComponentHierarchyFrames(instance, options) {
152
+ const frames = [];
153
+ let current = instance;
154
+ while (current && frames.length < MAX_HIERARCHY_DEPTH) {
155
+ const frameOptions = current.$options;
156
+ const frame = {
157
+ component: getComponentName(current),
158
+ file: frameOptions.__file ?? null
159
+ };
160
+ if (options.attachProps && current.$props) frame.props = serializeProps(current.$props, options.propsMaxDepth, options.propsDenylist);
161
+ frames.push(frame);
162
+ current = current.$parent;
163
+ }
164
+ return frames;
165
+ }
166
+
167
+ //#endregion
168
+ //#region src/convertToError.ts
169
+ function convertToError(error) {
170
+ if (error instanceof Error) return error;
171
+ if (typeof error === "string") return new Error(error);
172
+ return new Error(String(error));
173
+ }
174
+
175
+ //#endregion
176
+ //#region src/getErrorOrigin.ts
177
+ function getErrorOrigin(info) {
178
+ return INFO_TO_ORIGIN[info] ?? "unknown";
179
+ }
180
+
181
+ //#endregion
182
+ //#region src/getRouteContext.ts
183
+ const ROUTE_PARAMS_DEPTH = 2;
184
+ function getRouteContext(router, options = {}) {
185
+ if (!router || typeof router !== "object" || !("currentRoute" in router)) return null;
186
+ const currentRouteRef = router.currentRoute;
187
+ if (!currentRouteRef || typeof currentRouteRef !== "object" || !("value" in currentRouteRef)) return null;
188
+ const route = currentRouteRef.value;
189
+ if (!route || typeof route !== "object") return null;
190
+ const r = route;
191
+ const name = r.name;
192
+ const denylist = options.denylist ?? DEFAULT_PROPS_DENYLIST;
193
+ const params = r.params && typeof r.params === "object" ? r.params : {};
194
+ const query = r.query && typeof r.query === "object" ? r.query : {};
195
+ return {
196
+ name: typeof name === "string" ? name : typeof name === "symbol" ? name.toString() : null,
197
+ path: typeof r.path === "string" ? r.path : "",
198
+ fullPath: typeof r.fullPath === "string" ? (0, _flareapp_js.redactFullPath)(r.fullPath, denylist) : "",
199
+ params: serializeProps(params, ROUTE_PARAMS_DEPTH, denylist),
200
+ query: serializeProps(query, ROUTE_PARAMS_DEPTH, denylist),
201
+ hash: typeof r.hash === "string" ? r.hash : "",
202
+ matched: Array.isArray(r.matched) ? r.matched.map((record) => {
203
+ if (!record || typeof record !== "object") return "unknown";
204
+ const n = record.name;
205
+ return typeof n === "string" ? n : typeof n === "symbol" ? n.toString() : "unknown";
206
+ }) : []
207
+ };
208
+ }
209
+
210
+ //#endregion
211
+ //#region src/flareVue.ts
212
+ function vueContextToAttributes(context) {
213
+ const vue = {
214
+ info: context.vue.info,
215
+ errorOrigin: context.vue.errorOrigin,
216
+ componentName: context.vue.componentName,
217
+ componentHierarchy: context.vue.componentHierarchy,
218
+ componentHierarchyFrames: context.vue.componentHierarchyFrames
219
+ };
220
+ if (context.vue.componentProps) vue.componentProps = context.vue.componentProps;
221
+ if (context.vue.route) vue.route = context.vue.route;
222
+ return { "context.custom": {
223
+ framework: "vue",
224
+ vue
225
+ } };
226
+ }
227
+ function vueWarningContextToAttributes(context) {
228
+ const vue = {
229
+ type: context.vue.type,
230
+ info: context.vue.info,
231
+ componentName: context.vue.componentName,
232
+ componentTrace: context.vue.componentTrace
233
+ };
234
+ if (context.vue.route) vue.route = context.vue.route;
235
+ return { "context.custom": {
236
+ framework: "vue",
237
+ vue
238
+ } };
239
+ }
240
+ const installedApps = /* @__PURE__ */ new WeakSet();
241
+ const flareVue = (app, options) => {
242
+ if (installedApps.has(app)) return;
243
+ installedApps.add(app);
244
+ _flareapp_js.flare.setSdkInfo({
245
+ name: "@flareapp/vue",
246
+ version: PACKAGE_VERSION
247
+ });
248
+ _flareapp_js.flare.setFramework({
249
+ name: "Vue",
250
+ version: app.version
251
+ });
252
+ const attachProps = options?.attachProps ?? false;
253
+ const propsMaxDepth = options?.propsMaxDepth ?? 2;
254
+ const propsDenylist = resolveDenylist(options?.propsDenylist, options?.replaceDefaultDenylist);
255
+ const initialErrorHandler = app.config.errorHandler;
256
+ app.config.errorHandler = (error, instance, info) => {
257
+ const errorToReport = convertToError(error);
258
+ options?.beforeEvaluate?.({
259
+ error: errorToReport,
260
+ instance,
261
+ info
262
+ });
263
+ const errorOrigin = getErrorOrigin(info);
264
+ const componentName = getComponentName(instance);
265
+ const componentProps = attachProps && instance?.$props ? serializeProps(instance.$props, propsMaxDepth, propsDenylist) : void 0;
266
+ const componentHierarchy = buildComponentHierarchy(instance);
267
+ const componentHierarchyFrames = buildComponentHierarchyFrames(instance, {
268
+ attachProps,
269
+ propsMaxDepth,
270
+ propsDenylist
271
+ });
272
+ const route = getRouteContext(app.config.globalProperties.$router, { denylist: propsDenylist });
273
+ const context = { vue: {
274
+ info,
275
+ errorOrigin,
276
+ componentName,
277
+ ...componentProps && { componentProps },
278
+ componentHierarchy,
279
+ componentHierarchyFrames,
280
+ ...route && { route }
281
+ } };
282
+ const finalContext = options?.beforeSubmit?.({
283
+ error: errorToReport,
284
+ instance,
285
+ info,
286
+ context
287
+ }) ?? context;
288
+ Promise.resolve(_flareapp_js.flare.report(errorToReport, vueContextToAttributes(finalContext))).catch(() => {});
289
+ options?.afterSubmit?.({
290
+ error: errorToReport,
291
+ instance,
292
+ info,
293
+ context: finalContext
294
+ });
295
+ if (typeof initialErrorHandler === "function") {
296
+ initialErrorHandler(error, instance, info);
297
+ return;
298
+ }
299
+ console.error(error);
300
+ };
301
+ if (options?.captureWarnings) {
302
+ const initialWarnHandler = app.config.warnHandler;
303
+ app.config.warnHandler = (msg, instance, trace) => {
304
+ const componentName = getComponentName(instance);
305
+ const route = getRouteContext(app.config.globalProperties.$router, { denylist: propsDenylist });
306
+ const context = { vue: {
307
+ type: "warning",
308
+ info: msg,
309
+ componentName,
310
+ componentTrace: trace,
311
+ ...route && { route }
312
+ } };
313
+ Promise.resolve(_flareapp_js.flare.reportMessage(msg, "warning", vueWarningContextToAttributes(context))).catch(() => {});
314
+ if (typeof initialWarnHandler === "function") initialWarnHandler(msg, instance, trace);
315
+ };
316
+ }
317
+ };
318
+
319
+ //#endregion
320
+ //#region src/FlareErrorBoundary.ts
321
+ const FlareErrorBoundary = (0, vue.defineComponent)({
322
+ name: "FlareErrorBoundary",
323
+ props: {
324
+ beforeEvaluate: {
325
+ type: Function,
326
+ default: void 0
327
+ },
328
+ beforeSubmit: {
329
+ type: Function,
330
+ default: void 0
331
+ },
332
+ afterSubmit: {
333
+ type: Function,
334
+ default: void 0
335
+ },
336
+ onReset: {
337
+ type: Function,
338
+ default: void 0
339
+ },
340
+ resetKeys: {
341
+ type: Array,
342
+ default: void 0
343
+ },
344
+ attachProps: {
345
+ type: Boolean,
346
+ default: false
347
+ },
348
+ propsMaxDepth: {
349
+ type: Number,
350
+ default: 2
351
+ },
352
+ propsDenylist: {
353
+ type: RegExp,
354
+ default: void 0
355
+ },
356
+ replaceDefaultDenylist: {
357
+ type: Boolean,
358
+ default: false
359
+ }
360
+ },
361
+ setup(props, { slots }) {
362
+ const currentInstance = (0, vue.getCurrentInstance)();
363
+ const error = (0, vue.ref)(null);
364
+ const componentProps = (0, vue.ref)(void 0);
365
+ const componentHierarchy = (0, vue.ref)([]);
366
+ const componentHierarchyFrames = (0, vue.ref)([]);
367
+ const resetErrorBoundary = () => {
368
+ props.onReset?.(error.value);
369
+ error.value = null;
370
+ componentProps.value = void 0;
371
+ componentHierarchy.value = [];
372
+ componentHierarchyFrames.value = [];
373
+ };
374
+ (0, vue.watch)(() => props.resetKeys, (nextKeys, prevKeys) => {
375
+ if (error.value === null || !nextKeys || !prevKeys) return;
376
+ const lengthChanged = prevKeys.length !== nextKeys.length;
377
+ const valuesChanged = nextKeys.some((key, i) => !Object.is(key, prevKeys[i]));
378
+ if (lengthChanged || valuesChanged) resetErrorBoundary();
379
+ });
380
+ (0, vue.onErrorCaptured)((currentError, instance, info) => {
381
+ const errorToReport = convertToError(currentError);
382
+ props.beforeEvaluate?.({
383
+ error: errorToReport,
384
+ instance,
385
+ info
386
+ });
387
+ const resolvedDenylist = resolveDenylist(props.propsDenylist, props.replaceDefaultDenylist);
388
+ const hierarchy = buildComponentHierarchy(instance);
389
+ const hierarchyFrames = buildComponentHierarchyFrames(instance, {
390
+ attachProps: props.attachProps,
391
+ propsMaxDepth: props.propsMaxDepth,
392
+ propsDenylist: resolvedDenylist
393
+ });
394
+ const componentName = getComponentName(instance);
395
+ error.value = errorToReport;
396
+ const instanceProps = props.attachProps && instance?.$props ? serializeProps(instance.$props, props.propsMaxDepth, resolvedDenylist) : void 0;
397
+ const errorOrigin = getErrorOrigin(info);
398
+ const route = getRouteContext(currentInstance?.appContext.config.globalProperties.$router, { denylist: resolvedDenylist });
399
+ const context = { vue: {
400
+ info,
401
+ errorOrigin,
402
+ ...route && { route },
403
+ componentName,
404
+ ...instanceProps && { componentProps: instanceProps },
405
+ componentHierarchy: hierarchy,
406
+ componentHierarchyFrames: hierarchyFrames
407
+ } };
408
+ const finalContext = props.beforeSubmit?.({
409
+ error: errorToReport,
410
+ instance,
411
+ info,
412
+ context
413
+ }) ?? context;
414
+ componentProps.value = finalContext.vue.componentProps;
415
+ componentHierarchy.value = finalContext.vue.componentHierarchy;
416
+ componentHierarchyFrames.value = finalContext.vue.componentHierarchyFrames;
417
+ Promise.resolve(_flareapp_js.flare.report(errorToReport, vueContextToAttributes(finalContext))).catch(() => {});
418
+ props.afterSubmit?.({
419
+ error: errorToReport,
420
+ instance,
421
+ info,
422
+ context: finalContext
423
+ });
424
+ return false;
425
+ });
426
+ return () => {
427
+ if (error.value !== null) {
428
+ if (slots.fallback) return slots.fallback({
429
+ error: error.value,
430
+ ...componentProps.value && { componentProps: componentProps.value },
431
+ componentHierarchy: componentHierarchy.value,
432
+ componentHierarchyFrames: componentHierarchyFrames.value,
433
+ resetErrorBoundary
434
+ });
435
+ return null;
436
+ }
437
+ return slots.default?.();
438
+ };
439
+ }
440
+ });
441
+
442
+ //#endregion
443
+ exports.DEFAULT_PROPS_DENYLIST = DEFAULT_PROPS_DENYLIST;
444
+ exports.FlareErrorBoundary = FlareErrorBoundary;
445
+ exports.flareVue = flareVue;