@shipeasy/sdk 4.5.0 → 5.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/README.md +17 -14
- package/dist/client/index.d.mts +27 -15
- package/dist/client/index.d.ts +27 -15
- package/dist/client/index.js +32 -54
- package/dist/client/index.mjs +32 -54
- package/dist/server/index.d.mts +30 -13
- package/dist/server/index.d.ts +30 -13
- package/dist/server/index.js +30 -24
- package/dist/server/index.mjs +30 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,12 +69,12 @@ try {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
// Non-exception problems — the name is a stable identifier (it participates
|
|
72
|
-
// in the issue fingerprint); variable data goes in .
|
|
72
|
+
// in the issue fingerprint); all variable data goes in .extras():
|
|
73
73
|
if (rows.length > LIMIT) {
|
|
74
74
|
see.Violation("large query")
|
|
75
|
-
.message(`got ${rows.length} rows`)
|
|
76
75
|
.causes_the("search results")
|
|
77
|
-
.to("be trimmed")
|
|
76
|
+
.to("be trimmed")
|
|
77
|
+
.extras({ rows: rows.length });
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// Expected control-flow exceptions: document them, report nothing —
|
|
@@ -82,7 +82,7 @@ if (rows.length > LIMIT) {
|
|
|
82
82
|
try {
|
|
83
83
|
return decodeFoo(blob);
|
|
84
84
|
} catch (e) {
|
|
85
|
-
see.ControlFlowException(e
|
|
85
|
+
see.ControlFlowException(e).because("because it wasn't an encoded Foo");
|
|
86
86
|
return decodeBar(blob);
|
|
87
87
|
}
|
|
88
88
|
```
|
|
@@ -94,16 +94,19 @@ occurrence timeseries. The chain dispatches on the next microtask — no
|
|
|
94
94
|
`fetch` on the server), spam-guarded by a 30s dedup window and a per-session
|
|
95
95
|
cap.
|
|
96
96
|
|
|
97
|
-
The client SDK also auto-captures
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
consequence
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
97
|
+
The client SDK also auto-captures **network failures** (fetch network errors +
|
|
98
|
+
5xx) into the same primitive (`autoCollect: { errors }`, on by default) — each
|
|
99
|
+
names a specific endpoint and a specific outcome. It deliberately does **not**
|
|
100
|
+
blanket-report uncaught exceptions or unhandled promise rejections: those carry
|
|
101
|
+
no actionable consequence ("the page hit an error" names the plumbing, not the
|
|
102
|
+
feature). Code that knows the consequence reports it explicitly with `see()` at
|
|
103
|
+
the catch site.
|
|
104
|
+
|
|
105
|
+
**Rules**: if you don't know the consequence, don't catch the exception. You
|
|
106
|
+
**may** `see()` then re-throw — the re-thrown error links to its inner report
|
|
107
|
+
as a `caused_by` chain instead of double-counting. Never use `see.Violation()`
|
|
108
|
+
for a caught exception (you'd drop the stack). No PII or high-cardinality data
|
|
109
|
+
in extras.
|
|
107
110
|
|
|
108
111
|
## Drop-in `<script>` loader (no bundler)
|
|
109
112
|
|
package/dist/client/index.d.mts
CHANGED
|
@@ -8,15 +8,13 @@ interface Consequence {
|
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* Non-exception problem, built by `violation(name)`. A plain branded object
|
|
11
|
-
* (not an Error subclass)
|
|
12
|
-
*
|
|
11
|
+
* (not an Error subclass). The name is the whole identity — there is no
|
|
12
|
+
* separate message; any variable/context data belongs in `.extras()` on the
|
|
13
|
+
* see chain, never on the violation itself.
|
|
13
14
|
*/
|
|
14
15
|
interface Violation {
|
|
15
16
|
readonly __seViolation: true;
|
|
16
17
|
readonly violationName: string;
|
|
17
|
-
readonly violationMessage?: string;
|
|
18
|
-
/** Attach free-form detail. Variable data goes HERE (or in extras), never in the name. */
|
|
19
|
-
message(msg: string): Violation;
|
|
20
18
|
}
|
|
21
19
|
/**
|
|
22
20
|
* Identity of a problem that see() already reported, carried on the wire as
|
|
@@ -84,9 +82,22 @@ interface SeeChain {
|
|
|
84
82
|
/** camelCase alias of {@link SeeChain.causes_the}. */
|
|
85
83
|
causesThe(subject: string): SeeOutcomeStep;
|
|
86
84
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Violations share the exception consequence grammar exactly — there is no
|
|
87
|
+
* separate `.message()`. Put any variable/context data in `.extras()`.
|
|
88
|
+
*/
|
|
89
|
+
type SeeViolationChain = SeeChain;
|
|
90
|
+
interface SeeControlFlowTail {
|
|
91
|
+
/**
|
|
92
|
+
* Optional debugging context for the expected exception. Kept on the mark for
|
|
93
|
+
* local debugging only (expected exceptions are never reported). Callable
|
|
94
|
+
* repeatedly — keys merge, later wins.
|
|
95
|
+
*/
|
|
96
|
+
extras(extras: SeeExtras): SeeControlFlowTail;
|
|
97
|
+
}
|
|
98
|
+
interface SeeControlFlowChain {
|
|
99
|
+
/** Document why the exception is expected. The reason should start with "because". */
|
|
100
|
+
because(reason: string): SeeControlFlowTail;
|
|
90
101
|
}
|
|
91
102
|
|
|
92
103
|
declare global {
|
|
@@ -430,28 +441,29 @@ interface SeeApi {
|
|
|
430
441
|
/**
|
|
431
442
|
* Report a non-exception problem. Prefer passing a caught Error to `see()`
|
|
432
443
|
* when one exists. The name is a stable identifier (it participates in the
|
|
433
|
-
* issue fingerprint) — variable data goes in `.
|
|
444
|
+
* issue fingerprint) — variable data goes in `.extras()`, never the name.
|
|
434
445
|
*
|
|
435
446
|
* ```ts
|
|
436
447
|
* if (rows.length > LIMIT) {
|
|
437
|
-
* see.Violation("large query")
|
|
438
|
-
* .causes_the("search results").to("be trimmed");
|
|
448
|
+
* see.Violation("large query")
|
|
449
|
+
* .causes_the("search results").to("be trimmed").extras({ rows: rows.length });
|
|
439
450
|
* }
|
|
440
451
|
* ```
|
|
441
452
|
*/
|
|
442
453
|
Violation(name: string): SeeViolationChain;
|
|
443
454
|
/**
|
|
444
455
|
* Mark an exception as expected control flow — auto-capture skips it and
|
|
445
|
-
* nothing is reported.
|
|
456
|
+
* nothing is reported. Say why with `.because()` (reason should start with
|
|
457
|
+
* "because"); attach optional debug context with `.extras()`.
|
|
446
458
|
*
|
|
447
459
|
* ```ts
|
|
448
460
|
* } catch (e) {
|
|
449
|
-
* see.ControlFlowException(e
|
|
461
|
+
* see.ControlFlowException(e).because("because the blob wasn't an encoded Foo");
|
|
450
462
|
* return decodeAsBar(blob);
|
|
451
463
|
* }
|
|
452
464
|
* ```
|
|
453
465
|
*/
|
|
454
|
-
ControlFlowException(err: unknown
|
|
466
|
+
ControlFlowException(err: unknown): SeeControlFlowChain;
|
|
455
467
|
}
|
|
456
468
|
/**
|
|
457
469
|
* Structured error reporter — the whole grammar hangs off this one import.
|
|
@@ -497,4 +509,4 @@ interface I18nFacade {
|
|
|
497
509
|
}
|
|
498
510
|
declare const i18n: I18nFacade;
|
|
499
511
|
|
|
500
|
-
export { type AutoCollectGroups, type BootstrapPayload, type Consequence, type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserEnv, type FlagsClientBrowserOptions, type I18nFacade, type I18nKey, type I18nRichComponents, type I18nString, type I18nTagRenderer, type I18nVariables, LABEL_MARKER_END, LABEL_MARKER_RE, LABEL_MARKER_SEP, LABEL_MARKER_START, type LabelAttrs, type SeeApi, type SeeChain, type SeeErrorEvent, type SeeExtras, type SeeKind, type SeeViolationChain, type ShipeasyClientConfig, type ShipeasySdkBridge, type User, type Violation, _resetShipeasyForTests, attachDevtools, configureShipeasy, encodeLabelMarker, flags, getShipeasyClient, i18n, injectCorrelationHeader, isDevtoolsRequested, labelAttrs, loadDevtools, readConfigOverride, readExpOverride, readGateOverride, sameOrigin, see, shipeasy, version };
|
|
512
|
+
export { type AutoCollectGroups, type BootstrapPayload, type Consequence, type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserEnv, type FlagsClientBrowserOptions, type I18nFacade, type I18nKey, type I18nRichComponents, type I18nString, type I18nTagRenderer, type I18nVariables, LABEL_MARKER_END, LABEL_MARKER_RE, LABEL_MARKER_SEP, LABEL_MARKER_START, type LabelAttrs, type SeeApi, type SeeChain, type SeeControlFlowChain, type SeeErrorEvent, type SeeExtras, type SeeKind, type SeeViolationChain, type ShipeasyClientConfig, type ShipeasySdkBridge, type User, type Violation, _resetShipeasyForTests, attachDevtools, configureShipeasy, encodeLabelMarker, flags, getShipeasyClient, i18n, injectCorrelationHeader, isDevtoolsRequested, labelAttrs, loadDevtools, readConfigOverride, readExpOverride, readGateOverride, sameOrigin, see, shipeasy, version };
|
package/dist/client/index.d.ts
CHANGED
|
@@ -8,15 +8,13 @@ interface Consequence {
|
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* Non-exception problem, built by `violation(name)`. A plain branded object
|
|
11
|
-
* (not an Error subclass)
|
|
12
|
-
*
|
|
11
|
+
* (not an Error subclass). The name is the whole identity — there is no
|
|
12
|
+
* separate message; any variable/context data belongs in `.extras()` on the
|
|
13
|
+
* see chain, never on the violation itself.
|
|
13
14
|
*/
|
|
14
15
|
interface Violation {
|
|
15
16
|
readonly __seViolation: true;
|
|
16
17
|
readonly violationName: string;
|
|
17
|
-
readonly violationMessage?: string;
|
|
18
|
-
/** Attach free-form detail. Variable data goes HERE (or in extras), never in the name. */
|
|
19
|
-
message(msg: string): Violation;
|
|
20
18
|
}
|
|
21
19
|
/**
|
|
22
20
|
* Identity of a problem that see() already reported, carried on the wire as
|
|
@@ -84,9 +82,22 @@ interface SeeChain {
|
|
|
84
82
|
/** camelCase alias of {@link SeeChain.causes_the}. */
|
|
85
83
|
causesThe(subject: string): SeeOutcomeStep;
|
|
86
84
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Violations share the exception consequence grammar exactly — there is no
|
|
87
|
+
* separate `.message()`. Put any variable/context data in `.extras()`.
|
|
88
|
+
*/
|
|
89
|
+
type SeeViolationChain = SeeChain;
|
|
90
|
+
interface SeeControlFlowTail {
|
|
91
|
+
/**
|
|
92
|
+
* Optional debugging context for the expected exception. Kept on the mark for
|
|
93
|
+
* local debugging only (expected exceptions are never reported). Callable
|
|
94
|
+
* repeatedly — keys merge, later wins.
|
|
95
|
+
*/
|
|
96
|
+
extras(extras: SeeExtras): SeeControlFlowTail;
|
|
97
|
+
}
|
|
98
|
+
interface SeeControlFlowChain {
|
|
99
|
+
/** Document why the exception is expected. The reason should start with "because". */
|
|
100
|
+
because(reason: string): SeeControlFlowTail;
|
|
90
101
|
}
|
|
91
102
|
|
|
92
103
|
declare global {
|
|
@@ -430,28 +441,29 @@ interface SeeApi {
|
|
|
430
441
|
/**
|
|
431
442
|
* Report a non-exception problem. Prefer passing a caught Error to `see()`
|
|
432
443
|
* when one exists. The name is a stable identifier (it participates in the
|
|
433
|
-
* issue fingerprint) — variable data goes in `.
|
|
444
|
+
* issue fingerprint) — variable data goes in `.extras()`, never the name.
|
|
434
445
|
*
|
|
435
446
|
* ```ts
|
|
436
447
|
* if (rows.length > LIMIT) {
|
|
437
|
-
* see.Violation("large query")
|
|
438
|
-
* .causes_the("search results").to("be trimmed");
|
|
448
|
+
* see.Violation("large query")
|
|
449
|
+
* .causes_the("search results").to("be trimmed").extras({ rows: rows.length });
|
|
439
450
|
* }
|
|
440
451
|
* ```
|
|
441
452
|
*/
|
|
442
453
|
Violation(name: string): SeeViolationChain;
|
|
443
454
|
/**
|
|
444
455
|
* Mark an exception as expected control flow — auto-capture skips it and
|
|
445
|
-
* nothing is reported.
|
|
456
|
+
* nothing is reported. Say why with `.because()` (reason should start with
|
|
457
|
+
* "because"); attach optional debug context with `.extras()`.
|
|
446
458
|
*
|
|
447
459
|
* ```ts
|
|
448
460
|
* } catch (e) {
|
|
449
|
-
* see.ControlFlowException(e
|
|
461
|
+
* see.ControlFlowException(e).because("because the blob wasn't an encoded Foo");
|
|
450
462
|
* return decodeAsBar(blob);
|
|
451
463
|
* }
|
|
452
464
|
* ```
|
|
453
465
|
*/
|
|
454
|
-
ControlFlowException(err: unknown
|
|
466
|
+
ControlFlowException(err: unknown): SeeControlFlowChain;
|
|
455
467
|
}
|
|
456
468
|
/**
|
|
457
469
|
* Structured error reporter — the whole grammar hangs off this one import.
|
|
@@ -497,4 +509,4 @@ interface I18nFacade {
|
|
|
497
509
|
}
|
|
498
510
|
declare const i18n: I18nFacade;
|
|
499
511
|
|
|
500
|
-
export { type AutoCollectGroups, type BootstrapPayload, type Consequence, type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserEnv, type FlagsClientBrowserOptions, type I18nFacade, type I18nKey, type I18nRichComponents, type I18nString, type I18nTagRenderer, type I18nVariables, LABEL_MARKER_END, LABEL_MARKER_RE, LABEL_MARKER_SEP, LABEL_MARKER_START, type LabelAttrs, type SeeApi, type SeeChain, type SeeErrorEvent, type SeeExtras, type SeeKind, type SeeViolationChain, type ShipeasyClientConfig, type ShipeasySdkBridge, type User, type Violation, _resetShipeasyForTests, attachDevtools, configureShipeasy, encodeLabelMarker, flags, getShipeasyClient, i18n, injectCorrelationHeader, isDevtoolsRequested, labelAttrs, loadDevtools, readConfigOverride, readExpOverride, readGateOverride, sameOrigin, see, shipeasy, version };
|
|
512
|
+
export { type AutoCollectGroups, type BootstrapPayload, type Consequence, type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserEnv, type FlagsClientBrowserOptions, type I18nFacade, type I18nKey, type I18nRichComponents, type I18nString, type I18nTagRenderer, type I18nVariables, LABEL_MARKER_END, LABEL_MARKER_RE, LABEL_MARKER_SEP, LABEL_MARKER_START, type LabelAttrs, type SeeApi, type SeeChain, type SeeControlFlowChain, type SeeErrorEvent, type SeeExtras, type SeeKind, type SeeViolationChain, type ShipeasyClientConfig, type ShipeasySdkBridge, type User, type Violation, _resetShipeasyForTests, attachDevtools, configureShipeasy, encodeLabelMarker, flags, getShipeasyClient, i18n, injectCorrelationHeader, isDevtoolsRequested, labelAttrs, loadDevtools, readConfigOverride, readExpOverride, readGateOverride, sameOrigin, see, shipeasy, version };
|
package/dist/client/index.js
CHANGED
|
@@ -126,25 +126,29 @@ function causesThe(subject) {
|
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
128
|
function violation(name) {
|
|
129
|
-
|
|
130
|
-
__seViolation: true,
|
|
131
|
-
violationName: String(name),
|
|
132
|
-
...msg !== void 0 ? { violationMessage: msg } : {},
|
|
133
|
-
message(m) {
|
|
134
|
-
return make(String(m));
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
return make();
|
|
129
|
+
return { __seViolation: true, violationName: String(name) };
|
|
138
130
|
}
|
|
139
131
|
function isViolation(p) {
|
|
140
132
|
return typeof p === "object" && p !== null && p.__seViolation === true;
|
|
141
133
|
}
|
|
142
134
|
var EXPECTED_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:see-expected");
|
|
143
|
-
function
|
|
135
|
+
function readExpectedMark(err) {
|
|
136
|
+
if (typeof err !== "object" || err === null) return void 0;
|
|
137
|
+
const v = err[EXPECTED_SYM];
|
|
138
|
+
return v !== void 0 && v !== null && typeof v === "object" ? v : void 0;
|
|
139
|
+
}
|
|
140
|
+
function markExpected(err, because, extras) {
|
|
144
141
|
if (typeof err !== "object" || err === null) return;
|
|
142
|
+
const prev = readExpectedMark(err);
|
|
143
|
+
const clean = sanitizeExtras(extras);
|
|
144
|
+
const merged = prev?.extras || clean ? { ...prev?.extras, ...clean } : void 0;
|
|
145
|
+
const mark = {
|
|
146
|
+
because: String(because),
|
|
147
|
+
...merged ? { extras: merged } : {}
|
|
148
|
+
};
|
|
145
149
|
try {
|
|
146
150
|
Object.defineProperty(err, EXPECTED_SYM, {
|
|
147
|
-
value:
|
|
151
|
+
value: mark,
|
|
148
152
|
enumerable: false,
|
|
149
153
|
configurable: true
|
|
150
154
|
});
|
|
@@ -225,7 +229,7 @@ function buildSeeEvent(problem, consequence, extras, ctx, kindOverride, correlat
|
|
|
225
229
|
let kind;
|
|
226
230
|
if (isViolation(problem)) {
|
|
227
231
|
errorType = problem.violationName;
|
|
228
|
-
message = problem.
|
|
232
|
+
message = problem.violationName;
|
|
229
233
|
stack = captureCallsiteStack();
|
|
230
234
|
kind = kindOverride ?? "violation";
|
|
231
235
|
} else if (problem instanceof Error) {
|
|
@@ -308,19 +312,21 @@ function startSeeChain(getProblem, dispatch) {
|
|
|
308
312
|
return { causes_the: start, causesThe: start };
|
|
309
313
|
}
|
|
310
314
|
function startSeeViolationChain(name, dispatch) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
315
|
+
return startSeeChain(() => violation(name), dispatch);
|
|
316
|
+
}
|
|
317
|
+
function startControlFlowChain(err) {
|
|
318
|
+
return {
|
|
319
|
+
because(reason) {
|
|
320
|
+
markExpected(err, reason);
|
|
321
|
+
const tail = {
|
|
322
|
+
extras(x) {
|
|
323
|
+
markExpected(err, reason, x);
|
|
324
|
+
return tail;
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
return tail;
|
|
321
328
|
}
|
|
322
329
|
};
|
|
323
|
-
return chain;
|
|
324
330
|
}
|
|
325
331
|
function topStackLine(stack) {
|
|
326
332
|
if (!stack) return "";
|
|
@@ -575,39 +581,11 @@ function installAutoGuardrails(buffer, userId, anonId, groups, reportSee, ignore
|
|
|
575
581
|
}
|
|
576
582
|
}
|
|
577
583
|
if (groups.errors) {
|
|
578
|
-
const origOnError = window.onerror;
|
|
579
|
-
window.onerror = (msg, source, lineno, _colno, err) => {
|
|
580
|
-
if (!isExpected(err)) {
|
|
581
|
-
const problem = err ?? (typeof msg === "string" && msg ? msg : "Unknown error");
|
|
582
|
-
reportSee(
|
|
583
|
-
problem,
|
|
584
|
-
causesThe("page").to("hit an unhandled error"),
|
|
585
|
-
{
|
|
586
|
-
source: typeof source === "string" ? source : void 0,
|
|
587
|
-
line: lineno ?? void 0
|
|
588
|
-
},
|
|
589
|
-
"uncaught"
|
|
590
|
-
);
|
|
591
|
-
}
|
|
592
|
-
if (typeof origOnError === "function") return origOnError(msg, source, lineno, _colno, err);
|
|
593
|
-
return false;
|
|
594
|
-
};
|
|
595
|
-
window.addEventListener("unhandledrejection", (e) => {
|
|
596
|
-
const reason = e.reason;
|
|
597
|
-
if (isExpected(reason)) return;
|
|
598
|
-
reportSee(
|
|
599
|
-
reason ?? "Unhandled promise rejection",
|
|
600
|
-
causesThe("page").to("hit an unhandled promise rejection"),
|
|
601
|
-
void 0,
|
|
602
|
-
"unhandled_rejection"
|
|
603
|
-
);
|
|
604
|
-
});
|
|
605
584
|
const origFetch = window.fetch;
|
|
606
585
|
window.fetch = async function(...args) {
|
|
607
586
|
const startedAt = typeof performance !== "undefined" ? performance.now() : 0;
|
|
608
587
|
const url = typeof args[0] === "string" ? args[0] : args[0].toString();
|
|
609
588
|
const ignored = ignoreUrlPrefixes.some((p) => p && url.startsWith(p));
|
|
610
|
-
const bareUrl = url.split("?")[0].slice(0, 200);
|
|
611
589
|
let corr;
|
|
612
590
|
if (!ignored && sameOrigin(url) && typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
613
591
|
corr = crypto.randomUUID();
|
|
@@ -619,7 +597,7 @@ function installAutoGuardrails(buffer, userId, anonId, groups, reportSee, ignore
|
|
|
619
597
|
} catch (err) {
|
|
620
598
|
if (!ignored && !isExpected(err)) {
|
|
621
599
|
reportSee(
|
|
622
|
-
violation("NetworkError")
|
|
600
|
+
violation("NetworkError"),
|
|
623
601
|
causesThe(`request to ${endpointTemplate(url)}`).to("get no response"),
|
|
624
602
|
{ status: 0, url: url.slice(0, 200) },
|
|
625
603
|
"network"
|
|
@@ -630,7 +608,7 @@ function installAutoGuardrails(buffer, userId, anonId, groups, reportSee, ignore
|
|
|
630
608
|
if (!ignored && res.status >= 500) {
|
|
631
609
|
const elapsed = typeof performance !== "undefined" ? performance.now() - startedAt : 0;
|
|
632
610
|
reportSee(
|
|
633
|
-
violation("Http5xx")
|
|
611
|
+
violation("Http5xx"),
|
|
634
612
|
causesThe(`request to ${endpointTemplate(url)}`).to("fail with a server error"),
|
|
635
613
|
{ status: res.status, url: url.slice(0, 200), duration_ms: Math.round(elapsed) },
|
|
636
614
|
"network",
|
|
@@ -1409,7 +1387,7 @@ var see = Object.assign(
|
|
|
1409
1387
|
(problem) => startSeeChain(() => problem, dispatchSee),
|
|
1410
1388
|
{
|
|
1411
1389
|
Violation: (name) => startSeeViolationChain(name, dispatchSee),
|
|
1412
|
-
ControlFlowException:
|
|
1390
|
+
ControlFlowException: (err) => startControlFlowChain(err)
|
|
1413
1391
|
}
|
|
1414
1392
|
);
|
|
1415
1393
|
var LABEL_MARKER_START = "\uFFF9";
|
package/dist/client/index.mjs
CHANGED
|
@@ -78,25 +78,29 @@ function causesThe(subject) {
|
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
function violation(name) {
|
|
81
|
-
|
|
82
|
-
__seViolation: true,
|
|
83
|
-
violationName: String(name),
|
|
84
|
-
...msg !== void 0 ? { violationMessage: msg } : {},
|
|
85
|
-
message(m) {
|
|
86
|
-
return make(String(m));
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
return make();
|
|
81
|
+
return { __seViolation: true, violationName: String(name) };
|
|
90
82
|
}
|
|
91
83
|
function isViolation(p) {
|
|
92
84
|
return typeof p === "object" && p !== null && p.__seViolation === true;
|
|
93
85
|
}
|
|
94
86
|
var EXPECTED_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:see-expected");
|
|
95
|
-
function
|
|
87
|
+
function readExpectedMark(err) {
|
|
88
|
+
if (typeof err !== "object" || err === null) return void 0;
|
|
89
|
+
const v = err[EXPECTED_SYM];
|
|
90
|
+
return v !== void 0 && v !== null && typeof v === "object" ? v : void 0;
|
|
91
|
+
}
|
|
92
|
+
function markExpected(err, because, extras) {
|
|
96
93
|
if (typeof err !== "object" || err === null) return;
|
|
94
|
+
const prev = readExpectedMark(err);
|
|
95
|
+
const clean = sanitizeExtras(extras);
|
|
96
|
+
const merged = prev?.extras || clean ? { ...prev?.extras, ...clean } : void 0;
|
|
97
|
+
const mark = {
|
|
98
|
+
because: String(because),
|
|
99
|
+
...merged ? { extras: merged } : {}
|
|
100
|
+
};
|
|
97
101
|
try {
|
|
98
102
|
Object.defineProperty(err, EXPECTED_SYM, {
|
|
99
|
-
value:
|
|
103
|
+
value: mark,
|
|
100
104
|
enumerable: false,
|
|
101
105
|
configurable: true
|
|
102
106
|
});
|
|
@@ -177,7 +181,7 @@ function buildSeeEvent(problem, consequence, extras, ctx, kindOverride, correlat
|
|
|
177
181
|
let kind;
|
|
178
182
|
if (isViolation(problem)) {
|
|
179
183
|
errorType = problem.violationName;
|
|
180
|
-
message = problem.
|
|
184
|
+
message = problem.violationName;
|
|
181
185
|
stack = captureCallsiteStack();
|
|
182
186
|
kind = kindOverride ?? "violation";
|
|
183
187
|
} else if (problem instanceof Error) {
|
|
@@ -260,19 +264,21 @@ function startSeeChain(getProblem, dispatch) {
|
|
|
260
264
|
return { causes_the: start, causesThe: start };
|
|
261
265
|
}
|
|
262
266
|
function startSeeViolationChain(name, dispatch) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
267
|
+
return startSeeChain(() => violation(name), dispatch);
|
|
268
|
+
}
|
|
269
|
+
function startControlFlowChain(err) {
|
|
270
|
+
return {
|
|
271
|
+
because(reason) {
|
|
272
|
+
markExpected(err, reason);
|
|
273
|
+
const tail = {
|
|
274
|
+
extras(x) {
|
|
275
|
+
markExpected(err, reason, x);
|
|
276
|
+
return tail;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
return tail;
|
|
273
280
|
}
|
|
274
281
|
};
|
|
275
|
-
return chain;
|
|
276
282
|
}
|
|
277
283
|
function topStackLine(stack) {
|
|
278
284
|
if (!stack) return "";
|
|
@@ -527,39 +533,11 @@ function installAutoGuardrails(buffer, userId, anonId, groups, reportSee, ignore
|
|
|
527
533
|
}
|
|
528
534
|
}
|
|
529
535
|
if (groups.errors) {
|
|
530
|
-
const origOnError = window.onerror;
|
|
531
|
-
window.onerror = (msg, source, lineno, _colno, err) => {
|
|
532
|
-
if (!isExpected(err)) {
|
|
533
|
-
const problem = err ?? (typeof msg === "string" && msg ? msg : "Unknown error");
|
|
534
|
-
reportSee(
|
|
535
|
-
problem,
|
|
536
|
-
causesThe("page").to("hit an unhandled error"),
|
|
537
|
-
{
|
|
538
|
-
source: typeof source === "string" ? source : void 0,
|
|
539
|
-
line: lineno ?? void 0
|
|
540
|
-
},
|
|
541
|
-
"uncaught"
|
|
542
|
-
);
|
|
543
|
-
}
|
|
544
|
-
if (typeof origOnError === "function") return origOnError(msg, source, lineno, _colno, err);
|
|
545
|
-
return false;
|
|
546
|
-
};
|
|
547
|
-
window.addEventListener("unhandledrejection", (e) => {
|
|
548
|
-
const reason = e.reason;
|
|
549
|
-
if (isExpected(reason)) return;
|
|
550
|
-
reportSee(
|
|
551
|
-
reason ?? "Unhandled promise rejection",
|
|
552
|
-
causesThe("page").to("hit an unhandled promise rejection"),
|
|
553
|
-
void 0,
|
|
554
|
-
"unhandled_rejection"
|
|
555
|
-
);
|
|
556
|
-
});
|
|
557
536
|
const origFetch = window.fetch;
|
|
558
537
|
window.fetch = async function(...args) {
|
|
559
538
|
const startedAt = typeof performance !== "undefined" ? performance.now() : 0;
|
|
560
539
|
const url = typeof args[0] === "string" ? args[0] : args[0].toString();
|
|
561
540
|
const ignored = ignoreUrlPrefixes.some((p) => p && url.startsWith(p));
|
|
562
|
-
const bareUrl = url.split("?")[0].slice(0, 200);
|
|
563
541
|
let corr;
|
|
564
542
|
if (!ignored && sameOrigin(url) && typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
565
543
|
corr = crypto.randomUUID();
|
|
@@ -571,7 +549,7 @@ function installAutoGuardrails(buffer, userId, anonId, groups, reportSee, ignore
|
|
|
571
549
|
} catch (err) {
|
|
572
550
|
if (!ignored && !isExpected(err)) {
|
|
573
551
|
reportSee(
|
|
574
|
-
violation("NetworkError")
|
|
552
|
+
violation("NetworkError"),
|
|
575
553
|
causesThe(`request to ${endpointTemplate(url)}`).to("get no response"),
|
|
576
554
|
{ status: 0, url: url.slice(0, 200) },
|
|
577
555
|
"network"
|
|
@@ -582,7 +560,7 @@ function installAutoGuardrails(buffer, userId, anonId, groups, reportSee, ignore
|
|
|
582
560
|
if (!ignored && res.status >= 500) {
|
|
583
561
|
const elapsed = typeof performance !== "undefined" ? performance.now() - startedAt : 0;
|
|
584
562
|
reportSee(
|
|
585
|
-
violation("Http5xx")
|
|
563
|
+
violation("Http5xx"),
|
|
586
564
|
causesThe(`request to ${endpointTemplate(url)}`).to("fail with a server error"),
|
|
587
565
|
{ status: res.status, url: url.slice(0, 200), duration_ms: Math.round(elapsed) },
|
|
588
566
|
"network",
|
|
@@ -1361,7 +1339,7 @@ var see = Object.assign(
|
|
|
1361
1339
|
(problem) => startSeeChain(() => problem, dispatchSee),
|
|
1362
1340
|
{
|
|
1363
1341
|
Violation: (name) => startSeeViolationChain(name, dispatchSee),
|
|
1364
|
-
ControlFlowException:
|
|
1342
|
+
ControlFlowException: (err) => startControlFlowChain(err)
|
|
1365
1343
|
}
|
|
1366
1344
|
);
|
|
1367
1345
|
var LABEL_MARKER_START = "\uFFF9";
|
package/dist/server/index.d.mts
CHANGED
|
@@ -10,15 +10,13 @@ interface Consequence {
|
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* Non-exception problem, built by `violation(name)`. A plain branded object
|
|
13
|
-
* (not an Error subclass)
|
|
14
|
-
*
|
|
13
|
+
* (not an Error subclass). The name is the whole identity — there is no
|
|
14
|
+
* separate message; any variable/context data belongs in `.extras()` on the
|
|
15
|
+
* see chain, never on the violation itself.
|
|
15
16
|
*/
|
|
16
17
|
interface Violation {
|
|
17
18
|
readonly __seViolation: true;
|
|
18
19
|
readonly violationName: string;
|
|
19
|
-
readonly violationMessage?: string;
|
|
20
|
-
/** Attach free-form detail. Variable data goes HERE (or in extras), never in the name. */
|
|
21
|
-
message(msg: string): Violation;
|
|
22
20
|
}
|
|
23
21
|
/**
|
|
24
22
|
* Identity of a problem that see() already reported, carried on the wire as
|
|
@@ -87,9 +85,22 @@ interface SeeChain {
|
|
|
87
85
|
/** camelCase alias of {@link SeeChain.causes_the}. */
|
|
88
86
|
causesThe(subject: string): SeeOutcomeStep;
|
|
89
87
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Violations share the exception consequence grammar exactly — there is no
|
|
90
|
+
* separate `.message()`. Put any variable/context data in `.extras()`.
|
|
91
|
+
*/
|
|
92
|
+
type SeeViolationChain = SeeChain;
|
|
93
|
+
interface SeeControlFlowTail {
|
|
94
|
+
/**
|
|
95
|
+
* Optional debugging context for the expected exception. Kept on the mark for
|
|
96
|
+
* local debugging only (expected exceptions are never reported). Callable
|
|
97
|
+
* repeatedly — keys merge, later wins.
|
|
98
|
+
*/
|
|
99
|
+
extras(extras: SeeExtras): SeeControlFlowTail;
|
|
100
|
+
}
|
|
101
|
+
interface SeeControlFlowChain {
|
|
102
|
+
/** Document why the exception is expected. The reason should start with "because". */
|
|
103
|
+
because(reason: string): SeeControlFlowTail;
|
|
93
104
|
}
|
|
94
105
|
|
|
95
106
|
declare const version = "4.0.0";
|
|
@@ -367,20 +378,26 @@ interface SeeApi {
|
|
|
367
378
|
/**
|
|
368
379
|
* Report a non-exception problem. Prefer passing a caught Error to `see()`
|
|
369
380
|
* when one exists. The name is a stable identifier (it participates in the
|
|
370
|
-
* issue fingerprint) — variable data goes in `.
|
|
381
|
+
* issue fingerprint) — variable data goes in `.extras()`, never the name.
|
|
371
382
|
*
|
|
372
383
|
* ```ts
|
|
373
384
|
* if (results.length > LIMIT) {
|
|
374
|
-
* see.Violation("large query")
|
|
385
|
+
* see.Violation("large query")
|
|
386
|
+
* .causes_the("search results").to("be trimmed").extras({ rows: results.length });
|
|
375
387
|
* }
|
|
376
388
|
* ```
|
|
377
389
|
*/
|
|
378
390
|
Violation(name: string): SeeViolationChain;
|
|
379
391
|
/**
|
|
380
392
|
* Mark an exception as expected control flow — documents the expectation and
|
|
381
|
-
* reports nothing.
|
|
393
|
+
* reports nothing. Say why with `.because()` (reason should start with
|
|
394
|
+
* "because"); attach optional debug context with `.extras()`.
|
|
395
|
+
*
|
|
396
|
+
* ```ts
|
|
397
|
+
* see.ControlFlowException(e).because("because the metric may not exist yet");
|
|
398
|
+
* ```
|
|
382
399
|
*/
|
|
383
|
-
ControlFlowException(err: unknown
|
|
400
|
+
ControlFlowException(err: unknown): SeeControlFlowChain;
|
|
384
401
|
}
|
|
385
402
|
/**
|
|
386
403
|
* Structured error reporter — the whole grammar hangs off this one import.
|
|
@@ -389,4 +406,4 @@ interface SeeApi {
|
|
|
389
406
|
*/
|
|
390
407
|
declare const see: SeeApi;
|
|
391
408
|
|
|
392
|
-
export { ANON_ID_COOKIE, type BootstrapHtmlOptions, type BootstrapPayload, type Consequence, type ExperimentResult, type FetchLabelsOptions, FlagsClient, type FlagsClientEnv, type FlagsClientOptions, type I18nForRequest, type LabelFile, type SeeApi, type SeeChain, type SeeErrorEvent, type SeeExtras, type SeeKind, type SeeViolationChain, type ShipeasyServerConfig, type ShipeasyServerHandle, type User, type Violation, _resetShipeasyServerForTests, configureShipeasyServer, fetchLabelsForSSR, flags, getBootstrapHtml, getShipeasyServerClient, i18n, isExpected, see, seeContext, shipeasy, version };
|
|
409
|
+
export { ANON_ID_COOKIE, type BootstrapHtmlOptions, type BootstrapPayload, type Consequence, type ExperimentResult, type FetchLabelsOptions, FlagsClient, type FlagsClientEnv, type FlagsClientOptions, type I18nForRequest, type LabelFile, type SeeApi, type SeeChain, type SeeControlFlowChain, type SeeErrorEvent, type SeeExtras, type SeeKind, type SeeViolationChain, type ShipeasyServerConfig, type ShipeasyServerHandle, type User, type Violation, _resetShipeasyServerForTests, configureShipeasyServer, fetchLabelsForSSR, flags, getBootstrapHtml, getShipeasyServerClient, i18n, isExpected, see, seeContext, shipeasy, version };
|
package/dist/server/index.d.ts
CHANGED
|
@@ -10,15 +10,13 @@ interface Consequence {
|
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* Non-exception problem, built by `violation(name)`. A plain branded object
|
|
13
|
-
* (not an Error subclass)
|
|
14
|
-
*
|
|
13
|
+
* (not an Error subclass). The name is the whole identity — there is no
|
|
14
|
+
* separate message; any variable/context data belongs in `.extras()` on the
|
|
15
|
+
* see chain, never on the violation itself.
|
|
15
16
|
*/
|
|
16
17
|
interface Violation {
|
|
17
18
|
readonly __seViolation: true;
|
|
18
19
|
readonly violationName: string;
|
|
19
|
-
readonly violationMessage?: string;
|
|
20
|
-
/** Attach free-form detail. Variable data goes HERE (or in extras), never in the name. */
|
|
21
|
-
message(msg: string): Violation;
|
|
22
20
|
}
|
|
23
21
|
/**
|
|
24
22
|
* Identity of a problem that see() already reported, carried on the wire as
|
|
@@ -87,9 +85,22 @@ interface SeeChain {
|
|
|
87
85
|
/** camelCase alias of {@link SeeChain.causes_the}. */
|
|
88
86
|
causesThe(subject: string): SeeOutcomeStep;
|
|
89
87
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Violations share the exception consequence grammar exactly — there is no
|
|
90
|
+
* separate `.message()`. Put any variable/context data in `.extras()`.
|
|
91
|
+
*/
|
|
92
|
+
type SeeViolationChain = SeeChain;
|
|
93
|
+
interface SeeControlFlowTail {
|
|
94
|
+
/**
|
|
95
|
+
* Optional debugging context for the expected exception. Kept on the mark for
|
|
96
|
+
* local debugging only (expected exceptions are never reported). Callable
|
|
97
|
+
* repeatedly — keys merge, later wins.
|
|
98
|
+
*/
|
|
99
|
+
extras(extras: SeeExtras): SeeControlFlowTail;
|
|
100
|
+
}
|
|
101
|
+
interface SeeControlFlowChain {
|
|
102
|
+
/** Document why the exception is expected. The reason should start with "because". */
|
|
103
|
+
because(reason: string): SeeControlFlowTail;
|
|
93
104
|
}
|
|
94
105
|
|
|
95
106
|
declare const version = "4.0.0";
|
|
@@ -367,20 +378,26 @@ interface SeeApi {
|
|
|
367
378
|
/**
|
|
368
379
|
* Report a non-exception problem. Prefer passing a caught Error to `see()`
|
|
369
380
|
* when one exists. The name is a stable identifier (it participates in the
|
|
370
|
-
* issue fingerprint) — variable data goes in `.
|
|
381
|
+
* issue fingerprint) — variable data goes in `.extras()`, never the name.
|
|
371
382
|
*
|
|
372
383
|
* ```ts
|
|
373
384
|
* if (results.length > LIMIT) {
|
|
374
|
-
* see.Violation("large query")
|
|
385
|
+
* see.Violation("large query")
|
|
386
|
+
* .causes_the("search results").to("be trimmed").extras({ rows: results.length });
|
|
375
387
|
* }
|
|
376
388
|
* ```
|
|
377
389
|
*/
|
|
378
390
|
Violation(name: string): SeeViolationChain;
|
|
379
391
|
/**
|
|
380
392
|
* Mark an exception as expected control flow — documents the expectation and
|
|
381
|
-
* reports nothing.
|
|
393
|
+
* reports nothing. Say why with `.because()` (reason should start with
|
|
394
|
+
* "because"); attach optional debug context with `.extras()`.
|
|
395
|
+
*
|
|
396
|
+
* ```ts
|
|
397
|
+
* see.ControlFlowException(e).because("because the metric may not exist yet");
|
|
398
|
+
* ```
|
|
382
399
|
*/
|
|
383
|
-
ControlFlowException(err: unknown
|
|
400
|
+
ControlFlowException(err: unknown): SeeControlFlowChain;
|
|
384
401
|
}
|
|
385
402
|
/**
|
|
386
403
|
* Structured error reporter — the whole grammar hangs off this one import.
|
|
@@ -389,4 +406,4 @@ interface SeeApi {
|
|
|
389
406
|
*/
|
|
390
407
|
declare const see: SeeApi;
|
|
391
408
|
|
|
392
|
-
export { ANON_ID_COOKIE, type BootstrapHtmlOptions, type BootstrapPayload, type Consequence, type ExperimentResult, type FetchLabelsOptions, FlagsClient, type FlagsClientEnv, type FlagsClientOptions, type I18nForRequest, type LabelFile, type SeeApi, type SeeChain, type SeeErrorEvent, type SeeExtras, type SeeKind, type SeeViolationChain, type ShipeasyServerConfig, type ShipeasyServerHandle, type User, type Violation, _resetShipeasyServerForTests, configureShipeasyServer, fetchLabelsForSSR, flags, getBootstrapHtml, getShipeasyServerClient, i18n, isExpected, see, seeContext, shipeasy, version };
|
|
409
|
+
export { ANON_ID_COOKIE, type BootstrapHtmlOptions, type BootstrapPayload, type Consequence, type ExperimentResult, type FetchLabelsOptions, FlagsClient, type FlagsClientEnv, type FlagsClientOptions, type I18nForRequest, type LabelFile, type SeeApi, type SeeChain, type SeeControlFlowChain, type SeeErrorEvent, type SeeExtras, type SeeKind, type SeeViolationChain, type ShipeasyServerConfig, type ShipeasyServerHandle, type User, type Violation, _resetShipeasyServerForTests, configureShipeasyServer, fetchLabelsForSSR, flags, getBootstrapHtml, getShipeasyServerClient, i18n, isExpected, see, seeContext, shipeasy, version };
|
package/dist/server/index.js
CHANGED
|
@@ -128,25 +128,29 @@ function causesThe(subject) {
|
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
130
|
function violation(name) {
|
|
131
|
-
|
|
132
|
-
__seViolation: true,
|
|
133
|
-
violationName: String(name),
|
|
134
|
-
...msg !== void 0 ? { violationMessage: msg } : {},
|
|
135
|
-
message(m) {
|
|
136
|
-
return make(String(m));
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
return make();
|
|
131
|
+
return { __seViolation: true, violationName: String(name) };
|
|
140
132
|
}
|
|
141
133
|
function isViolation(p) {
|
|
142
134
|
return typeof p === "object" && p !== null && p.__seViolation === true;
|
|
143
135
|
}
|
|
144
136
|
var EXPECTED_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:see-expected");
|
|
145
|
-
function
|
|
137
|
+
function readExpectedMark(err) {
|
|
138
|
+
if (typeof err !== "object" || err === null) return void 0;
|
|
139
|
+
const v = err[EXPECTED_SYM];
|
|
140
|
+
return v !== void 0 && v !== null && typeof v === "object" ? v : void 0;
|
|
141
|
+
}
|
|
142
|
+
function markExpected(err, because, extras) {
|
|
146
143
|
if (typeof err !== "object" || err === null) return;
|
|
144
|
+
const prev = readExpectedMark(err);
|
|
145
|
+
const clean = sanitizeExtras(extras);
|
|
146
|
+
const merged = prev?.extras || clean ? { ...prev?.extras, ...clean } : void 0;
|
|
147
|
+
const mark = {
|
|
148
|
+
because: String(because),
|
|
149
|
+
...merged ? { extras: merged } : {}
|
|
150
|
+
};
|
|
147
151
|
try {
|
|
148
152
|
Object.defineProperty(err, EXPECTED_SYM, {
|
|
149
|
-
value:
|
|
153
|
+
value: mark,
|
|
150
154
|
enumerable: false,
|
|
151
155
|
configurable: true
|
|
152
156
|
});
|
|
@@ -227,7 +231,7 @@ function buildSeeEvent(problem, consequence, extras, ctx, kindOverride, correlat
|
|
|
227
231
|
let kind;
|
|
228
232
|
if (isViolation(problem)) {
|
|
229
233
|
errorType = problem.violationName;
|
|
230
|
-
message = problem.
|
|
234
|
+
message = problem.violationName;
|
|
231
235
|
stack = captureCallsiteStack();
|
|
232
236
|
kind = kindOverride ?? "violation";
|
|
233
237
|
} else if (problem instanceof Error) {
|
|
@@ -310,19 +314,21 @@ function startSeeChain(getProblem, dispatch) {
|
|
|
310
314
|
return { causes_the: start, causesThe: start };
|
|
311
315
|
}
|
|
312
316
|
function startSeeViolationChain(name, dispatch) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
317
|
+
return startSeeChain(() => violation(name), dispatch);
|
|
318
|
+
}
|
|
319
|
+
function startControlFlowChain(err) {
|
|
320
|
+
return {
|
|
321
|
+
because(reason) {
|
|
322
|
+
markExpected(err, reason);
|
|
323
|
+
const tail = {
|
|
324
|
+
extras(x) {
|
|
325
|
+
markExpected(err, reason, x);
|
|
326
|
+
return tail;
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
return tail;
|
|
323
330
|
}
|
|
324
331
|
};
|
|
325
|
-
return chain;
|
|
326
332
|
}
|
|
327
333
|
function topStackLine(stack) {
|
|
328
334
|
if (!stack) return "";
|
|
@@ -1027,7 +1033,7 @@ var see = Object.assign(
|
|
|
1027
1033
|
(problem) => startSeeChain(() => problem, dispatchSee),
|
|
1028
1034
|
{
|
|
1029
1035
|
Violation: (name) => startSeeViolationChain(name, dispatchSee),
|
|
1030
|
-
ControlFlowException:
|
|
1036
|
+
ControlFlowException: (err) => startControlFlowChain(err)
|
|
1031
1037
|
}
|
|
1032
1038
|
);
|
|
1033
1039
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/server/index.mjs
CHANGED
|
@@ -81,25 +81,29 @@ function causesThe(subject) {
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
function violation(name) {
|
|
84
|
-
|
|
85
|
-
__seViolation: true,
|
|
86
|
-
violationName: String(name),
|
|
87
|
-
...msg !== void 0 ? { violationMessage: msg } : {},
|
|
88
|
-
message(m) {
|
|
89
|
-
return make(String(m));
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
return make();
|
|
84
|
+
return { __seViolation: true, violationName: String(name) };
|
|
93
85
|
}
|
|
94
86
|
function isViolation(p) {
|
|
95
87
|
return typeof p === "object" && p !== null && p.__seViolation === true;
|
|
96
88
|
}
|
|
97
89
|
var EXPECTED_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:see-expected");
|
|
98
|
-
function
|
|
90
|
+
function readExpectedMark(err) {
|
|
91
|
+
if (typeof err !== "object" || err === null) return void 0;
|
|
92
|
+
const v = err[EXPECTED_SYM];
|
|
93
|
+
return v !== void 0 && v !== null && typeof v === "object" ? v : void 0;
|
|
94
|
+
}
|
|
95
|
+
function markExpected(err, because, extras) {
|
|
99
96
|
if (typeof err !== "object" || err === null) return;
|
|
97
|
+
const prev = readExpectedMark(err);
|
|
98
|
+
const clean = sanitizeExtras(extras);
|
|
99
|
+
const merged = prev?.extras || clean ? { ...prev?.extras, ...clean } : void 0;
|
|
100
|
+
const mark = {
|
|
101
|
+
because: String(because),
|
|
102
|
+
...merged ? { extras: merged } : {}
|
|
103
|
+
};
|
|
100
104
|
try {
|
|
101
105
|
Object.defineProperty(err, EXPECTED_SYM, {
|
|
102
|
-
value:
|
|
106
|
+
value: mark,
|
|
103
107
|
enumerable: false,
|
|
104
108
|
configurable: true
|
|
105
109
|
});
|
|
@@ -180,7 +184,7 @@ function buildSeeEvent(problem, consequence, extras, ctx, kindOverride, correlat
|
|
|
180
184
|
let kind;
|
|
181
185
|
if (isViolation(problem)) {
|
|
182
186
|
errorType = problem.violationName;
|
|
183
|
-
message = problem.
|
|
187
|
+
message = problem.violationName;
|
|
184
188
|
stack = captureCallsiteStack();
|
|
185
189
|
kind = kindOverride ?? "violation";
|
|
186
190
|
} else if (problem instanceof Error) {
|
|
@@ -263,19 +267,21 @@ function startSeeChain(getProblem, dispatch) {
|
|
|
263
267
|
return { causes_the: start, causesThe: start };
|
|
264
268
|
}
|
|
265
269
|
function startSeeViolationChain(name, dispatch) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
270
|
+
return startSeeChain(() => violation(name), dispatch);
|
|
271
|
+
}
|
|
272
|
+
function startControlFlowChain(err) {
|
|
273
|
+
return {
|
|
274
|
+
because(reason) {
|
|
275
|
+
markExpected(err, reason);
|
|
276
|
+
const tail = {
|
|
277
|
+
extras(x) {
|
|
278
|
+
markExpected(err, reason, x);
|
|
279
|
+
return tail;
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
return tail;
|
|
276
283
|
}
|
|
277
284
|
};
|
|
278
|
-
return chain;
|
|
279
285
|
}
|
|
280
286
|
function topStackLine(stack) {
|
|
281
287
|
if (!stack) return "";
|
|
@@ -980,7 +986,7 @@ var see = Object.assign(
|
|
|
980
986
|
(problem) => startSeeChain(() => problem, dispatchSee),
|
|
981
987
|
{
|
|
982
988
|
Violation: (name) => startSeeViolationChain(name, dispatchSee),
|
|
983
|
-
ControlFlowException:
|
|
989
|
+
ControlFlowException: (err) => startControlFlowChain(err)
|
|
984
990
|
}
|
|
985
991
|
);
|
|
986
992
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shipeasy/sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Shipeasy SDK — feature gates, runtime configs, experiments, and metrics for the Shipeasy hosted service.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"homepage": "https://shipeasy.ai",
|