@tracelens/shared 0.1.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.
Files changed (63) hide show
  1. package/dist/__tests__/validation.test.d.ts +2 -0
  2. package/dist/__tests__/validation.test.d.ts.map +1 -0
  3. package/dist/__tests__/validation.test.js +16 -0
  4. package/dist/index.d.ts +4 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +4 -0
  7. package/dist/schemas/dependency.schema.d.ts +177 -0
  8. package/dist/schemas/dependency.schema.d.ts.map +1 -0
  9. package/dist/schemas/dependency.schema.js +187 -0
  10. package/dist/schemas/error.schema.d.ts +170 -0
  11. package/dist/schemas/error.schema.d.ts.map +1 -0
  12. package/dist/schemas/error.schema.js +176 -0
  13. package/dist/schemas/index.d.ts +5 -0
  14. package/dist/schemas/index.d.ts.map +1 -0
  15. package/dist/schemas/index.js +5 -0
  16. package/dist/schemas/performance.schema.d.ts +333 -0
  17. package/dist/schemas/performance.schema.d.ts.map +1 -0
  18. package/dist/schemas/performance.schema.js +200 -0
  19. package/dist/schemas/trace.schema.d.ts +325 -0
  20. package/dist/schemas/trace.schema.d.ts.map +1 -0
  21. package/dist/schemas/trace.schema.js +145 -0
  22. package/dist/types/dependency.types.d.ts +109 -0
  23. package/dist/types/dependency.types.d.ts.map +1 -0
  24. package/dist/types/dependency.types.js +8 -0
  25. package/dist/types/index.d.ts +10 -0
  26. package/dist/types/index.d.ts.map +1 -0
  27. package/dist/types/index.js +5 -0
  28. package/dist/types/performance.types.d.ts +95 -0
  29. package/dist/types/performance.types.d.ts.map +1 -0
  30. package/dist/types/performance.types.js +1 -0
  31. package/dist/types/security.types.d.ts +154 -0
  32. package/dist/types/security.types.d.ts.map +1 -0
  33. package/dist/types/security.types.js +8 -0
  34. package/dist/types/trace.types.d.ts +57 -0
  35. package/dist/types/trace.types.d.ts.map +1 -0
  36. package/dist/types/trace.types.js +20 -0
  37. package/dist/utils/index.d.ts +3 -0
  38. package/dist/utils/index.d.ts.map +1 -0
  39. package/dist/utils/index.js +5 -0
  40. package/dist/utils/validation.d.ts +21 -0
  41. package/dist/utils/validation.d.ts.map +1 -0
  42. package/dist/utils/validation.js +157 -0
  43. package/jest.config.js +14 -0
  44. package/package.json +22 -0
  45. package/src/__tests__/validation.test.ts +19 -0
  46. package/src/index.d.ts.map +1 -0
  47. package/src/index.ts +4 -0
  48. package/src/schemas/dependency.schema.ts +187 -0
  49. package/src/schemas/error.schema.ts +176 -0
  50. package/src/schemas/index.ts +5 -0
  51. package/src/schemas/performance.schema.ts +200 -0
  52. package/src/schemas/trace.schema.ts +146 -0
  53. package/src/types/dependency.types.ts +120 -0
  54. package/src/types/index.d.ts.map +1 -0
  55. package/src/types/index.ts +11 -0
  56. package/src/types/performance.types.ts +108 -0
  57. package/src/types/security.types.ts +172 -0
  58. package/src/types/trace.types.ts +62 -0
  59. package/src/utils/index.d.ts.map +1 -0
  60. package/src/utils/index.ts +6 -0
  61. package/src/utils/validation.ts +209 -0
  62. package/tsconfig.json +9 -0
  63. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,157 @@
