@bugspotter/sdk 0.1.0-alpha.2 → 0.1.2-alpha.5
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/CHANGELOG.md +46 -0
- package/README.md +156 -84
- package/dist/bugspotter.min.js +1 -1
- package/dist/capture/network.js +5 -2
- package/dist/collectors/dom.js +2 -1
- package/dist/constants.d.ts +13 -0
- package/dist/constants.js +16 -0
- package/dist/core/file-upload-handler.d.ts +61 -0
- package/dist/core/file-upload-handler.js +157 -0
- package/dist/core/transport.d.ts +14 -25
- package/dist/core/transport.js +39 -145
- package/dist/index.d.ts +19 -7
- package/dist/index.esm.js +103 -47
- package/dist/index.js +115 -54
- package/dist/utils/config-validator.d.ts +14 -0
- package/dist/utils/config-validator.js +28 -0
- package/dist/utils/url-helpers.d.ts +28 -0
- package/dist/utils/url-helpers.js +64 -0
- package/dist/version.d.ts +8 -0
- package/dist/version.js +11 -0
- package/dist/widget/button.d.ts +5 -0
- package/dist/widget/button.js +50 -12
- package/dist/widget/components/form-validator.d.ts +2 -2
- package/dist/widget/components/form-validator.js +7 -2
- package/dist/widget/modal.d.ts +1 -1
- package/dist/widget/modal.js +2 -1
- package/docs/SESSION_REPLAY.md +66 -4
- package/package.json +5 -2
- package/scripts/generate-version.js +39 -0
- package/tsconfig.cjs.json +15 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* URL Helper Utilities
|
|
4
|
+
* Extract base API URL from endpoint configuration
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.InvalidEndpointError = void 0;
|
|
8
|
+
exports.stripEndpointSuffix = stripEndpointSuffix;
|
|
9
|
+
exports.getApiBaseUrl = getApiBaseUrl;
|
|
10
|
+
const logger_1 = require("./logger");
|
|
11
|
+
const logger = (0, logger_1.getLogger)();
|
|
12
|
+
/**
|
|
13
|
+
* Custom error for invalid endpoint URLs
|
|
14
|
+
*/
|
|
15
|
+
class InvalidEndpointError extends Error {
|
|
16
|
+
constructor(endpoint, reason) {
|
|
17
|
+
super(`Invalid endpoint URL: ${endpoint}. ${reason}`);
|
|
18
|
+
this.endpoint = endpoint;
|
|
19
|
+
this.reason = reason;
|
|
20
|
+
this.name = 'InvalidEndpointError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.InvalidEndpointError = InvalidEndpointError;
|
|
24
|
+
/**
|
|
25
|
+
* Strip known endpoint suffixes from path
|
|
26
|
+
* Removes /api/v1/reports path
|
|
27
|
+
*/
|
|
28
|
+
function stripEndpointSuffix(path) {
|
|
29
|
+
// Use lastIndexOf to handle paths like '/prefix/api/v1/reports'
|
|
30
|
+
const reportsIndex = path.lastIndexOf('/api/v1/reports');
|
|
31
|
+
if (reportsIndex !== -1) {
|
|
32
|
+
return path.substring(0, reportsIndex);
|
|
33
|
+
}
|
|
34
|
+
// Remove trailing slash
|
|
35
|
+
return path.replace(/\/$/, '') || '';
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Extract base API URL from endpoint
|
|
39
|
+
* Returns scheme + host + base path (without /api/v1/reports suffix)
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* getApiBaseUrl('https://api.example.com/api/v1/reports')
|
|
43
|
+
* // Returns: 'https://api.example.com'
|
|
44
|
+
*
|
|
45
|
+
* @throws InvalidEndpointError if endpoint is not a valid absolute URL
|
|
46
|
+
*/
|
|
47
|
+
function getApiBaseUrl(endpoint) {
|
|
48
|
+
if (!endpoint) {
|
|
49
|
+
throw new InvalidEndpointError('', 'No endpoint configured');
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const url = new URL(endpoint);
|
|
53
|
+
const basePath = stripEndpointSuffix(url.pathname);
|
|
54
|
+
return url.origin + basePath;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
58
|
+
logger.error('Invalid endpoint URL - must be a valid absolute URL', {
|
|
59
|
+
endpoint,
|
|
60
|
+
error: errorMessage,
|
|
61
|
+
});
|
|
62
|
+
throw new InvalidEndpointError(endpoint, 'Must be a valid absolute URL (e.g., https://api.example.com/api/v1/reports)');
|
|
63
|
+
}
|
|
64
|
+
}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SDK version - auto-generated from package.json
|
|
4
|
+
* DO NOT EDIT THIS FILE MANUALLY
|
|
5
|
+
*
|
|
6
|
+
* This file is automatically generated during the build process.
|
|
7
|
+
* To update the version, modify package.json
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.VERSION = void 0;
|
|
11
|
+
exports.VERSION = '0.1.2-alpha.5';
|
package/dist/widget/button.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
type ButtonPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
2
2
|
export interface FloatingButtonOptions {
|
|
3
3
|
position?: ButtonPosition;
|
|
4
|
+
/** Icon to display - can be text/emoji or 'svg' for default bug icon */
|
|
4
5
|
icon?: string;
|
|
6
|
+
/** Custom SVG icon (overrides icon if provided) */
|
|
7
|
+
customSvg?: string;
|
|
5
8
|
backgroundColor?: string;
|
|
6
9
|
size?: number;
|
|
7
10
|
offset?: {
|
|
@@ -9,6 +12,8 @@ export interface FloatingButtonOptions {
|
|
|
9
12
|
y: number;
|
|
10
13
|
};
|
|
11
14
|
zIndex?: number;
|
|
15
|
+
/** Custom tooltip text */
|
|
16
|
+
tooltip?: string;
|
|
12
17
|
}
|
|
13
18
|
export declare class FloatingButton {
|
|
14
19
|
private button;
|
package/dist/widget/button.js
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FloatingButton = void 0;
|
|
4
|
+
// Professional bug report icon SVG
|
|
5
|
+
const DEFAULT_SVG_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
6
|
+
<path d="M8 2v4"/>
|
|
7
|
+
<path d="M16 2v4"/>
|
|
8
|
+
<path d="M12 12v5"/>
|
|
9
|
+
<circle cx="12" cy="10" r="4"/>
|
|
10
|
+
<path d="M9 16c-1.5 1-3 2-3 4h12c0-2-1.5-3-3-4"/>
|
|
11
|
+
<path d="M3 8h4"/>
|
|
12
|
+
<path d="M17 8h4"/>
|
|
13
|
+
<path d="M5 12h2"/>
|
|
14
|
+
<path d="M17 12h2"/>
|
|
15
|
+
<path d="M6 16h2"/>
|
|
16
|
+
<path d="M16 16h2"/>
|
|
17
|
+
</svg>`;
|
|
4
18
|
const DEFAULT_BUTTON_OPTIONS = {
|
|
5
19
|
position: 'bottom-right',
|
|
6
|
-
icon: '
|
|
7
|
-
|
|
8
|
-
|
|
20
|
+
icon: 'svg', // Use SVG icon by default
|
|
21
|
+
customSvg: undefined,
|
|
22
|
+
backgroundColor: '#2563eb', // Professional blue color
|
|
23
|
+
size: 56,
|
|
9
24
|
offset: { x: 20, y: 20 },
|
|
10
25
|
zIndex: 999999,
|
|
26
|
+
tooltip: 'Report an Issue',
|
|
11
27
|
};
|
|
12
28
|
const BUTTON_STYLES = {
|
|
13
29
|
transition: 'transform 0.2s ease, box-shadow 0.2s ease',
|
|
@@ -23,7 +39,7 @@ const BUTTON_STYLES = {
|
|
|
23
39
|
};
|
|
24
40
|
class FloatingButton {
|
|
25
41
|
constructor(options = {}) {
|
|
26
|
-
var _a, _b, _c, _d, _e, _f;
|
|
42
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
27
43
|
this.eventHandlers = new Map();
|
|
28
44
|
this.handleMouseEnter = () => {
|
|
29
45
|
this.button.style.transform = BUTTON_STYLES.transform.hover;
|
|
@@ -42,10 +58,12 @@ class FloatingButton {
|
|
|
42
58
|
this.options = {
|
|
43
59
|
position: (_a = options.position) !== null && _a !== void 0 ? _a : DEFAULT_BUTTON_OPTIONS.position,
|
|
44
60
|
icon: (_b = options.icon) !== null && _b !== void 0 ? _b : DEFAULT_BUTTON_OPTIONS.icon,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
61
|
+
customSvg: (_c = options.customSvg) !== null && _c !== void 0 ? _c : DEFAULT_BUTTON_OPTIONS.customSvg,
|
|
62
|
+
backgroundColor: (_d = options.backgroundColor) !== null && _d !== void 0 ? _d : DEFAULT_BUTTON_OPTIONS.backgroundColor,
|
|
63
|
+
size: (_e = options.size) !== null && _e !== void 0 ? _e : DEFAULT_BUTTON_OPTIONS.size,
|
|
64
|
+
offset: (_f = options.offset) !== null && _f !== void 0 ? _f : DEFAULT_BUTTON_OPTIONS.offset,
|
|
65
|
+
zIndex: (_g = options.zIndex) !== null && _g !== void 0 ? _g : DEFAULT_BUTTON_OPTIONS.zIndex,
|
|
66
|
+
tooltip: (_h = options.tooltip) !== null && _h !== void 0 ? _h : DEFAULT_BUTTON_OPTIONS.tooltip,
|
|
49
67
|
};
|
|
50
68
|
this.button = this.createButton();
|
|
51
69
|
// Ensure DOM is ready before appending
|
|
@@ -60,8 +78,18 @@ class FloatingButton {
|
|
|
60
78
|
}
|
|
61
79
|
createButton() {
|
|
62
80
|
const btn = document.createElement('button');
|
|
63
|
-
|
|
64
|
-
|
|
81
|
+
// Set button content (SVG or text)
|
|
82
|
+
if (this.options.customSvg) {
|
|
83
|
+
btn.innerHTML = this.options.customSvg;
|
|
84
|
+
}
|
|
85
|
+
else if (this.options.icon === 'svg') {
|
|
86
|
+
btn.innerHTML = DEFAULT_SVG_ICON;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
btn.textContent = this.options.icon;
|
|
90
|
+
}
|
|
91
|
+
btn.setAttribute('aria-label', this.options.tooltip);
|
|
92
|
+
btn.setAttribute('title', this.options.tooltip);
|
|
65
93
|
btn.setAttribute('data-bugspotter-exclude', 'true');
|
|
66
94
|
btn.style.cssText = this.getButtonStyles();
|
|
67
95
|
this.addHoverEffects(btn);
|
|
@@ -70,6 +98,9 @@ class FloatingButton {
|
|
|
70
98
|
getButtonStyles() {
|
|
71
99
|
const { position, size, offset, backgroundColor, zIndex } = this.options;
|
|
72
100
|
const positionStyles = this.getPositionStyles(position, offset);
|
|
101
|
+
// SVG icons need slightly different sizing
|
|
102
|
+
const isSvgIcon = this.options.customSvg || this.options.icon === 'svg';
|
|
103
|
+
const iconSize = size * 0.5;
|
|
73
104
|
return `
|
|
74
105
|
position: fixed;
|
|
75
106
|
${positionStyles}
|
|
@@ -80,10 +111,11 @@ class FloatingButton {
|
|
|
80
111
|
color: white;
|
|
81
112
|
border: none;
|
|
82
113
|
cursor: pointer;
|
|
83
|
-
font-size: ${
|
|
114
|
+
font-size: ${iconSize}px;
|
|
84
115
|
display: flex;
|
|
85
116
|
align-items: center;
|
|
86
117
|
justify-content: center;
|
|
118
|
+
padding: ${isSvgIcon ? size * 0.25 : 0}px;
|
|
87
119
|
box-shadow: ${BUTTON_STYLES.boxShadow.default};
|
|
88
120
|
transition: ${BUTTON_STYLES.transition};
|
|
89
121
|
z-index: ${zIndex};
|
|
@@ -125,7 +157,13 @@ class FloatingButton {
|
|
|
125
157
|
this.button.style.display = 'none';
|
|
126
158
|
}
|
|
127
159
|
setIcon(icon) {
|
|
128
|
-
this.
|
|
160
|
+
this.options.icon = icon;
|
|
161
|
+
if (icon === 'svg') {
|
|
162
|
+
this.button.innerHTML = DEFAULT_SVG_ICON;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
this.button.textContent = icon;
|
|
166
|
+
}
|
|
129
167
|
}
|
|
130
168
|
setBackgroundColor(color) {
|
|
131
169
|
this.button.style.backgroundColor = color;
|
|
@@ -15,7 +15,7 @@ export interface ValidationErrors {
|
|
|
15
15
|
}
|
|
16
16
|
export interface FormData {
|
|
17
17
|
title: string;
|
|
18
|
-
description
|
|
18
|
+
description?: string;
|
|
19
19
|
piiDetected: boolean;
|
|
20
20
|
piiConfirmed: boolean;
|
|
21
21
|
}
|
|
@@ -41,7 +41,7 @@ export declare class FormValidator {
|
|
|
41
41
|
/**
|
|
42
42
|
* Validate description field
|
|
43
43
|
*/
|
|
44
|
-
validateDescription(description
|
|
44
|
+
validateDescription(description?: string): string | null;
|
|
45
45
|
/**
|
|
46
46
|
* Validate single field by name
|
|
47
47
|
*/
|
|
@@ -58,9 +58,14 @@ class FormValidator {
|
|
|
58
58
|
* Validate description field
|
|
59
59
|
*/
|
|
60
60
|
validateDescription(description) {
|
|
61
|
+
// Description is optional
|
|
62
|
+
if (!description) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
61
65
|
const trimmed = description.trim();
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
// Whitespace-only is invalid (user attempted to provide content but it's meaningless)
|
|
67
|
+
if (trimmed.length === 0) {
|
|
68
|
+
return 'Description cannot be only whitespace';
|
|
64
69
|
}
|
|
65
70
|
if (trimmed.length < this.minDescriptionLength) {
|
|
66
71
|
return `Description must be at least ${this.minDescriptionLength} characters`;
|
package/dist/widget/modal.d.ts
CHANGED
package/dist/widget/modal.js
CHANGED
|
@@ -219,6 +219,7 @@ class BugReportModal {
|
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
async handleSubmit(e) {
|
|
222
|
+
var _a;
|
|
222
223
|
e.preventDefault();
|
|
223
224
|
const elements = this.domCache.get();
|
|
224
225
|
const formData = {
|
|
@@ -270,7 +271,7 @@ class BugReportModal {
|
|
|
270
271
|
// Submit
|
|
271
272
|
const bugReportData = {
|
|
272
273
|
title: formData.title.trim(),
|
|
273
|
-
description: formData.description.trim(),
|
|
274
|
+
description: (_a = formData.description) === null || _a === void 0 ? void 0 : _a.trim(),
|
|
274
275
|
};
|
|
275
276
|
try {
|
|
276
277
|
await this.options.onSubmit(bugReportData);
|
package/docs/SESSION_REPLAY.md
CHANGED
|
@@ -85,22 +85,84 @@ console.log(report.replay); // Array of rrweb events
|
|
|
85
85
|
|
|
86
86
|
### 4. Event Transmission
|
|
87
87
|
|
|
88
|
-
The replay events are
|
|
88
|
+
The replay events are compressed and uploaded via presigned URLs using an optimized 3-request flow:
|
|
89
|
+
|
|
90
|
+
**Step 1: Create Bug Report with Presigned URLs**
|
|
89
91
|
|
|
90
92
|
```typescript
|
|
93
|
+
// Initial bug report with flags indicating which files will be uploaded
|
|
94
|
+
POST /api/v1/reports
|
|
91
95
|
{
|
|
92
96
|
title: "Bug title",
|
|
93
97
|
description: "Bug description",
|
|
94
98
|
report: {
|
|
95
|
-
screenshot: "...",
|
|
96
99
|
console: [...],
|
|
97
100
|
network: [...],
|
|
98
|
-
metadata: {...}
|
|
99
|
-
|
|
101
|
+
metadata: {...}
|
|
102
|
+
},
|
|
103
|
+
hasScreenshot: true, // SDK sets this if screenshot was captured
|
|
104
|
+
hasReplay: true // SDK sets this if replay events were recorded
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Response includes bug report ID AND presigned URLs
|
|
108
|
+
{
|
|
109
|
+
"success": true,
|
|
110
|
+
"data": {
|
|
111
|
+
"id": "bug-uuid-here",
|
|
112
|
+
"title": "Bug title",
|
|
113
|
+
"presignedUrls": {
|
|
114
|
+
"screenshot": {
|
|
115
|
+
"uploadUrl": "https://s3.amazonaws.com/...",
|
|
116
|
+
"storageKey": "screenshots/project/bug/screenshot.png"
|
|
117
|
+
},
|
|
118
|
+
"replay": {
|
|
119
|
+
"uploadUrl": "https://s3.amazonaws.com/...",
|
|
120
|
+
"storageKey": "replays/project/bug/replay.gz"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
100
123
|
}
|
|
101
124
|
}
|
|
102
125
|
```
|
|
103
126
|
|
|
127
|
+
**Step 2: Upload Files Directly to S3**
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Upload screenshot to presigned URL (parallel with replay)
|
|
131
|
+
PUT https://s3.amazonaws.com/presigned-screenshot-url
|
|
132
|
+
Content-Type: image/png
|
|
133
|
+
<binary screenshot data>
|
|
134
|
+
|
|
135
|
+
// Upload compressed replay to presigned URL (parallel with screenshot)
|
|
136
|
+
PUT https://s3.amazonaws.com/presigned-replay-url
|
|
137
|
+
Content-Type: application/gzip
|
|
138
|
+
<compressed replay events>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Step 3: Confirm Uploads**
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// Confirm screenshot upload
|
|
145
|
+
POST /api/v1/reports/{bugId}/confirm-upload
|
|
146
|
+
{
|
|
147
|
+
"fileType": "screenshot"
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Confirm replay upload
|
|
151
|
+
POST /api/v1/reports/{bugId}/confirm-upload
|
|
152
|
+
{
|
|
153
|
+
"fileType": "replay"
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Optimized Flow Benefits:**
|
|
158
|
+
|
|
159
|
+
- **40% fewer HTTP requests** - 3 requests vs 5 in old flow
|
|
160
|
+
- **Reduces server load** - Files go directly to storage (S3)
|
|
161
|
+
- **Improves performance** - No API server bottleneck for large files
|
|
162
|
+
- **Better scalability** - Storage handles the bandwidth
|
|
163
|
+
- **Parallel uploads** - Screenshot and replay upload concurrently
|
|
164
|
+
- **Automatic compression** - Replay events are gzipped before upload
|
|
165
|
+
|
|
104
166
|
## Event Types
|
|
105
167
|
|
|
106
168
|
The DOM collector captures the following event types:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bugspotter/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2-alpha.5",
|
|
4
4
|
"description": "Professional bug reporting SDK with screenshots, session replay, and automatic error capture for web applications",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -16,13 +16,16 @@
|
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
18
|
"dev": "webpack --watch --mode development",
|
|
19
|
+
"generate-version": "node scripts/generate-version.js",
|
|
20
|
+
"prebuild": "npm run generate-version",
|
|
19
21
|
"build": "npm run build:webpack && npm run build:esm && npm run build:cjs",
|
|
20
22
|
"build:webpack": "webpack --mode production",
|
|
21
23
|
"build:esm": "tsc --project tsconfig.build.json --module ES2020 --outDir dist/esm && shx mv dist/esm/index.js dist/index.esm.js && shx rm -rf dist/esm",
|
|
22
|
-
"build:cjs": "tsc --project tsconfig.
|
|
24
|
+
"build:cjs": "tsc --project tsconfig.cjs.json",
|
|
23
25
|
"prepublishOnly": "npm run build && npm test",
|
|
24
26
|
"lint": "eslint \"src/**/*.{ts,js}\"",
|
|
25
27
|
"lint:fix": "eslint \"src/**/*.{ts,js}\" --fix",
|
|
28
|
+
"pretest": "npm run generate-version",
|
|
26
29
|
"test": "vitest run",
|
|
27
30
|
"test:watch": "vitest",
|
|
28
31
|
"test:ui": "vitest --ui",
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Generate version.ts file from package.json
|
|
4
|
+
* This ensures VERSION is available in all build outputs (UMD, ESM, CJS)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
// Read package.json
|
|
12
|
+
const packageJsonPath = path.join(__dirname, '../package.json');
|
|
13
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
14
|
+
|
|
15
|
+
if (!packageJson.version) {
|
|
16
|
+
console.error('Error: No version found in package.json');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Generate version.ts content with proper documentation
|
|
21
|
+
const versionFilePath = path.join(__dirname, '../src/version.ts');
|
|
22
|
+
const versionFileContent = `/**
|
|
23
|
+
* SDK version - auto-generated from package.json
|
|
24
|
+
* DO NOT EDIT THIS FILE MANUALLY
|
|
25
|
+
*
|
|
26
|
+
* This file is automatically generated during the build process.
|
|
27
|
+
* To update the version, modify package.json
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
export const VERSION = '${packageJson.version}';
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
// Write the file
|
|
34
|
+
fs.writeFileSync(versionFilePath, versionFileContent, 'utf8');
|
|
35
|
+
console.log(`✓ Generated version.ts with version ${packageJson.version}`);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error('Error generating version.ts:', error.message);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"extends": "../../tsconfig.json",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"target": "ES2017",
|
|
6
|
+
"module": "CommonJS",
|
|
7
|
+
"lib": ["ES2017", "DOM", "DOM.Iterable"],
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"outDir": "./dist",
|
|
11
|
+
"isolatedModules": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/**/*"],
|
|
14
|
+
"exclude": ["node_modules", "dist", "tests", "**/*.test.ts", "**/*.spec.ts"]
|
|
15
|
+
}
|