@asteby/metacore-lib 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB;AAWD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAA;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IACpC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CACnC;AAiDD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,KAAK,CAAC,EAAE,SAAS,EACjB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAC7B,MAAM,CAAC,EAAE,UAAU,CAAA;CACf,GACL,MAAM,CAqBR"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB;AAaD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAA;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;IACpC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CACnC;AAiDD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,KAAK,CAAC,EAAE,SAAS,EACjB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAC7B,MAAM,CAAC,EAAE,UAAU,CAAA;CACf,GACL,MAAM,CAqBR"}
package/dist/errors.js CHANGED
@@ -4,6 +4,7 @@
4
4
  * `toast` is injected (typically from `sonner`) to avoid a hard dependency.
5
5
  * Localized strings can be overridden via the `labels` argument.
6
6
  */
7
+ import { looksLikeHtml } from './http-errors';
7
8
  const DEFAULT_LABELS = {
8
9
  generic: 'Something went wrong!',
9
10
  notFound: 'Content not found.',
@@ -15,8 +16,9 @@ const DEFAULT_LABELS = {
15
16
  function extractMessage(error, labels) {
16
17
  if (!error)
17
18
  return labels.generic;
19
+ // An HTML page is never a message (misrouted proxy / SPA catch-all).
18
20
  if (typeof error === 'string')
19
- return error;
21
+ return looksLikeHtml(error) ? labels.generic : error;
20
22
  if (typeof error !== 'object')
21
23
  return labels.generic;
22
24
  const err = error;
@@ -32,7 +34,8 @@ function extractMessage(error, labels) {
32
34
  return labels.notFound;
33
35
  if (status === 204)
34
36
  return labels.notFound;
35
- return (data?.message || data?.title || data?.error || data?.detail || err.message || labels.generic);
37
+ const candidates = [data?.message, data?.title, data?.error, data?.detail, err.message];
38
+ return candidates.find((c) => typeof c === 'string' && c && !looksLikeHtml(c)) || labels.generic;
36
39
  }
37
40
  // Network-level errors
38
41
  if (err.code === 'ECONNABORTED' || err.name === 'TimeoutError')
@@ -41,7 +44,7 @@ function extractMessage(error, labels) {
41
44
  return labels.network;
42
45
  if ('status' in err && Number(err.status) === 204)
43
46
  return labels.notFound;
44
- return err.message || labels.generic;
47
+ return err.message && !looksLikeHtml(err.message) ? err.message : labels.generic;
45
48
  }
46
49
  /**
47
50
  * Report a server error to the user via `toast` and log it.
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,MAAM,cAAc,GAAgB;IAClC,OAAO,EAAE,uBAAuB;IAChC,QAAQ,EAAE,oBAAoB;IAC9B,YAAY,EAAE,iDAAiD;IAC/D,SAAS,EAAE,oDAAoD;IAC/D,OAAO,EAAE,8CAA8C;IACvD,OAAO,EAAE,sCAAsC;CAChD,CAAA;AA0BD,SAAS,cAAc,CAAC,KAAc,EAAE,MAAmB;IACzD,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC,OAAO,CAAA;IAEjC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAE3C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,OAAO,CAAA;IAEpD,MAAM,GAAG,GAAG,KAAwB,CAAA;IAEpC,oBAAoB;IACpB,IAAI,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,CAAA;QACjD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,EAAE,IAEd,CAAA;QAEb,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,MAAM,CAAC,YAAY,CAAA;QAC9C,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,MAAM,CAAC,SAAS,CAAA;QAC3C,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,MAAM,CAAC,QAAQ,CAAA;QAC1C,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,MAAM,CAAC,QAAQ,CAAA;QAE1C,OAAO,CACL,IAAI,EAAE,OAAO,IAAI,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAC7F,CAAA;IACH,CAAC;IAED,uBAAuB;IACvB,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc;QAAE,OAAO,MAAM,CAAC,OAAO,CAAA;IACrF,IAAI,GAAG,CAAC,IAAI,KAAK,aAAa,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc;QAAE,OAAO,MAAM,CAAC,OAAO,CAAA;IAEpF,IAAI,QAAQ,IAAI,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAA;IAEzE,OAAO,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAA;AACtC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAc,EACd,KAAiB,EACjB,UAGI,EAAE;IAEN,MAAM,MAAM,GAAgB,EAAE,GAAG,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAA;IAC5E,MAAM,MAAM,GAAe,OAAO,CAAC,MAAM,IAAI,OAAO,CAAA;IAEpD,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAE7C,IAAI,CAAC;QACH,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAA;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,wBAAwB;IAC1B,CAAC;IAED,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Typed errors for API responses that are not what an API promises.
3
+ *
4
+ * A `/api/...` call that lands on the wrong upstream (a misrouted proxy, a
5
+ * Next.js / SPA catch-all, a Cloudflare or nginx error page) answers with an
6
+ * HTML document. Without a guard the page ends up rendered verbatim in a toast
7
+ * or a modal ("<!DOCTYPE html><html lang=…"). The same happens one hop later
8
+ * when a backend forwards an upstream's HTML body as its own JSON `message`.
9
+ *
10
+ * `HtmlResponseError` is what HTTP clients throw instead: a human message, the
11
+ * technical detail (status, URL, a text snippet) kept apart for a collapsible
12
+ * "details" section, and a short `correlationId` the user can quote to support.
13
+ *
14
+ * Pure: no React, no DOM, no axios — usable from any fetch/axios client,
15
+ * including federated addon bundles.
16
+ */
17
+ export declare const HTML_RESPONSE_ERROR_CODE = "html_response";
18
+ /** True when `value` is (the start of) an HTML document or fragment. */
19
+ export declare function looksLikeHtml(value: unknown): boolean;
20
+ /** True when a Content-Type header value declares HTML. */
21
+ export declare function isHtmlContentType(contentType: unknown): boolean;
22
+ /** `<title>` of an HTML document, if any — often the only useful bit ("502 Bad Gateway"). */
23
+ export declare function htmlTitle(html: string): string | undefined;
24
+ /** Plain-text excerpt of an HTML body for logs / a details panel (tags, scripts and styles stripped). */
25
+ export declare function htmlSnippet(html: string, max?: number): string;
26
+ /** Short random id (e.g. `ERR-7K2Q9F`) to correlate what the user sees with logs and fleet reports. */
27
+ export declare function newCorrelationId(prefix?: string): string;
28
+ export interface HtmlResponseErrorInit {
29
+ /** HTTP status of the response (the outer one when `embedded`). */
30
+ status?: number;
31
+ /** `METHOD url` or just the url of the request. */
32
+ url?: string;
33
+ /** Response Content-Type, when known. */
34
+ contentType?: string;
35
+ /** The HTML that was received (never shown to the user as-is). */
36
+ html?: string;
37
+ /**
38
+ * True when the HTML arrived inside a JSON envelope (`{message:"<!DOCTYPE…"}`)
39
+ * — i.e. the backend answered, but forwarded an upstream's page. False when
40
+ * the response body itself was HTML.
41
+ */
42
+ embedded?: boolean;
43
+ /** Human message to show instead of the default. */
44
+ message?: string;
45
+ correlationId?: string;
46
+ }
47
+ /**
48
+ * Thrown by HTTP clients when an API endpoint answers with HTML. `message` is
49
+ * always human-readable; the raw page stays in `html` / `snippet` / `details()`.
50
+ *
51
+ * For compatibility with code that reads axios-style errors, it also carries a
52
+ * `response` whose `data.message` is the human message (never the HTML).
53
+ */
54
+ export declare class HtmlResponseError extends Error {
55
+ readonly code = "html_response";
56
+ readonly status?: number;
57
+ readonly url?: string;
58
+ readonly contentType?: string;
59
+ readonly html: string;
60
+ readonly title?: string;
61
+ readonly snippet: string;
62
+ readonly embedded: boolean;
63
+ readonly correlationId: string;
64
+ readonly response: {
65
+ status?: number;
66
+ data: {
67
+ success: false;
68
+ code: string;
69
+ message: string;
70
+ correlation_id: string;
71
+ };
72
+ };
73
+ constructor(init?: HtmlResponseErrorInit);
74
+ /** Multi-line technical detail for a collapsible panel or a bug report. Never includes the full page. */
75
+ details(): string;
76
+ }
77
+ export declare function isHtmlResponseError(error: unknown): error is HtmlResponseError;
78
+ export interface DetectHtmlInput {
79
+ status?: number;
80
+ url?: string;
81
+ contentType?: string;
82
+ /** Parsed body (object) or raw text. */
83
+ body: unknown;
84
+ message?: string;
85
+ }
86
+ /**
87
+ * Inspect a response and return an `HtmlResponseError` when it is HTML — the
88
+ * body itself, or a JSON envelope whose `message`/`error`/`detail` field is an
89
+ * HTML page. Returns `undefined` for anything else (JSON, plain text, empty).
90
+ */
91
+ export declare function detectHtmlResponse(input: DetectHtmlInput): HtmlResponseError | undefined;
92
+ //# sourceMappingURL=http-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-errors.d.ts","sourceRoot":"","sources":["../src/http-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,wBAAwB,kBAAkB,CAAA;AAKvD,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAWrD;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,OAAO,GAAG,OAAO,CAE/D;AAED,6FAA6F;AAC7F,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG1D;AAED,yGAAyG;AACzG,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,MAAM,CAO3D;AAED,uGAAuG;AACvG,wBAAgB,gBAAgB,CAAC,MAAM,SAAQ,GAAG,MAAM,CAUvD;AAED,MAAM,WAAW,qBAAqB;IACpC,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;GAMG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,mBAA2B;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,QAAQ,EAAE;QACjB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,IAAI,EAAE;YAAE,OAAO,EAAE,KAAK,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,cAAc,EAAE,MAAM,CAAA;SAAE,CAAA;KAChF,CAAA;gBAEW,IAAI,GAAE,qBAA0B;IAkB5C,yGAAyG;IACzG,OAAO,IAAI,MAAM;CAYlB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAM9E;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,wCAAwC;IACxC,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,iBAAiB,GAAG,SAAS,CAoBxF"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Typed errors for API responses that are not what an API promises.
3
+ *
4
+ * A `/api/...` call that lands on the wrong upstream (a misrouted proxy, a
5
+ * Next.js / SPA catch-all, a Cloudflare or nginx error page) answers with an
6
+ * HTML document. Without a guard the page ends up rendered verbatim in a toast
7
+ * or a modal ("<!DOCTYPE html><html lang=…"). The same happens one hop later
8
+ * when a backend forwards an upstream's HTML body as its own JSON `message`.
9
+ *
10
+ * `HtmlResponseError` is what HTTP clients throw instead: a human message, the
11
+ * technical detail (status, URL, a text snippet) kept apart for a collapsible
12
+ * "details" section, and a short `correlationId` the user can quote to support.
13
+ *
14
+ * Pure: no React, no DOM, no axios — usable from any fetch/axios client,
15
+ * including federated addon bundles.
16
+ */
17
+ export const HTML_RESPONSE_ERROR_CODE = 'html_response';
18
+ const DEFAULT_HUMAN_MESSAGE = 'The service answered with a web page instead of data. It may be misconfigured or temporarily unavailable.';
19
+ /** True when `value` is (the start of) an HTML document or fragment. */
20
+ export function looksLikeHtml(value) {
21
+ if (typeof value !== 'string')
22
+ return false;
23
+ const head = value.trimStart().slice(0, 512).toLowerCase();
24
+ if (!head.startsWith('<'))
25
+ return false;
26
+ return (head.startsWith('<!doctype html') ||
27
+ head.startsWith('<html') ||
28
+ head.startsWith('<head') ||
29
+ head.startsWith('<body') ||
30
+ /<(html|head|body|title|meta|script|div)[\s>/]/.test(head));
31
+ }
32
+ /** True when a Content-Type header value declares HTML. */
33
+ export function isHtmlContentType(contentType) {
34
+ return typeof contentType === 'string' && /\btext\/html\b|\bapplication\/xhtml\+xml\b/i.test(contentType);
35
+ }
36
+ /** `<title>` of an HTML document, if any — often the only useful bit ("502 Bad Gateway"). */
37
+ export function htmlTitle(html) {
38
+ const title = html.match(/<title[^>]*>([^<]*)<\/title>/i)?.[1]?.trim();
39
+ return title || undefined;
40
+ }
41
+ /** Plain-text excerpt of an HTML body for logs / a details panel (tags, scripts and styles stripped). */
42
+ export function htmlSnippet(html, max = 240) {
43
+ const text = html
44
+ .replace(/<(script|style)[^>]*>[\s\S]*?<\/\1>/gi, ' ')
45
+ .replace(/<[^>]+>/g, ' ')
46
+ .replace(/\s+/g, ' ')
47
+ .trim();
48
+ return text.length > max ? `${text.slice(0, max)}…` : text;
49
+ }
50
+ /** Short random id (e.g. `ERR-7K2Q9F`) to correlate what the user sees with logs and fleet reports. */
51
+ export function newCorrelationId(prefix = 'ERR') {
52
+ let id = '';
53
+ try {
54
+ const bytes = new Uint8Array(4);
55
+ globalThis.crypto.getRandomValues(bytes);
56
+ id = Array.from(bytes, (b) => b.toString(36).padStart(2, '0')).join('');
57
+ }
58
+ catch {
59
+ id = Math.random().toString(36).slice(2, 10);
60
+ }
61
+ return `${prefix}-${id.slice(0, 6).toUpperCase()}`;
62
+ }
63
+ /**
64
+ * Thrown by HTTP clients when an API endpoint answers with HTML. `message` is
65
+ * always human-readable; the raw page stays in `html` / `snippet` / `details()`.
66
+ *
67
+ * For compatibility with code that reads axios-style errors, it also carries a
68
+ * `response` whose `data.message` is the human message (never the HTML).
69
+ */
70
+ export class HtmlResponseError extends Error {
71
+ code = HTML_RESPONSE_ERROR_CODE;
72
+ status;
73
+ url;
74
+ contentType;
75
+ html;
76
+ title;
77
+ snippet;
78
+ embedded;
79
+ correlationId;
80
+ response;
81
+ constructor(init = {}) {
82
+ const message = init.message || DEFAULT_HUMAN_MESSAGE;
83
+ super(message);
84
+ this.name = 'HtmlResponseError';
85
+ this.status = init.status;
86
+ this.url = init.url;
87
+ this.contentType = init.contentType;
88
+ this.html = init.html ?? '';
89
+ this.title = this.html ? htmlTitle(this.html) : undefined;
90
+ this.snippet = this.html ? htmlSnippet(this.html) : '';
91
+ this.embedded = !!init.embedded;
92
+ this.correlationId = init.correlationId || newCorrelationId();
93
+ this.response = {
94
+ status: init.status,
95
+ data: { success: false, code: HTML_RESPONSE_ERROR_CODE, message, correlation_id: this.correlationId },
96
+ };
97
+ }
98
+ /** Multi-line technical detail for a collapsible panel or a bug report. Never includes the full page. */
99
+ details() {
100
+ const lines = [
101
+ `code: ${this.code}${this.embedded ? ' (html inside JSON message)' : ''}`,
102
+ `correlation: ${this.correlationId}`,
103
+ ];
104
+ if (this.status !== undefined)
105
+ lines.push(`status: ${this.status}`);
106
+ if (this.url)
107
+ lines.push(`request: ${this.url}`);
108
+ if (this.contentType)
109
+ lines.push(`content-type: ${this.contentType}`);
110
+ if (this.title)
111
+ lines.push(`page title: ${this.title}`);
112
+ if (this.snippet)
113
+ lines.push(`body: ${this.snippet}`);
114
+ return lines.join('\n');
115
+ }
116
+ }
117
+ export function isHtmlResponseError(error) {
118
+ return (error instanceof HtmlResponseError ||
119
+ (!!error && typeof error === 'object' && error.code === HTML_RESPONSE_ERROR_CODE &&
120
+ error.name === 'HtmlResponseError'));
121
+ }
122
+ /**
123
+ * Inspect a response and return an `HtmlResponseError` when it is HTML — the
124
+ * body itself, or a JSON envelope whose `message`/`error`/`detail` field is an
125
+ * HTML page. Returns `undefined` for anything else (JSON, plain text, empty).
126
+ */
127
+ export function detectHtmlResponse(input) {
128
+ const { body } = input;
129
+ if (typeof body === 'string') {
130
+ if (looksLikeHtml(body) || (isHtmlContentType(input.contentType) && body.trim() !== '')) {
131
+ return new HtmlResponseError({ ...input, html: body, embedded: false });
132
+ }
133
+ return undefined;
134
+ }
135
+ if (body && typeof body === 'object') {
136
+ const o = body;
137
+ for (const key of ['message', 'error', 'detail', 'title']) {
138
+ const v = o[key];
139
+ const nested = v && typeof v === 'object' ? v.message : undefined;
140
+ const candidate = looksLikeHtml(v) ? v : looksLikeHtml(nested) ? nested : undefined;
141
+ if (typeof candidate === 'string') {
142
+ return new HtmlResponseError({ ...input, html: candidate, embedded: true });
143
+ }
144
+ }
145
+ }
146
+ return undefined;
147
+ }
148
+ //# sourceMappingURL=http-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-errors.js","sourceRoot":"","sources":["../src/http-errors.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -6,5 +6,7 @@ export { formatCurrency, getCurrencySymbol, parseCurrency, SPANISH_SYMBOLS, } fr
6
6
  export type { CurrencyInfo } from './currency';
7
7
  export { handleServerError } from './errors';
8
8
  export type { ErrorLabels, ToastLike, LoggerLike } from './errors';
9
+ export { HtmlResponseError, HTML_RESPONSE_ERROR_CODE, detectHtmlResponse, isHtmlResponseError, looksLikeHtml, isHtmlContentType, htmlTitle, htmlSnippet, newCorrelationId, } from './http-errors';
10
+ export type { HtmlResponseErrorInit, DetectHtmlInput } from './http-errors';
9
11
  export { showSubmittedData } from './show-submitted-data';
10
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,QAAQ,CAAA;AACf,YAAY,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAE1C,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAEnD,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAElE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,QAAQ,CAAA;AACf,YAAY,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAE1C,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAEnD,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAElE,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,gBAAgB,GACjB,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA"}
package/dist/index.js CHANGED
@@ -2,5 +2,6 @@ export { formatDate, formatDistance, formatRelative, getAllTimezones, detectTime
2
2
  export { formatNumber, formatPercentage, truncate } from './format';
3
3
  export { formatCurrency, getCurrencySymbol, parseCurrency, SPANISH_SYMBOLS, } from './currency';
4
4
  export { handleServerError } from './errors';
5
+ export { HtmlResponseError, HTML_RESPONSE_ERROR_CODE, detectHtmlResponse, isHtmlResponseError, looksLikeHtml, isHtmlContentType, htmlTitle, htmlSnippet, newCorrelationId, } from './http-errors';
5
6
  export { showSubmittedData } from './show-submitted-data';
6
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,QAAQ,CAAA;AAGf,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGnE,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAG5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,QAAQ,CAAA;AAGf,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGnE,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAG5C,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,gBAAgB,GACjB,MAAM,eAAe,CAAA;AAGtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-lib",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Metacore utilities — date/currency/number formatting, error handling, cookies",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -36,6 +36,10 @@
36
36
  "types": "./dist/errors.d.ts",
37
37
  "import": "./dist/errors.js"
38
38
  },
39
+ "./http-errors": {
40
+ "types": "./dist/http-errors.d.ts",
41
+ "import": "./dist/http-errors.js"
42
+ },
39
43
  "./show-submitted-data": {
40
44
  "types": "./dist/show-submitted-data.d.ts",
41
45
  "import": "./dist/show-submitted-data.js"
@@ -60,7 +64,8 @@
60
64
  "date-fns": "^4.1.0",
61
65
  "react": "^19.2.4",
62
66
  "sonner": "^2.0.0",
63
- "typescript": "^6.0.0"
67
+ "typescript": "^6.0.0",
68
+ "vitest": "^4.0.0"
64
69
  },
65
70
  "publishConfig": {
66
71
  "access": "public"
@@ -69,6 +74,7 @@
69
74
  "build": "tsc -p tsconfig.json",
70
75
  "dev": "tsc -w -p tsconfig.json",
71
76
  "typecheck": "tsc -p tsconfig.json --noEmit",
77
+ "test": "vitest run",
72
78
  "clean": "rm -rf dist"
73
79
  }
74
80
  }