1
+ export class ValidationError extends Error {
2
+ field;
3
+ value;
4
+ constructor(message, field, value) {
5
+ super(message);
6
+ this.field = field;
7
+ this.value = value;
8
+ this.name = 'ValidationError';
9
+ }
10
+ }
11
+ export function validateTraceSpan(span) {
12
+ if (!span || typeof span !== 'object') {
13
+ throw new ValidationError('Span must be an object', 'span', span);
14
+ }
15
+ const s = span;
16
+ if (!s.traceId || typeof s.traceId !== 'string') {
17
+ throw new ValidationError('traceId must be a string', 'traceId', s.traceId);
18
+ }
19
+ if (!s.spanId || typeof s.spanId !== 'string') {
20
+ throw new ValidationError('spanId must be a string', 'spanId', s.spanId);
21
+ }
22
+ if (!s.operationName || typeof s.operationName !== 'string') {
23
+ throw new ValidationError('operationName must be a string', 'operationName', s.operationName);
24
+ }
25
+ if (!s.startTime || typeof s.startTime !== 'number') {
26
+ throw new ValidationError('startTime must be a number', 'startTime', s.startTime);
27
+ }
28
+ if (s.endTime !== undefined && typeof s.endTime !== 'number') {
29
+ throw new ValidationError('endTime must be a number', 'endTime', s.endTime);
30
+ }
31
+ if (!s.tags || typeof s.tags !== 'object') {
32
+ throw new ValidationError('tags must be an object', 'tags', s.tags);
33
+ }
34
+ return s;
35
+ }
36
+ export function validateTrace(trace) {
37
+ if (!trace || typeof trace !== 'object') {
38
+ throw new ValidationError('Trace must be an object', 'trace', trace);
39
+ }
40
+ const t = trace;
41
+ if (!t.traceId || typeof t.traceId !== 'string') {
42
+ throw new ValidationError('traceId must be a string', 'traceId', t.traceId);
43
+ }
44
+ if (!Array.isArray(t.spans)) {
45
+ throw new ValidationError('spans must be an array', 'spans', t.spans);
46
+ }
47
+ // Validate each span
48
+ t.spans.forEach((span, index) => {
49
+ try {
50
+ validateTraceSpan(span);
51
+ }
52
+ catch (error) {
53
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
54
+ throw new ValidationError(`Invalid span at index ${index}: ${errorMessage}`, `spans[${index}]`, span);
55
+ }
56
+ });
57
+ return t;
58
+ }
59
+ export function validatePerformanceEvent(event) {
60
+ if (!event || typeof event !== 'object') {
61
+ throw new ValidationError('Event must be an object', 'event', event);
62
+ }
63
+ const e = event;
64
+ if (!e.id || typeof e.id !== 'string') {
65
+ throw new ValidationError('id must be a string', 'id', e.id);
66
+ }
67
+ if (!e.timestamp || typeof e.timestamp !== 'number') {
68
+ throw new ValidationError('timestamp must be a number', 'timestamp', e.timestamp);
69
+ }
70
+ const validTypes = ['web-vitals', 'resource-timing', 'navigation-timing', 'long-task'];
71
+ if (!e.type || !validTypes.includes(e.type)) {
72
+ throw new ValidationError(`type must be one of: ${validTypes.join(', ')}`, 'type', e.type);
73
+ }
74
+ if (!e.url || typeof e.url !== 'string') {
75
+ throw new ValidationError('url must be a string', 'url', e.url);
76
+ }
77
+ return e;
78
+ }
79
+ export function validateDependencySnapshot(snapshot) {
80
+ if (!snapshot || typeof snapshot !== 'object') {
81
+ throw new ValidationError('Snapshot must be an object', 'snapshot', snapshot);
82
+ }
83
+ const s = snapshot;
84
+ if (!s.id || typeof s.id !== 'string') {
85
+ throw new ValidationError('id must be a string', 'id', s.id);
86
+ }
87
+ if (!s.projectId || typeof s.projectId !== 'string') {
88
+ throw new ValidationError('projectId must be a string', 'projectId', s.projectId);
89
+ }
90
+ if (!s.timestamp || typeof s.timestamp !== 'number') {
91
+ throw new ValidationError('timestamp must be a number', 'timestamp', s.timestamp);
92
+ }
93
+ if (!Array.isArray(s.dependencies)) {
94
+ throw new ValidationError('dependencies must be an array', 'dependencies', s.dependencies);
95
+ }
96
+ return s;
97
+ }
98
+ export function validateCVERecord(cve) {
99
+ if (!cve || typeof cve !== 'object') {
100
+ throw new ValidationError('CVE must be an object', 'cve', cve);
101
+ }
102
+ const c = cve;
103
+ if (!c.id || typeof c.id !== 'string') {
104
+ throw new ValidationError('id must be a string', 'id', c.id);
105
+ }
106
+ // Validate CVE ID format
107
+ const cveIdPattern = /^CVE-\d{4}-\d{4,}$/;
108
+ if (!cveIdPattern.test(c.id)) {
109
+ throw new ValidationError('id must be in CVE-YYYY-NNNN format', 'id', c.id);
110
+ }
111
+ if (!c.published || typeof c.published !== 'string') {
112
+ throw new ValidationError('published must be a string', 'published', c.published);
113
+ }
114
+ return c;
115
+ }
116
+ export function sanitizeInput(input) {
117
+ // Remove potentially dangerous characters
118
+ return input
119
+ .replace(/[<>]/g, '') // Remove angle brackets
120
+ .replace(/javascript:/gi, '') // Remove javascript: protocol
121
+ .replace(/on\w+=/gi, '') // Remove event handlers
122
+ .trim();
123
+ }
124
+ export function validateProjectId(projectId) {
125
+ // Project ID should be alphanumeric with hyphens and underscores
126
+ const projectIdPattern = /^[a-zA-Z0-9_-]+$/;
127
+ return projectIdPattern.test(projectId) && projectId.length >= 3 && projectId.length <= 50;
128
+ }
129
+ export function validateTimestamp(timestamp) {
130
+ // Timestamp should be a reasonable Unix timestamp (after 2020, before 2050)
131
+ const minTimestamp = 1577836800000; // 2020-01-01
132
+ const maxTimestamp = 2524608000000; // 2050-01-01
133
+ return timestamp >= minTimestamp && timestamp <= maxTimestamp;
134
+ }
135
+ export function validateUrl(url) {
136
+ try {
137
+ new URL(url);
138
+ return true;
139
+ }
140
+ catch {
141
+ return false;
142
+ }
143
+ }
144
+ export function validateVersion(version) {
145
+ // Validate semantic version format
146
+ const semverPattern = /^\d+\.\d+\.\d+(?:-[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*)?(?:\+[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*)?$/;
147
+ return semverPattern.test(version);
148
+ }
149
+ export function isValidJSON(str) {
150
+ try {
151
+ JSON.parse(str);
152
+ return true;
153
+ }
154
+ catch {
155
+ return false;
156
+ }
157
+ }
package/jest.config.js ADDED
@@ -0,0 +1,14 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
4
+ roots: ['<rootDir>/src'],
5
+ testMatch: ['**/__tests__/**/*.test.ts'],
6
+ transform: {
7
+ '^.+\\.ts$': 'ts-jest',
8
+ },
9
+ collectCoverageFrom: [
10
+ 'src/**/*.ts',
11
+ '!src/**/*.d.ts',
12
+ '!src/__tests__/**',
13
+ ],
14
+ };
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@tracelens/shared",
3
+ "version": "0.1.0",
4
+ "description": "Shared types and utilities for TraceLens",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "dev": "tsc --watch",
10
+ "lint": "eslint src/**/*.ts",
11
+ "test": "jest",
12
+ "type-check": "tsc --noEmit"
13
+ },
14
+ "devDependencies": {
15
+ "@tracelens/eslint-config": "file:../../tools/eslint-config",
16
+ "@tracelens/tsconfig": "file:../../tools/tsconfig",
17
+ "@types/jest": "^29.0.0",
18
+ "jest": "^29.0.0",
19
+ "ts-jest": "^29.4.6",
20
+ "typescript": "^5.0.0"
21
+ }
22
+ }
@@ -0,0 +1,19 @@
1
+ // Basic validation test
2
+ import { validateProjectId, validateTimestamp, validateVersion } from '../utils/validation';
3
+
4
+ describe('Basic Validation', () => {
5
+ test('validateProjectId works', () => {
6
+ expect(validateProjectId('my-project')).toBe(true);
7
+ expect(validateProjectId('ab')).toBe(false);
8
+ });
9
+
10
+ test('validateTimestamp works', () => {
11
+ expect(validateTimestamp(Date.now())).toBe(true);
12
+ expect(validateTimestamp(0)).toBe(false);
13
+ });
14
+
15
+ test('validateVersion works', () => {
16
+ expect(validateVersion('1.0.0')).toBe(true);
17
+ expect(validateVersion('invalid')).toBe(false);
18
+ });
19
+ });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ // TraceLens Shared Types and Utilities
2
+ export * from './types';
3
+ export * from './utils';
4
+ export * from './schemas';
@@ -0,0 +1,187 @@
1
+ // Dependency snapshot schema for TraceLens
2
+ export const DependencySnapshotSchema = {
3
+ type: 'object',
4
+ required: [
5
+ 'id',
6
+ 'projectId',
7
+ 'timestamp',
8
+ 'environment',
9
+ 'nodeVersion',
10
+ 'packageManager',
11
+ 'dependencies',
12
+ 'runtimeDependencies',
13
+ 'totalSize'
14
+ ],
15
+ properties: {
16
+ id: {
17
+ type: 'string',
18
+ pattern: '^[a-zA-Z0-9_-]+$',
19
+ minLength: 1,
20
+ maxLength: 100,
21
+ description: 'Unique identifier for this dependency snapshot'
22
+ },
23
+ projectId: {
24
+ type: 'string',
25
+ pattern: '^[a-zA-Z0-9_-]+$',
26
+ minLength: 3,
27
+ maxLength: 50,
28
+ description: 'Project identifier'
29
+ },
30
+ timestamp: {
31
+ type: 'number',
32
+ minimum: 1577836800000, // 2020-01-01
33
+ maximum: 2524608000000, // 2050-01-01
34
+ description: 'Snapshot timestamp in milliseconds since epoch'
35
+ },
36
+ environment: {
37
+ type: 'string',
38
+ enum: ['development', 'production', 'test'],
39
+ description: 'Environment where snapshot was taken'
40
+ },
41
+ nodeVersion: {
42
+ type: 'string',
43
+ pattern: '^v?\\d+\\.\\d+\\.\\d+',
44
+ description: 'Node.js version (e.g., v18.17.0)'
45
+ },
46
+ npmVersion: {
47
+ type: 'string',
48
+ pattern: '^\\d+\\.\\d+\\.\\d+',
49
+ description: 'npm version if applicable'
50
+ },
51
+ yarnVersion: {
52
+ type: 'string',
53
+ pattern: '^\\d+\\.\\d+\\.\\d+',
54
+ description: 'Yarn version if applicable'
55
+ },
56
+ packageManager: {
57
+ type: 'string',
58
+ enum: ['npm', 'yarn', 'pnpm'],
59
+ description: 'Package manager used'
60
+ },
61
+ dependencies: {
62
+ type: 'array',
63
+ items: {
64
+ $ref: '#/definitions/PackageDependency'
65
+ },
66
+ maxItems: 10000,
67
+ description: 'List of package dependencies'
68
+ },
69
+ runtimeDependencies: {
70
+ type: 'array',
71
+ items: {
72
+ $ref: '#/definitions/RuntimeDependency'
73
+ },
74
+ maxItems: 10000,
75
+ description: 'List of runtime dependencies with execution data'
76
+ },
77
+ totalSize: {
78
+ type: 'number',
79
+ minimum: 0,
80
+ description: 'Total size of all dependencies in bytes'
81
+ },
82
+ bundleSize: {
83
+ type: 'number',
84
+ minimum: 0,
85
+ description: 'Bundle size in bytes if applicable'
86
+ }
87
+ },
88
+ definitions: {
89
+ PackageDependency: {
90
+ type: 'object',
91
+ required: ['name', 'version', 'type'],
92
+ properties: {
93
+ name: {
94
+ type: 'string',
95
+ pattern: '^(@[a-z0-9-~][a-z0-9-._~]*/)?[a-z0-9-~][a-z0-9-._~]*$',
96
+ maxLength: 214,
97
+ description: 'Package name (npm naming rules)'
98
+ },
99
+ version: {
100
+ type: 'string',
101
+ pattern: '^\\d+\\.\\d+\\.\\d+(?:-[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)?(?:\\+[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)?$',
102
+ description: 'Semantic version'
103
+ },
104
+ type: {
105
+ type: 'string',
106
+ enum: ['production', 'development', 'peer', 'optional', 'bundled'],
107
+ description: 'Dependency type'
108
+ },
109
+ resolved: {
110
+ type: 'string',
111
+ format: 'uri',
112
+ description: 'Resolved URL for the package'
113
+ },
114
+ integrity: {
115
+ type: 'string',
116
+ pattern: '^(sha1|sha256|sha384|sha512)-[A-Za-z0-9+/]+=*$',
117
+ description: 'Package integrity hash'
118
+ },
119
+ dev: {
120
+ type: 'boolean',
121
+ description: 'Whether this is a development dependency'
122
+ },
123
+ optional: {
124
+ type: 'boolean',
125
+ description: 'Whether this is an optional dependency'
126
+ },
127
+ bundled: {
128
+ type: 'boolean',
129
+ description: 'Whether this dependency is bundled'
130
+ }
131
+ },
132
+ additionalProperties: false
133
+ },
134
+ RuntimeDependency: {
135
+ type: 'object',
136
+ required: ['name', 'version', 'loadTime', 'executionTime', 'memoryUsage', 'importPath', 'isEsm'],
137
+ properties: {
138
+ name: {
139
+ type: 'string',
140
+ pattern: '^(@[a-z0-9-~][a-z0-9-._~]*/)?[a-z0-9-~][a-z0-9-._~]*$',
141
+ maxLength: 214,
142
+ description: 'Package name'
143
+ },
144
+ version: {
145
+ type: 'string',
146
+ pattern: '^\\d+\\.\\d+\\.\\d+(?:-[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)?(?:\\+[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)?$',
147
+ description: 'Package version'
148
+ },
149
+ loadTime: {
150
+ type: 'number',
151
+ minimum: 0,
152
+ description: 'Time to load the module in milliseconds'
153
+ },
154
+ executionTime: {
155
+ type: 'number',
156
+ minimum: 0,
157
+ description: 'Time to execute module initialization in milliseconds'
158
+ },
159
+ memoryUsage: {
160
+ type: 'number',
161
+ minimum: 0,
162
+ description: 'Memory usage in bytes'
163
+ },
164
+ importPath: {
165
+ type: 'string',
166
+ maxLength: 1024,
167
+ description: 'Import path used to load the module'
168
+ },
169
+ isEsm: {
170
+ type: 'boolean',
171
+ description: 'Whether the module is an ES module'
172
+ },
173
+ exports: {
174
+ type: 'array',
175
+ items: {
176
+ type: 'string',
177
+ maxLength: 256
178
+ },
179
+ maxItems: 1000,
180
+ description: 'List of exported symbols'
181
+ }
182
+ },
183
+ additionalProperties: false
184
+ }
185
+ },
186
+ additionalProperties: false
187
+ } as const;
@@ -0,0 +1,176 @@
1
+ // Error event schema for TraceLens
2
+ export const ErrorEventSchema = {
3
+ type: 'object',
4
+ required: ['id', 'timestamp', 'type', 'message', 'source', 'projectId'],
5
+ properties: {
6
+ id: {
7
+ type: 'string',
8
+ pattern: '^[a-zA-Z0-9_-]+$',
9
+ minLength: 1,
10
+ maxLength: 100,
11
+ description: 'Unique identifier for this error event'
12
+ },
13
+ timestamp: {
14
+ type: 'number',
15
+ minimum: 1577836800000, // 2020-01-01
16
+ maximum: 2524608000000, // 2050-01-01
17
+ description: 'Error timestamp in milliseconds since epoch'
18
+ },
19
+ type: {
20
+ type: 'string',
21
+ enum: [
22
+ 'javascript-error',
23
+ 'unhandled-promise-rejection',
24
+ 'resource-error',
25
+ 'network-error',
26
+ 'csp-violation',
27
+ 'server-error',
28
+ 'database-error',
29
+ 'validation-error'
30
+ ],
31
+ description: 'Type of error that occurred'
32
+ },
33
+ message: {
34
+ type: 'string',
35
+ maxLength: 2048,
36
+ description: 'Error message'
37
+ },
38
+ source: {
39
+ type: 'string',
40
+ enum: ['browser', 'server', 'network'],
41
+ description: 'Source of the error'
42
+ },
43
+ projectId: {
44
+ type: 'string',
45
+ pattern: '^[a-zA-Z0-9_-]+$',
46
+ minLength: 3,
47
+ maxLength: 50,
48
+ description: 'Project identifier'
49
+ },
50
+ stack: {
51
+ type: 'string',
52
+ maxLength: 8192,
53
+ description: 'Error stack trace'
54
+ },
55
+ filename: {
56
+ type: 'string',
57
+ maxLength: 1024,
58
+ description: 'File where error occurred'
59
+ },
60
+ lineno: {
61
+ type: 'number',
62
+ minimum: 0,
63
+ description: 'Line number where error occurred'
64
+ },
65
+ colno: {
66
+ type: 'number',
67
+ minimum: 0,
68
+ description: 'Column number where error occurred'
69
+ },
70
+ url: {
71
+ type: 'string',
72
+ format: 'uri',
73
+ maxLength: 2048,
74
+ description: 'URL where error occurred'
75
+ },
76
+ userAgent: {
77
+ type: 'string',
78
+ maxLength: 512,
79
+ description: 'User agent string'
80
+ },
81
+ userId: {
82
+ type: 'string',
83
+ maxLength: 100,
84
+ description: 'User identifier (if available)'
85
+ },
86
+ sessionId: {
87
+ type: 'string',
88
+ maxLength: 100,
89
+ description: 'Session identifier'
90
+ },
91
+ traceId: {
92
+ type: 'string',
93
+ pattern: '^[a-f0-9]{32}$',
94
+ description: 'Associated trace ID if available'
95
+ },
96
+ spanId: {
97
+ type: 'string',
98
+ pattern: '^[a-f0-9]{16}$',
99
+ description: 'Associated span ID if available'
100
+ },
101
+ severity: {
102
+ type: 'string',
103
+ enum: ['low', 'medium', 'high', 'critical'],
104
+ description: 'Error severity level'
105
+ },
106
+ tags: {
107
+ type: 'object',
108
+ patternProperties: {
109
+ '^[a-zA-Z][a-zA-Z0-9._-]*$': {
110
+ oneOf: [
111
+ { type: 'string', maxLength: 256 },
112
+ { type: 'number' },
113
+ { type: 'boolean' }
114
+ ]
115
+ }
116
+ },
117
+ additionalProperties: false,
118
+ maxProperties: 50,
119
+ description: 'Additional tags for categorization'
120
+ },
121
+ context: {
122
+ type: 'object',
123
+ properties: {
124
+ component: {
125
+ type: 'string',
126
+ maxLength: 256,
127
+ description: 'Component where error occurred'
128
+ },
129
+ action: {
130
+ type: 'string',
131
+ maxLength: 256,
132
+ description: 'Action being performed when error occurred'
133
+ },
134
+ environment: {
135
+ type: 'string',
136
+ enum: ['development', 'staging', 'production'],
137
+ description: 'Environment where error occurred'
138
+ },
139
+ version: {
140
+ type: 'string',
141
+ maxLength: 50,
142
+ description: 'Application version'
143
+ },
144
+ buildId: {
145
+ type: 'string',
146
+ maxLength: 100,
147
+ description: 'Build identifier'
148
+ }
149
+ },
150
+ additionalProperties: false,
151
+ description: 'Additional context about the error'
152
+ },
153
+ fingerprint: {
154
+ type: 'string',
155
+ pattern: '^[a-f0-9]{32}$',
156
+ description: 'Error fingerprint for grouping similar errors'
157
+ },
158
+ count: {
159
+ type: 'number',
160
+ minimum: 1,
161
+ default: 1,
162
+ description: 'Number of times this error occurred'
163
+ },
164
+ firstSeen: {
165
+ type: 'number',
166
+ minimum: 1577836800000,
167
+ description: 'Timestamp when this error was first seen'
168
+ },
169
+ lastSeen: {
170
+ type: 'number',
171
+ minimum: 1577836800000,
172
+ description: 'Timestamp when this error was last seen'
173
+ }
174
+ },
175
+ additionalProperties: false
176
+ } as const;
@@ -0,0 +1,5 @@
1
+ // Schema exports
2
+ export * from './performance.schema';
3
+ export * from './trace.schema';
4
+ export * from './dependency.schema';
5
+ export * from './error.schema';