@flareapp/svelte 2.11.0 → 2.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/getErrorOrigin.d.ts +0 -4
- package/dist/getErrorOrigin.js +4 -7
- package/dist/identify.d.ts +0 -2
- package/dist/identify.js +2 -2
- package/dist/inject.js +2 -3
- package/dist/preprocessor.js +15 -26
- package/dist/profileComponent.d.ts +0 -6
- package/dist/profileComponent.js +3 -6
- package/dist/resolveProfileName.d.ts +0 -9
- package/dist/resolveProfileName.js +8 -13
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -97,6 +97,15 @@ Profiling and component tracking are independent. You can run either on its own:
|
|
|
97
97
|
withFlareConfig(config, { componentTracking: false, profileComponents: [/\+page$/] });
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
+
### Self time
|
|
101
|
+
|
|
102
|
+
Every component span carries `flare.component.self_time_ns`: the span's duration minus the time its own
|
|
103
|
+
profiled children account for. Children that overlap in time are counted once, so the value never goes
|
|
104
|
+
below zero.
|
|
105
|
+
|
|
106
|
+
A child that mounts after its parent's span closed is not subtracted. Its work happened outside the
|
|
107
|
+
parent's window, so the parent keeps its full duration.
|
|
108
|
+
|
|
100
109
|
### Preprocessor ordering
|
|
101
110
|
|
|
102
111
|
Both features are injected by a Svelte preprocessor, which `withFlareConfig` installs for you. It parses
|
package/dist/getErrorOrigin.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
1
|
import type ErrorStackParser from 'error-stack-parser';
|
|
2
2
|
import type { SvelteErrorOrigin } from './types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Classify a parsed stack trace's error origin: 'event' (DOM handler), 'effect' (async side-effect),
|
|
5
|
-
* 'render' (component render phase), or 'unknown' (no frames or no recognizable pattern).
|
|
6
|
-
*/
|
|
7
3
|
export declare function getErrorOrigin(frames: ErrorStackParser.StackFrame[]): SvelteErrorOrigin;
|
package/dist/getErrorOrigin.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Checked in
|
|
3
|
-
// component wins over the .svelte filename check.
|
|
1
|
+
// The boundary catch site can't tell origins apart, so the stack trace is the only signal.
|
|
2
|
+
// Checked in order event > effect > render > unknown: an event handler wins over a .svelte match.
|
|
4
3
|
// Inline event handlers and DOM event API calls. Svelte compiles `onclick={handler}` to
|
|
5
4
|
// `.onclick = ...` or `addEventListener(...)`, so these match compiled output and manual DOM calls.
|
|
6
5
|
const EVENT_PATTERNS = [
|
|
@@ -28,10 +27,8 @@ const EVENT_PATTERNS = [
|
|
|
28
27
|
// Async side-effects: $effect callbacks (Svelte 5 schedules via queueMicrotask), onMount
|
|
29
28
|
// microtasks, promise continuations, MutationObserver callbacks. Not render-phase code.
|
|
30
29
|
const EFFECT_PATTERNS = [/queueMicrotask/, /Promise\.then/, /Promise\.catch/, /MutationObserver/];
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* 'render' (component render phase), or 'unknown' (no frames or no recognizable pattern).
|
|
34
|
-
*/
|
|
30
|
+
// Classify a parsed stack trace's error origin: 'event' (DOM handler), 'effect' (async side-effect),
|
|
31
|
+
// 'render' (component render phase), or 'unknown' (no frames or no recognizable pattern).
|
|
35
32
|
export function getErrorOrigin(frames) {
|
|
36
33
|
if (frames.length === 0) {
|
|
37
34
|
return 'unknown';
|
package/dist/identify.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import type { Flare } from '@flareapp/js/browser';
|
|
2
|
-
/** Web path: full identity on the default singleton. Svelte's framework has no version. */
|
|
3
2
|
export declare function registerSvelteSdkIdentity(flare: Flare): void;
|
|
4
|
-
/** Injected path: framework tag only, never sdkInfo. */
|
|
5
3
|
export declare function tagSvelteFramework(flare: Flare): void;
|
package/dist/identify.js
CHANGED
|
@@ -5,12 +5,12 @@ const tagger = createIdentityTagger({
|
|
|
5
5
|
sdkVersion: PACKAGE_VERSION,
|
|
6
6
|
frameworkName: FrameworkName.Svelte,
|
|
7
7
|
});
|
|
8
|
-
|
|
8
|
+
// Web path: full identity on the default singleton. Svelte's framework has no version.
|
|
9
9
|
export function registerSvelteSdkIdentity(flare) {
|
|
10
10
|
tagger.registerSdkIdentity(flare);
|
|
11
11
|
tagger.tagFramework(flare, undefined);
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
// Injected path: framework tag only, never sdkInfo.
|
|
14
14
|
export function tagSvelteFramework(flare) {
|
|
15
15
|
tagger.tagFramework(flare, undefined);
|
|
16
16
|
}
|
package/dist/inject.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
// Electron-safe entry
|
|
2
|
-
//
|
|
3
|
-
// at wiring time if absent.
|
|
1
|
+
// Electron-safe entry: no @flareapp/js root import, no default registration, no import-time identity.
|
|
2
|
+
// The caller must pass `flare` (handler option or boundary prop); resolveFlare throws at wiring time if absent.
|
|
4
3
|
export { default as FlareErrorBoundary } from './FlareErrorBoundary.svelte';
|
|
5
4
|
export { createFlareErrorHandler } from './createFlareErrorHandler.js';
|
|
6
5
|
export { __flareRegisterComponent, getComponentTreeContext } from './componentTree.js';
|
package/dist/preprocessor.js
CHANGED
|
@@ -58,30 +58,25 @@ export function flarePreprocessor(options) {
|
|
|
58
58
|
},
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
// Keeps the merged sourcemap's `sources` from carrying an absolute build-machine path.
|
|
62
62
|
function basename(filename) {
|
|
63
63
|
return filename.split(/[/\\]/).pop() ?? filename;
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
* changing it would change component hierarchies people already have.
|
|
68
|
-
*/
|
|
65
|
+
// The name error reports use. Stays a bare basename instead of `resolveProfileName`, because changing
|
|
66
|
+
// it would change component hierarchies people already have.
|
|
69
67
|
function extractComponentName(filename) {
|
|
70
68
|
return basename(filename).replace(/\.svelte$/, '');
|
|
71
69
|
}
|
|
72
70
|
function escapeString(str) {
|
|
73
71
|
return str.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
74
72
|
}
|
|
75
|
-
|
|
73
|
+
// Copied from Svelte's own preprocessor, so we agree with it on what counts as a style tag.
|
|
76
74
|
const REGEX_STYLE_TAGS = /<!--[^]*?-->|<style((?:\s+[^=>'"/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/\s]+)*\s*)(?:\/>|>([\S\s]*?)<\/style>)/g;
|
|
77
75
|
const CLOSING_STYLE_TAG = '</style>';
|
|
78
|
-
|
|
76
|
+
// One warning per file per process. A dev server runs this hook again on every save.
|
|
79
77
|
const warnedFiles = new Set();
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
* still line up. Svelte parses style bodies as CSS, so `lang="scss"` and friends throw and would
|
|
83
|
-
* otherwise cost the file its registration.
|
|
84
|
-
*/
|
|
78
|
+
// Blanks out every `<style>` body, keeping the character count so offsets into the original still
|
|
79
|
+
// line up. Svelte parses style bodies as CSS, so `lang="scss"` and similar would throw otherwise.
|
|
85
80
|
function blankStyleBodies(content) {
|
|
86
81
|
return content.replace(REGEX_STYLE_TAGS, (match, _attributes, body) => {
|
|
87
82
|
// The first branch of the regex matches comments, which have no body to blank.
|
|
@@ -101,7 +96,7 @@ function warnOnce(filename, reason) {
|
|
|
101
96
|
// Silence here reads as "component tracking works", which is worse than a noisy build.
|
|
102
97
|
console.warn(`[flare] Skipped component tracking for ${filename}: ${reason}`);
|
|
103
98
|
}
|
|
104
|
-
|
|
99
|
+
// How many BOM characters sit at the very start of the source, back to back.
|
|
105
100
|
function countLeadingBoms(content) {
|
|
106
101
|
let count = 0;
|
|
107
102
|
while (content.charCodeAt(count) === 0xfeff) {
|
|
@@ -109,16 +104,11 @@ function countLeadingBoms(content) {
|
|
|
109
104
|
}
|
|
110
105
|
return count;
|
|
111
106
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
* source cannot be parsed. Svelte hands a script hook every `<script>` in the file, nested ones
|
|
115
|
-
* included, so only the parser can say which one belongs to the component. `bomCount` rides along
|
|
116
|
-
* because the null case still needs to know how many bytes of BOM it must insert after.
|
|
117
|
-
*/
|
|
107
|
+
// Where the instance script body begins (null = none, undefined = unparseable). Only the parser can
|
|
108
|
+
// tell which `<script>` belongs to the component; `bomCount` tags along for the null case's BOM insert.
|
|
118
109
|
async function instanceScriptStart(content, filename) {
|
|
119
|
-
// parse() strips
|
|
120
|
-
//
|
|
121
|
-
// own stripping to act on, so the count we add back is exact no matter how many there were.
|
|
110
|
+
// parse() strips one leading BOM and reports offsets against the stripped source. Stripping all
|
|
111
|
+
// of them here first means the count we add back is exact, no matter how many BOMs there were.
|
|
122
112
|
const bomCount = countLeadingBoms(content);
|
|
123
113
|
const source = content.slice(bomCount);
|
|
124
114
|
try {
|
|
@@ -137,14 +127,13 @@ async function instanceScriptStart(content, filename) {
|
|
|
137
127
|
return undefined;
|
|
138
128
|
}
|
|
139
129
|
}
|
|
140
|
-
|
|
130
|
+
// The map matters: inserting lines shifts everything below, throwing off stack frames and breakpoints.
|
|
141
131
|
function injectWithMap(content, injection, filename, start, bomCount) {
|
|
142
132
|
const magicSource = new MagicString(content);
|
|
143
133
|
if (start === null) {
|
|
144
134
|
const scriptBlock = `<script>\n${injection}</script>\n`;
|
|
145
|
-
// prepend() inserts at offset 0,
|
|
146
|
-
//
|
|
147
|
-
// BOM at the front so compile()'s own BOM stripping still fires.
|
|
135
|
+
// prepend() inserts at offset 0, ahead of any BOM, and would move it into the template.
|
|
136
|
+
// appendRight(bomCount, ...) inserts after the BOM(s) instead, so compile()'s own stripping still fires.
|
|
148
137
|
if (bomCount > 0) {
|
|
149
138
|
magicSource.appendRight(bomCount, scriptBlock);
|
|
150
139
|
}
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Records one `browser_component` span for this component's mount. The preprocessor injects the call,
|
|
3
|
-
* don't write it by hand.
|
|
4
|
-
*
|
|
5
|
-
* Init runs top-down, so a child can point at a span id its parent reserved but hasn't recorded yet.
|
|
6
|
-
*/
|
|
7
1
|
export declare function __flareProfileComponent(name: string): void;
|
package/dist/profileComponent.js
CHANGED
|
@@ -3,12 +3,9 @@ import { getContext, onMount, setContext } from 'svelte';
|
|
|
3
3
|
// Separate from the component tree's key: that one chains every component, this one only the
|
|
4
4
|
// profiled ones.
|
|
5
5
|
const PROFILE_KEY = '__flare_component_profile';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
* Init runs top-down, so a child can point at a span id its parent reserved but hasn't recorded yet.
|
|
11
|
-
*/
|
|
6
|
+
// Records one `browser_component` span for this component's mount. The preprocessor injects this call;
|
|
7
|
+
// don't write it by hand. Init runs top-down, so a child may point at a span id its parent reserved
|
|
8
|
+
// but hasn't recorded yet.
|
|
12
9
|
export function __flareProfileComponent(name) {
|
|
13
10
|
try {
|
|
14
11
|
const inherited = getContext(PROFILE_KEY) ?? null;
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The name a profiled component reports, and what `profileComponents` matches against.
|
|
3
|
-
*
|
|
4
|
-
* Separate from `extractComponentName`, which feeds error reports and has to keep its bare basenames.
|
|
5
|
-
* Profiling needs the route path too, otherwise every route in a SvelteKit app is just `+page`.
|
|
6
|
-
*
|
|
7
|
-
* @param filename Absolute path as a Svelte preprocessor receives it.
|
|
8
|
-
* @param routesDir Project-relative routes directory, from `kit.files.routes`.
|
|
9
|
-
*/
|
|
10
1
|
export declare function resolveProfileName(filename: string, routesDir?: string): string;
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* @param filename Absolute path as a Svelte preprocessor receives it.
|
|
8
|
-
* @param routesDir Project-relative routes directory, from `kit.files.routes`.
|
|
9
|
-
*/
|
|
1
|
+
// The name a profiled component reports, and what `profileComponents` matches against.
|
|
2
|
+
// Separate from `extractComponentName`, which feeds error reports and needs bare basenames.
|
|
3
|
+
// Profiling needs the route path too, or every SvelteKit route is just `+page`.
|
|
4
|
+
//
|
|
5
|
+
// `filename` is the absolute path as a Svelte preprocessor receives it; `routesDir` is the
|
|
6
|
+
// project-relative routes directory, from `kit.files.routes`.
|
|
10
7
|
export function resolveProfileName(filename, routesDir = 'src/routes') {
|
|
11
8
|
const normalized = filename.replace(/\\/g, '/');
|
|
12
9
|
const base = normalized.split('/').pop() ?? normalized;
|
|
@@ -27,10 +24,8 @@ export function resolveProfileName(filename, routesDir = 'src/routes') {
|
|
|
27
24
|
const relativeDir = normalized.slice(start, normalized.lastIndexOf('/'));
|
|
28
25
|
return relativeDir ? `${relativeDir}/${name}` : name;
|
|
29
26
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
* occurrence, so a project checked out under something like /home/src/routes/ still works.
|
|
33
|
-
*/
|
|
27
|
+
// Index just past the routes directory, or -1 when the path isn't there. Anchors on the last
|
|
28
|
+
// occurrence, so a project checked out under something like /home/src/routes/ still works.
|
|
34
29
|
function routeDirStart(normalized, normalizedRoutesDir) {
|
|
35
30
|
const nested = normalized.lastIndexOf(`/${normalizedRoutesDir}/`);
|
|
36
31
|
if (nested !== -1) {
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "2.
|
|
1
|
+
export declare const PACKAGE_VERSION = "2.12.1";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// generated during release, do not modify
|
|
2
|
-
export const PACKAGE_VERSION = '2.
|
|
2
|
+
export const PACKAGE_VERSION = '2.12.1';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flareapp/svelte",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.1",
|
|
4
4
|
"description": "Svelte client for flareapp.io",
|
|
5
5
|
"homepage": "https://flareapp.io",
|
|
6
6
|
"bugs": "https://github.com/spatie/flare-client-js/issues",
|
|
@@ -73,14 +73,14 @@
|
|
|
73
73
|
"vitest": "^4.0.0"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
|
-
"@flareapp/js": "^2.
|
|
76
|
+
"@flareapp/js": "^2.12.1",
|
|
77
77
|
"svelte": "^5.3.0"
|
|
78
78
|
},
|
|
79
79
|
"publishConfig": {
|
|
80
80
|
"access": "public"
|
|
81
81
|
},
|
|
82
82
|
"dependencies": {
|
|
83
|
-
"@flareapp/core": "2.
|
|
83
|
+
"@flareapp/core": "2.12.1",
|
|
84
84
|
"error-stack-parser": "^2.1.4",
|
|
85
85
|
"magic-string": "^0.30.21"
|
|
86
86
|
}
|