@ihyeon/browser-error-log-protocol 0.1.16 → 0.1.17

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.ko.md CHANGED
@@ -10,7 +10,7 @@ Browser Error Log SDK·수집기·뷰어를 위한 버전이 있는 TypeScript
10
10
  npm install @ihyeon/browser-error-log-protocol
11
11
  ```
12
12
 
13
- 게시 패키지 대신 로컬 소스 tarball을 사용하려면 Node.js 24에서 `npm ci`, `npm run check:package`를 실행하고 `output/packages/ihyeon-browser-error-log-protocol-0.1.16.tgz`를 절대 경로로 설치합니다. [SDK 가이드](https://github.com/hyeonse-swing/browser-error-log/blob/main/docs/ko/personal-sdk.md)를 참고하세요.
13
+ 게시 패키지 대신 로컬 소스 tarball을 사용하려면 Node.js 24에서 `npm ci`, `npm run check:package`를 실행하고 `output/packages/ihyeon-browser-error-log-protocol-0.1.17.tgz`를 절대 경로로 설치합니다. [SDK 가이드](https://github.com/hyeonse-swing/browser-error-log/blob/main/docs/ko/personal-sdk.md)를 참고하세요.
14
14
 
15
15
  ## 이벤트·조회 계약
16
16
 
package/README.md CHANGED
@@ -10,7 +10,7 @@ Install directly when implementing your own collector or viewer; `@ihyeon/browse
10
10
  npm install @ihyeon/browser-error-log-protocol
