@nexussdk/contracts 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/tracker.ts ADDED
@@ -0,0 +1,205 @@
1
+ /**
2
+ * @fileoverview Telemetry, Breadcrumb Tracing, and Error Ingestion contracts.
3
+ * @module @nexus/contracts/tracker
4
+ */
5
+
6
+ import type { Environment } from './auth.js';
7
+ import type { UserContext } from './flags.js';
8
+
9
+ /**
10
+ * Severity level of captured telemetry events.
11
+ *
12
+ * @example
13
+ * const level: SeverityLevel = 'error';
14
+ */
15
+ export type SeverityLevel = 'debug' | 'info' | 'warning' | 'error' | 'fatal';
16
+
17
+ /**
18
+ * Categorization of user action trails leading to a crash.
19
+ *
20
+ * @example
21
+ * const category: BreadcrumbCategory = 'ui.click';
22
+ */
23
+ export type BreadcrumbCategory = 'ui.click' | 'navigation' | 'http' | 'console' | 'custom';
24
+
25
+ /**
26
+ * Recorded trail of user activity captured before an exception.
27
+ *
28
+ * @example
29
+ * const breadcrumb: Breadcrumb = {
30
+ * timestamp: 1704067200000,
31
+ * category: 'ui.click',
32
+ * message: 'Clicked button #checkout-btn',
33
+ * level: 'info',
34
+ * data: { elementId: 'checkout-btn', page: '/checkout' },
35
+ * };
36
+ */
37
+ export interface Breadcrumb {
38
+ /** Milliseconds epoch timestamp when event occurred. */
39
+ timestamp: number;
40
+ /** Categorical discriminator. */
41
+ category: BreadcrumbCategory;
42
+ /** Human-readable event description (e.g. "Clicked button #checkout-btn"). */
43
+ message: string;
44
+ /** Severity level of the action. */
45
+ level?: SeverityLevel;
46
+ /** Sanitized event payload (e.g. HTTP status, target route). */
47
+ data?: Record<string, unknown>;
48
+ }
49
+
50
+ /**
51
+ * Parsed and structured stack frame information.
52
+ *
53
+ * @example
54
+ * const frame: StackFrame = {
55
+ * functionName: 'processPayment',
56
+ * fileName: 'https://app.example.com/chunk.abc123.js',
57
+ * lineNumber: 1,
58
+ * columnNumber: 45231,
59
+ * };
60
+ */
61
+ export interface StackFrame {
62
+ /** Name of the executing function or scope. */
63
+ functionName: string;
64
+ /** URL or relative path of the script file. */
65
+ fileName: string;
66
+ /** 1-based source line number. */
67
+ lineNumber: number;
68
+ /** 1-based source column number. */
69
+ columnNumber: number;
70
+ /** Extracted source context lines if available (after source map resolution). */
71
+ contextLines?: string[];
72
+ }
73
+
74
+ /**
75
+ * Ambient client execution device and browser context.
76
+ *
77
+ * @example
78
+ * const ctx: DeviceContext = {
79
+ * userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...',
80
+ * currentUrl: 'https://app.example.com/checkout',
81
+ * viewport: '1920x1080',
82
+ * networkStatus: '4g',
83
+ * timezone: 'Asia/Ho_Chi_Minh',
84
+ * };
85
+ */
86
+ export interface DeviceContext {
87
+ /** Browser User-Agent string. */
88
+ userAgent: string;
89
+ /** Client operating system name and version. */
90
+ os?: string;
91
+ /** Browser name and version. */
92
+ browser?: string;
93
+ /** Viewport dimensions (e.g. "1920x1080"). */
94
+ viewport?: string;
95
+ /** Current browser window URL where error occurred. */
96
+ currentUrl: string;
97
+ /** Network connectivity condition (e.g. "4g", "wifi", "online"). */
98
+ networkStatus?: string;
99
+ /** Client timezone (e.g. "Asia/Ho_Chi_Minh"). */
100
+ timezone?: string;
101
+ }
102
+
103
+ /**
104
+ * Ingestion payload dispatched from @nexus/tracker to Go-Gin edge.
105
+ *
106
+ * @example
107
+ * const payload: ErrorEventPayload = {
108
+ * fingerprint: 'sha256hex...',
109
+ * errorType: 'TypeError',
110
+ * errorMessage: "Cannot read properties of undefined (reading 'map')",
111
+ * stackTrace: [{ functionName: 'ProductList', fileName: 'chunk.js', lineNumber: 1, columnNumber: 400 }],
112
+ * breadcrumbs: [],
113
+ * deviceContext: { userAgent: 'Mozilla/5.0...', currentUrl: '/products' },
114
+ * occurrenceCount: 1,
115
+ * clientTimestamp: 1704067200000,
116
+ * };
117
+ */
118
+ export interface ErrorEventPayload {
119
+ /**
120
+ * Deterministic hash representing this specific class of crash.
121
+ * Format: sha256(errorType + ":" + errorMessage + ":" + topFrameFile + ":" + topFrameLine)
122
+ */
123
+ fingerprint: string;
124
+ /** JavaScript error type (e.g. "TypeError", "ReferenceError", "UnhandledRejection"). */
125
+ errorType: string;
126
+ /** Primary error message string. */
127
+ errorMessage: string;
128
+ /** Parsed stack trace frames from innermost to outermost. */
129
+ stackTrace: StackFrame[];
130
+ /** Chronological ring-buffer trail of events prior to crash (max 20). */
131
+ breadcrumbs: Breadcrumb[];
132
+ /** End-user context at time of crash (sanitized before transmission). */
133
+ userContext?: UserContext;
134
+ /** Client environment context. */
135
+ deviceContext: DeviceContext;
136
+ /** Key-value metadata tags for search aggregation. */
137
+ tags?: Record<string, string>;
138
+ /**
139
+ * Counter tracking consecutive duplicate occurrences aggregated by client.
140
+ * Prevents infinite loop crash cascades from overwhelming ingestion.
141
+ */
142
+ occurrenceCount: number;
143
+ /** Client-side epoch timestamp in milliseconds when error was captured. */
144
+ clientTimestamp: number;
145
+ }
146
+
147
+ /**
148
+ * Persistent error event record stored in PostgreSQL and returned to Shell UI.
149
+ *
150
+ * @example
151
+ * const entity: ErrorEventEntity = {
152
+ * ...payload,
153
+ * id: 'uuid-v4',
154
+ * projectId: 'project-uuid',
155
+ * environment: 'production',
156
+ * serverReceivedAt: '2024-01-01T00:00:05Z',
157
+ * };
158
+ */
159
+ export interface ErrorEventEntity extends ErrorEventPayload {
160
+ /** Unique UUID v4 identifier. */
161
+ id: string;
162
+ /** Project UUID v4 identifier. */
163
+ projectId: string;
164
+ /** Target deployment environment. */
165
+ environment: Environment;
166
+ /** Timestamp when Go-Gin successfully processed and recorded the event. */
167
+ serverReceivedAt: string;
168
+ }
169
+
170
+ /**
171
+ * Aggregated error group item displayed on the Console Dashboard.
172
+ *
173
+ * @example
174
+ * const group: ErrorGroupSummary = {
175
+ * fingerprint: 'sha256hex...',
176
+ * errorType: 'TypeError',
177
+ * errorMessage: "Cannot read properties of undefined (reading 'map')",
178
+ * environment: 'production',
179
+ * totalCount: 1547,
180
+ * affectedUsersCount: 234,
181
+ * firstSeenAt: '2024-01-01T10:00:00Z',
182
+ * lastSeenAt: '2024-06-15T14:32:01Z',
183
+ * };
184
+ */
185
+ export interface ErrorGroupSummary {
186
+ /** Fingerprint common to all events in this group. */
187
+ fingerprint: string;
188
+ /** Error type classification. */
189
+ errorType: string;
190
+ /** Primary error message. */
191
+ errorMessage: string;
192
+ /** Environment where errors occurred. */
193
+ environment: Environment;
194
+ /** Total sum of crash occurrences across all end-users. */
195
+ totalCount: number;
196
+ /** Count of unique users impacted by this crash group. */
197
+ affectedUsersCount: number;
198
+ /** Timestamp of the first time this crash was ever seen. */
199
+ firstSeenAt: string;
200
+ /** Timestamp of the latest crash occurrence. */
201
+ lastSeenAt: string;
202
+ }
203
+
204
+ // Re-export UserContext for downstream consumers of @nexus/contracts/tracker
205
+ export type { UserContext };
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src"]
8
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts', 'src/auth.ts', 'src/flags.ts', 'src/tracker.ts', 'src/rfc7807.ts'],
5
+ format: ['esm', 'cjs'],
6
+ dts: true,
7
+ splitting: false,
8
+ sourcemap: true,
9
+ clean: true,
10
+ treeshake: true,
11
+ target: 'es2022',
12
+ outExtension({ format }) {
13
+ return {
14
+ js: format === 'esm' ? '.mjs' : '.cjs',
15
+ };
16
+ },
17
+ });