11
11
  ```
12
12
 
13
- For local source-checkout development, use Node.js 24, `npm ci`, and `npm run check:package`, then install `output/packages/ihyeon-browser-error-log-protocol-0.1.16.tgz` by absolute path. See the [SDK guide](https://github.com/hyeonse-swing/browser-error-log/blob/main/docs/personal-sdk.md).
13
+ For local source-checkout development, use Node.js 24, `npm ci`, and `npm run check:package`, then install `output/packages/ihyeon-browser-error-log-protocol-0.1.17.tgz` by absolute path. See the [SDK guide](https://github.com/hyeonse-swing/browser-error-log/blob/main/docs/personal-sdk.md).
14
14
 
15
15
  ## Event and query contracts
16
16
 
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var a=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var u=(t,e)=>{for(var n in e)a(t,n,{get:e[n],enumerable:!0})},m=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of c(e))!g.call(t,r)&&r!==n&&a(t,r,{get:()=>e[r],enumerable:!(o=i(e,r))||o.enumerable});return t};var p=t=>m(a({},"__esModule",{value:!0}),t);var b={};u(b,{BREADCRUMB_LIMITS:()=>s,EVENT_LABELS:()=>f,SCHEMA_VERSION:()=>d,SDK_VERSION:()=>l,isBreadcrumbTrail:()=>y});module.exports=p(b);var d=1,l="0.1.16",s={count:20,bytes:12e3,category:40,message:256,dataKeys:6,dataKey:80,dataString:200};function y(t){try{if(!Array.isArray(t)||t.length>s.count)return!1;for(let e of t){if(!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).some(n=>!["occurredAt","category","message","data"].includes(n))||typeof e.occurredAt!="string"||!Number.isFinite(Date.parse(e.occurredAt))||new Date(e.occurredAt).toISOString()!==e.occurredAt||typeof e.category!="string"||!e.category.trim()||e.category.length>s.category||typeof e.message!="string"||!e.message.trim()||e.message.length>s.message)return!1;if(e.data!==void 0){if(!e.data||typeof e.data!="object"||Array.isArray(e.data))return!1;let n=Object.entries(e.data);if(n.length>s.dataKeys||n.some(([o,r])=>o.length>s.dataKey||!(r===null||typeof r=="boolean"||typeof r=="string"&&r.length<=s.dataString||typeof r=="number"&&Number.isFinite(r))))return!1}}return new TextEncoder().encode(JSON.stringify(t)).length<=s.bytes}catch{return!1}}var f={javascript:"JavaScript",promise:"Promise",react:"React",console:"Console",http:"HTTP error",network:"Network failure",manual:"Manual"};
1
+ "use strict";var a=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var u=(t,e)=>{for(var n in e)a(t,n,{get:e[n],enumerable:!0})},m=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of c(e))!g.call(t,r)&&r!==n&&a(t,r,{get:()=>e[r],enumerable:!(o=i(e,r))||o.enumerable});return t};var p=t=>m(a({},"__esModule",{value:!0}),t);var b={};u(b,{BREADCRUMB_LIMITS:()=>s,EVENT_LABELS:()=>f,SCHEMA_VERSION:()=>d,SDK_VERSION:()=>l,isBreadcrumbTrail:()=>y});module.exports=p(b);var d=1,l="0.1.17",s={count:20,bytes:12e3,category:40,message:256,dataKeys:6,dataKey:80,dataString:200};function y(t){try{if(!Array.isArray(t)||t.length>s.count)return!1;for(let e of t){if(!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).some(n=>!["occurredAt","category","message","data"].includes(n))||typeof e.occurredAt!="string"||!Number.isFinite(Date.parse(e.occurredAt))||new Date(e.occurredAt).toISOString()!==e.occurredAt||typeof e.category!="string"||!e.category.trim()||e.category.length>s.category||typeof e.message!="string"||!e.message.trim()||e.message.length>s.message)return!1;if(e.data!==void 0){if(!e.data||typeof e.data!="object"||Array.isArray(e.data))return!1;let n=Object.entries(e.data);if(n.length>s.dataKeys||n.some(([o,r])=>o.length>s.dataKey||!(r===null||typeof r=="boolean"||typeof r=="string"&&r.length<=s.dataString||typeof r=="number"&&Number.isFinite(r))))return!1}}return new TextEncoder().encode(JSON.stringify(t)).length<=s.bytes}catch{return!1}}var f={javascript:"JavaScript",promise:"Promise",react:"React",console:"Console",http:"HTTP error",network:"Network failure",manual:"Manual"};
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["export const SCHEMA_VERSION = 1 as const;\nexport const SDK_VERSION = '0.1.16';\n\nexport type EventType = 'javascript' | 'promise' | 'react' | 'console' | 'http' | 'network' | 'manual';\nexport type Runtime = 'browser' | 'webview-ios' | 'webview-android' | 'unknown';\n\nexport const BREADCRUMB_LIMITS = {\n count: 20, bytes: 12_000, category: 40, message: 256,\n dataKeys: 6, dataKey: 80, dataString: 200,\n} as const;\n\nexport interface Breadcrumb {\n occurredAt: string;\n category: string;\n message: string;\n data?: Record<string, string | number | boolean | null>;\n}\n\n/** Validates the bounded, canonical UTC breadcrumb representation on the wire. */\nexport function isBreadcrumbTrail(value: unknown): value is Breadcrumb[] {\n try {\n if (!Array.isArray(value) || value.length > BREADCRUMB_LIMITS.count) return false;\n for (const item of value) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) return false;\n if (Object.keys(item).some(key => !['occurredAt', 'category', 'message', 'data'].includes(key))) return false;\n if (typeof item.occurredAt !== 'string' || !Number.isFinite(Date.parse(item.occurredAt)) ||\n new Date(item.occurredAt).toISOString() !== item.occurredAt) return false;\n if (typeof item.category !== 'string' || !item.category.trim() || item.category.length > BREADCRUMB_LIMITS.category ||\n typeof item.message !== 'string' || !item.message.trim() || item.message.length > BREADCRUMB_LIMITS.message) return false;\n if (item.data !== undefined) {\n if (!item.data || typeof item.data !== 'object' || Array.isArray(item.data)) return false;\n const entries = Object.entries(item.data);\n if (entries.length > BREADCRUMB_LIMITS.dataKeys || entries.some(([key, field]) =>\n key.length > BREADCRUMB_LIMITS.dataKey || !(field === null || typeof field === 'boolean' ||\n (typeof field === 'string' && field.length <= BREADCRUMB_LIMITS.dataString) ||\n (typeof field === 'number' && Number.isFinite(field))))) return false;\n }\n }\n return new TextEncoder().encode(JSON.stringify(value)).length <= BREADCRUMB_LIMITS.bytes;\n } catch { return false; }\n}\n\nexport interface ErrorEventRecord {\n schemaVersion: 1;\n eventId: string;\n project: string;\n environment: string;\n release: string;\n sdkVersion: string;\n occurredAt: string;\n receivedAt?: string;\n viewId: string;\n sequence: number;\n elapsedMs: number;\n type: EventType;\n message: string;\n name?: string;\n stack?: string;\n componentStack?: string;\n page: string;\n runtime: Runtime;\n browser?: string;\n context?: Record<string, string | number | boolean | null>;\n breadcrumbs?: Breadcrumb[];\n network?: { method: string; url: string; status?: number; durationMs: number };\n}\n\nexport interface EventBatch { schemaVersion: 1; events: ErrorEventRecord[] }\nexport interface EventFilter {\n project?: string;\n environment?: string;\n type?: EventType;\n query?: string;\n from?: string;\n to?: string;\n cursor?: string;\n limit?: number;\n}\nexport interface EventPage { events: ErrorEventRecord[]; nextCursor?: string }\nexport interface EventDataSource {\n listEvents(filter: EventFilter, signal?: AbortSignal): Promise<EventPage>;\n getEvent(project: string, eventId: string, signal?: AbortSignal): Promise<ErrorEventRecord | null>;\n}\n\nexport const EVENT_LABELS: Record<EventType, string> = {\n javascript: 'JavaScript', promise: 'Promise', react: 'React', console: 'Console',\n http: 'HTTP error', network: 'Network failure', manual: 'Manual',\n};\n"],
4
+ "sourcesContent": ["export const SCHEMA_VERSION = 1 as const;\nexport const SDK_VERSION = '0.1.17';\n\nexport type EventType = 'javascript' | 'promise' | 'react' | 'console' | 'http' | 'network' | 'manual';\nexport type Runtime = 'browser' | 'webview-ios' | 'webview-android' | 'unknown';\n\nexport const BREADCRUMB_LIMITS = {\n count: 20, bytes: 12_000, category: 40, message: 256,\n dataKeys: 6, dataKey: 80, dataString: 200,\n} as const;\n\nexport interface Breadcrumb {\n occurredAt: string;\n category: string;\n message: string;\n data?: Record<string, string | number | boolean | null>;\n}\n\n/** Validates the bounded, canonical UTC breadcrumb representation on the wire. */\nexport function isBreadcrumbTrail(value: unknown): value is Breadcrumb[] {\n try {\n if (!Array.isArray(value) || value.length > BREADCRUMB_LIMITS.count) return false;\n for (const item of value) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) return false;\n if (Object.keys(item).some(key => !['occurredAt', 'category', 'message', 'data'].includes(key))) return false;\n if (typeof item.occurredAt !== 'string' || !Number.isFinite(Date.parse(item.occurredAt)) ||\n new Date(item.occurredAt).toISOString() !== item.occurredAt) return false;\n if (typeof item.category !== 'string' || !item.category.trim() || item.category.length > BREADCRUMB_LIMITS.category ||\n typeof item.message !== 'string' || !item.message.trim() || item.message.length > BREADCRUMB_LIMITS.message) return false;\n if (item.data !== undefined) {\n if (!item.data || typeof item.data !== 'object' || Array.isArray(item.data)) return false;\n const entries = Object.entries(item.data);\n if (entries.length > BREADCRUMB_LIMITS.dataKeys || entries.some(([key, field]) =>\n key.length > BREADCRUMB_LIMITS.dataKey || !(field === null || typeof field === 'boolean' ||\n (typeof field === 'string' && field.length <= BREADCRUMB_LIMITS.dataString) ||\n (typeof field === 'number' && Number.isFinite(field))))) return false;\n }\n }\n return new TextEncoder().encode(JSON.stringify(value)).length <= BREADCRUMB_LIMITS.bytes;\n } catch { return false; }\n}\n\nexport interface ErrorEventRecord {\n schemaVersion: 1;\n eventId: string;\n project: string;\n environment: string;\n release: string;\n sdkVersion: string;\n occurredAt: string;\n receivedAt?: string;\n viewId: string;\n sequence: number;\n elapsedMs: number;\n type: EventType;\n message: string;\n name?: string;\n stack?: string;\n componentStack?: string;\n page: string;\n runtime: Runtime;\n browser?: string;\n context?: Record<string, string | number | boolean | null>;\n breadcrumbs?: Breadcrumb[];\n network?: { method: string; url: string; status?: number; durationMs: number };\n}\n\nexport interface EventBatch { schemaVersion: 1; events: ErrorEventRecord[] }\nexport interface EventFilter {\n project?: string;\n environment?: string;\n type?: EventType;\n query?: string;\n from?: string;\n to?: string;\n cursor?: string;\n limit?: number;\n}\nexport interface EventPage { events: ErrorEventRecord[]; nextCursor?: string }\nexport interface EventDataSource {\n listEvents(filter: EventFilter, signal?: AbortSignal): Promise<EventPage>;\n getEvent(project: string, eventId: string, signal?: AbortSignal): Promise<ErrorEventRecord | null>;\n}\n\nexport const EVENT_LABELS: Record<EventType, string> = {\n javascript: 'JavaScript', promise: 'Promise', react: 'React', console: 'Console',\n http: 'HTTP error', network: 'Network failure', manual: 'Manual',\n};\n"],
5
5
  "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,uBAAAE,EAAA,iBAAAC,EAAA,mBAAAC,EAAA,gBAAAC,EAAA,sBAAAC,IAAA,eAAAC,EAAAP,GAAO,IAAMI,EAAiB,EACjBC,EAAc,SAKdH,EAAoB,CAC/B,MAAO,GAAI,MAAO,KAAQ,SAAU,GAAI,QAAS,IACjD,SAAU,EAAG,QAAS,GAAI,WAAY,GACxC,EAUO,SAASI,EAAkBE,EAAuC,CACvE,GAAI,CACF,GAAI,CAAC,MAAM,QAAQA,CAAK,GAAKA,EAAM,OAASN,EAAkB,MAAO,MAAO,GAC5E,QAAWO,KAAQD,EAAO,CAKxB,GAJI,CAACC,GAAQ,OAAOA,GAAS,UAAY,MAAM,QAAQA,CAAI,GACvD,OAAO,KAAKA,CAAI,EAAE,KAAKC,GAAO,CAAC,CAAC,aAAc,WAAY,UAAW,MAAM,EAAE,SAASA,CAAG,CAAC,GAC1F,OAAOD,EAAK,YAAe,UAAY,CAAC,OAAO,SAAS,KAAK,MAAMA,EAAK,UAAU,CAAC,GACnF,IAAI,KAAKA,EAAK,UAAU,EAAE,YAAY,IAAMA,EAAK,YACjD,OAAOA,EAAK,UAAa,UAAY,CAACA,EAAK,SAAS,KAAK,GAAKA,EAAK,SAAS,OAASP,EAAkB,UACvG,OAAOO,EAAK,SAAY,UAAY,CAACA,EAAK,QAAQ,KAAK,GAAKA,EAAK,QAAQ,OAASP,EAAkB,QAAS,MAAO,GACxH,GAAIO,EAAK,OAAS,OAAW,CAC3B,GAAI,CAACA,EAAK,MAAQ,OAAOA,EAAK,MAAS,UAAY,MAAM,QAAQA,EAAK,IAAI,EAAG,MAAO,GACpF,IAAME,EAAU,OAAO,QAAQF,EAAK,IAAI,EACxC,GAAIE,EAAQ,OAAST,EAAkB,UAAYS,EAAQ,KAAK,CAAC,CAACD,EAAKE,CAAK,IAC1EF,EAAI,OAASR,EAAkB,SAAW,EAAEU,IAAU,MAAQ,OAAOA,GAAU,WAC5E,OAAOA,GAAU,UAAYA,EAAM,QAAUV,EAAkB,YAC/D,OAAOU,GAAU,UAAY,OAAO,SAASA,CAAK,EAAG,EAAG,MAAO,EACtE,CACF,CACA,OAAO,IAAI,YAAY,EAAE,OAAO,KAAK,UAAUJ,CAAK,CAAC,EAAE,QAAUN,EAAkB,KACrF,MAAQ,CAAE,MAAO,EAAO,CAC1B,CA4CO,IAAMC,EAA0C,CACrD,WAAY,aAAc,QAAS,UAAW,MAAO,QAAS,QAAS,UACvE,KAAM,aAAc,QAAS,kBAAmB,OAAQ,QAC1D",
6
6
  "names": ["index_exports", "__export", "BREADCRUMB_LIMITS", "EVENT_LABELS", "SCHEMA_VERSION", "SDK_VERSION", "isBreadcrumbTrail", "__toCommonJS", "value", "item", "key", "entries", "field"]
7
7
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export declare const SCHEMA_VERSION: 1;
2
- export declare const SDK_VERSION = "0.1.16";
2
+ export declare const SDK_VERSION = "0.1.17";
3
3
  export type EventType = 'javascript' | 'promise' | 'react' | 'console' | 'http' | 'network' | 'manual';
4
4
  export type Runtime = 'browser' | 'webview-ios' | 'webview-android' | 'unknown';
5
5
  export declare const BREADCRUMB_LIMITS: {
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var a=1,i="0.1.16",t={count:20,bytes:12e3,category:40,message:256,dataKeys:6,dataKey:80,dataString:200};function c(n){try{if(!Array.isArray(n)||n.length>t.count)return!1;for(let e of n){if(!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).some(s=>!["occurredAt","category","message","data"].includes(s))||typeof e.occurredAt!="string"||!Number.isFinite(Date.parse(e.occurredAt))||new Date(e.occurredAt).toISOString()!==e.occurredAt||typeof e.category!="string"||!e.category.trim()||e.category.length>t.category||typeof e.message!="string"||!e.message.trim()||e.message.length>t.message)return!1;if(e.data!==void 0){if(!e.data||typeof e.data!="object"||Array.isArray(e.data))return!1;let s=Object.entries(e.data);if(s.length>t.dataKeys||s.some(([o,r])=>o.length>t.dataKey||!(r===null||typeof r=="boolean"||typeof r=="string"&&r.length<=t.dataString||typeof r=="number"&&Number.isFinite(r))))return!1}}return new TextEncoder().encode(JSON.stringify(n)).length<=t.bytes}catch{return!1}}var g={javascript:"JavaScript",promise:"Promise",react:"React",console:"Console",http:"HTTP error",network:"Network failure",manual:"Manual"};export{t as BREADCRUMB_LIMITS,g as EVENT_LABELS,a as SCHEMA_VERSION,i as SDK_VERSION,c as isBreadcrumbTrail};
1
+ var a=1,i="0.1.17",t={count:20,bytes:12e3,category:40,message:256,dataKeys:6,dataKey:80,dataString:200};function c(n){try{if(!Array.isArray(n)||n.length>t.count)return!1;for(let e of n){if(!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).some(s=>!["occurredAt","category","message","data"].includes(s))||typeof e.occurredAt!="string"||!Number.isFinite(Date.parse(e.occurredAt))||new Date(e.occurredAt).toISOString()!==e.occurredAt||typeof e.category!="string"||!e.category.trim()||e.category.length>t.category||typeof e.message!="string"||!e.message.trim()||e.message.length>t.message)return!1;if(e.data!==void 0){if(!e.data||typeof e.data!="object"||Array.isArray(e.data))return!1;let s=Object.entries(e.data);if(s.length>t.dataKeys||s.some(([o,r])=>o.length>t.dataKey||!(r===null||typeof r=="boolean"||typeof r=="string"&&r.length<=t.dataString||typeof r=="number"&&Number.isFinite(r))))return!1}}return new TextEncoder().encode(JSON.stringify(n)).length<=t.bytes}catch{return!1}}var g={javascript:"JavaScript",promise:"Promise",react:"React",console:"Console",http:"HTTP error",network:"Network failure",manual:"Manual"};export{t as BREADCRUMB_LIMITS,g as EVENT_LABELS,a as SCHEMA_VERSION,i as SDK_VERSION,c as isBreadcrumbTrail};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["export const SCHEMA_VERSION = 1 as const;\nexport const SDK_VERSION = '0.1.16';\n\nexport type EventType = 'javascript' | 'promise' | 'react' | 'console' | 'http' | 'network' | 'manual';\nexport type Runtime = 'browser' | 'webview-ios' | 'webview-android' | 'unknown';\n\nexport const BREADCRUMB_LIMITS = {\n count: 20, bytes: 12_000, category: 40, message: 256,\n dataKeys: 6, dataKey: 80, dataString: 200,\n} as const;\n\nexport interface Breadcrumb {\n occurredAt: string;\n category: string;\n message: string;\n data?: Record<string, string | number | boolean | null>;\n}\n\n/** Validates the bounded, canonical UTC breadcrumb representation on the wire. */\nexport function isBreadcrumbTrail(value: unknown): value is Breadcrumb[] {\n try {\n if (!Array.isArray(value) || value.length > BREADCRUMB_LIMITS.count) return false;\n for (const item of value) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) return false;\n if (Object.keys(item).some(key => !['occurredAt', 'category', 'message', 'data'].includes(key))) return false;\n if (typeof item.occurredAt !== 'string' || !Number.isFinite(Date.parse(item.occurredAt)) ||\n new Date(item.occurredAt).toISOString() !== item.occurredAt) return false;\n if (typeof item.category !== 'string' || !item.category.trim() || item.category.length > BREADCRUMB_LIMITS.category ||\n typeof item.message !== 'string' || !item.message.trim() || item.message.length > BREADCRUMB_LIMITS.message) return false;\n if (item.data !== undefined) {\n if (!item.data || typeof item.data !== 'object' || Array.isArray(item.data)) return false;\n const entries = Object.entries(item.data);\n if (entries.length > BREADCRUMB_LIMITS.dataKeys || entries.some(([key, field]) =>\n key.length > BREADCRUMB_LIMITS.dataKey || !(field === null || typeof field === 'boolean' ||\n (typeof field === 'string' && field.length <= BREADCRUMB_LIMITS.dataString) ||\n (typeof field === 'number' && Number.isFinite(field))))) return false;\n }\n }\n return new TextEncoder().encode(JSON.stringify(value)).length <= BREADCRUMB_LIMITS.bytes;\n } catch { return false; }\n}\n\nexport interface ErrorEventRecord {\n schemaVersion: 1;\n eventId: string;\n project: string;\n environment: string;\n release: string;\n sdkVersion: string;\n occurredAt: string;\n receivedAt?: string;\n viewId: string;\n sequence: number;\n elapsedMs: number;\n type: EventType;\n message: string;\n name?: string;\n stack?: string;\n componentStack?: string;\n page: string;\n runtime: Runtime;\n browser?: string;\n context?: Record<string, string | number | boolean | null>;\n breadcrumbs?: Breadcrumb[];\n network?: { method: string; url: string; status?: number; durationMs: number };\n}\n\nexport interface EventBatch { schemaVersion: 1; events: ErrorEventRecord[] }\nexport interface EventFilter {\n project?: string;\n environment?: string;\n type?: EventType;\n query?: string;\n from?: string;\n to?: string;\n cursor?: string;\n limit?: number;\n}\nexport interface EventPage { events: ErrorEventRecord[]; nextCursor?: string }\nexport interface EventDataSource {\n listEvents(filter: EventFilter, signal?: AbortSignal): Promise<EventPage>;\n getEvent(project: string, eventId: string, signal?: AbortSignal): Promise<ErrorEventRecord | null>;\n}\n\nexport const EVENT_LABELS: Record<EventType, string> = {\n javascript: 'JavaScript', promise: 'Promise', react: 'React', console: 'Console',\n http: 'HTTP error', network: 'Network failure', manual: 'Manual',\n};\n"],
4
+ "sourcesContent": ["export const SCHEMA_VERSION = 1 as const;\nexport const SDK_VERSION = '0.1.17';\n\nexport type EventType = 'javascript' | 'promise' | 'react' | 'console' | 'http' | 'network' | 'manual';\nexport type Runtime = 'browser' | 'webview-ios' | 'webview-android' | 'unknown';\n\nexport const BREADCRUMB_LIMITS = {\n count: 20, bytes: 12_000, category: 40, message: 256,\n dataKeys: 6, dataKey: 80, dataString: 200,\n} as const;\n\nexport interface Breadcrumb {\n occurredAt: string;\n category: string;\n message: string;\n data?: Record<string, string | number | boolean | null>;\n}\n\n/** Validates the bounded, canonical UTC breadcrumb representation on the wire. */\nexport function isBreadcrumbTrail(value: unknown): value is Breadcrumb[] {\n try {\n if (!Array.isArray(value) || value.length > BREADCRUMB_LIMITS.count) return false;\n for (const item of value) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) return false;\n if (Object.keys(item).some(key => !['occurredAt', 'category', 'message', 'data'].includes(key))) return false;\n if (typeof item.occurredAt !== 'string' || !Number.isFinite(Date.parse(item.occurredAt)) ||\n new Date(item.occurredAt).toISOString() !== item.occurredAt) return false;\n if (typeof item.category !== 'string' || !item.category.trim() || item.category.length > BREADCRUMB_LIMITS.category ||\n typeof item.message !== 'string' || !item.message.trim() || item.message.length > BREADCRUMB_LIMITS.message) return false;\n if (item.data !== undefined) {\n if (!item.data || typeof item.data !== 'object' || Array.isArray(item.data)) return false;\n const entries = Object.entries(item.data);\n if (entries.length > BREADCRUMB_LIMITS.dataKeys || entries.some(([key, field]) =>\n key.length > BREADCRUMB_LIMITS.dataKey || !(field === null || typeof field === 'boolean' ||\n (typeof field === 'string' && field.length <= BREADCRUMB_LIMITS.dataString) ||\n (typeof field === 'number' && Number.isFinite(field))))) return false;\n }\n }\n return new TextEncoder().encode(JSON.stringify(value)).length <= BREADCRUMB_LIMITS.bytes;\n } catch { return false; }\n}\n\nexport interface ErrorEventRecord {\n schemaVersion: 1;\n eventId: string;\n project: string;\n environment: string;\n release: string;\n sdkVersion: string;\n occurredAt: string;\n receivedAt?: string;\n viewId: string;\n sequence: number;\n elapsedMs: number;\n type: EventType;\n message: string;\n name?: string;\n stack?: string;\n componentStack?: string;\n page: string;\n runtime: Runtime;\n browser?: string;\n context?: Record<string, string | number | boolean | null>;\n breadcrumbs?: Breadcrumb[];\n network?: { method: string; url: string; status?: number; durationMs: number };\n}\n\nexport interface EventBatch { schemaVersion: 1; events: ErrorEventRecord[] }\nexport interface EventFilter {\n project?: string;\n environment?: string;\n type?: EventType;\n query?: string;\n from?: string;\n to?: string;\n cursor?: string;\n limit?: number;\n}\nexport interface EventPage { events: ErrorEventRecord[]; nextCursor?: string }\nexport interface EventDataSource {\n listEvents(filter: EventFilter, signal?: AbortSignal): Promise<EventPage>;\n getEvent(project: string, eventId: string, signal?: AbortSignal): Promise<ErrorEventRecord | null>;\n}\n\nexport const EVENT_LABELS: Record<EventType, string> = {\n javascript: 'JavaScript', promise: 'Promise', react: 'React', console: 'Console',\n http: 'HTTP error', network: 'Network failure', manual: 'Manual',\n};\n"],
5
5
  "mappings": "AAAO,IAAMA,EAAiB,EACjBC,EAAc,SAKdC,EAAoB,CAC/B,MAAO,GAAI,MAAO,KAAQ,SAAU,GAAI,QAAS,IACjD,SAAU,EAAG,QAAS,GAAI,WAAY,GACxC,EAUO,SAASC,EAAkBC,EAAuC,CACvE,GAAI,CACF,GAAI,CAAC,MAAM,QAAQA,CAAK,GAAKA,EAAM,OAASF,EAAkB,MAAO,MAAO,GAC5E,QAAWG,KAAQD,EAAO,CAKxB,GAJI,CAACC,GAAQ,OAAOA,GAAS,UAAY,MAAM,QAAQA,CAAI,GACvD,OAAO,KAAKA,CAAI,EAAE,KAAKC,GAAO,CAAC,CAAC,aAAc,WAAY,UAAW,MAAM,EAAE,SAASA,CAAG,CAAC,GAC1F,OAAOD,EAAK,YAAe,UAAY,CAAC,OAAO,SAAS,KAAK,MAAMA,EAAK,UAAU,CAAC,GACnF,IAAI,KAAKA,EAAK,UAAU,EAAE,YAAY,IAAMA,EAAK,YACjD,OAAOA,EAAK,UAAa,UAAY,CAACA,EAAK,SAAS,KAAK,GAAKA,EAAK,SAAS,OAASH,EAAkB,UACvG,OAAOG,EAAK,SAAY,UAAY,CAACA,EAAK,QAAQ,KAAK,GAAKA,EAAK,QAAQ,OAASH,EAAkB,QAAS,MAAO,GACxH,GAAIG,EAAK,OAAS,OAAW,CAC3B,GAAI,CAACA,EAAK,MAAQ,OAAOA,EAAK,MAAS,UAAY,MAAM,QAAQA,EAAK,IAAI,EAAG,MAAO,GACpF,IAAME,EAAU,OAAO,QAAQF,EAAK,IAAI,EACxC,GAAIE,EAAQ,OAASL,EAAkB,UAAYK,EAAQ,KAAK,CAAC,CAACD,EAAKE,CAAK,IAC1EF,EAAI,OAASJ,EAAkB,SAAW,EAAEM,IAAU,MAAQ,OAAOA,GAAU,WAC5E,OAAOA,GAAU,UAAYA,EAAM,QAAUN,EAAkB,YAC/D,OAAOM,GAAU,UAAY,OAAO,SAASA,CAAK,EAAG,EAAG,MAAO,EACtE,CACF,CACA,OAAO,IAAI,YAAY,EAAE,OAAO,KAAK,UAAUJ,CAAK,CAAC,EAAE,QAAUF,EAAkB,KACrF,MAAQ,CAAE,MAAO,EAAO,CAC1B,CA4CO,IAAMO,EAA0C,CACrD,WAAY,aAAc,QAAS,UAAW,MAAO,QAAS,QAAS,UACvE,KAAM,aAAc,QAAS,kBAAmB,OAAQ,QAC1D",
6
6
  "names": ["SCHEMA_VERSION", "SDK_VERSION", "BREADCRUMB_LIMITS", "isBreadcrumbTrail", "value", "item", "key", "entries", "field", "EVENT_LABELS"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ihyeon/browser-error-log-protocol",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "Versioned event and query contracts for Browser Error Log collectors and viewers.",
5
5
  "keywords": [
6
6
  "error-monitoring",