tia-gpc-widget 1.0.9 → 1.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.
package/README.md CHANGED
@@ -51,9 +51,70 @@ Intelligent chat widget for TIA GPC integration. Compatible with **React, HTML,
51
51
 
52
52
  ---
53
53
 
54
+ ## 🚀 Auto-Update Loader (Recommended)
55
+
56
+ **NEW!** Install once, get updates forever. No more manual version updates!
57
+
58
+ The **TIA GPC Widget Loader** is a small, stable script (~1KB gzipped) that automatically loads the latest version of the widget. Your clients install it **ONCE** and receive all future updates automatically.
59
+
60
+ ### Quick Start with Loader
61
+
62
+ ```html
63
+ <!DOCTYPE html>
64
+ <html lang="en">
65
+ <head>
66
+ <meta charset="UTF-8">
67
+ <title>My App with TIA GPC</title>
68
+ </head>
69
+ <body>
70
+ <h1>My Application</h1>
71
+
72
+ <!-- TIA GPC Widget Loader (install once, updates forever) -->
73
+ <script src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@latest/dist/loader.min.js"></script>
74
+
75
+ <!-- Widget element -->
76
+ <tia-gpc-widget
77
+ token="your-license-token-here"
78
+ theme="auto"
79
+ position="bottom-right"
80
+ language="en"
81
+ ></tia-gpc-widget>
82
+ </body>
83
+ </html>
84
+ ```
85
+
86
+ **Benefits:**
87
+ - ✅ Install once, never update manually again
88
+ - ✅ Automatic updates when you publish new versions
89
+ - ✅ Built-in error handling and retries
90
+ - ✅ Support for stable/beta channels
91
+ - ✅ Extremely small (~1KB gzipped)
92
+ - ✅ Works with all frameworks (HTML, React, Angular, ASP.NET, etc.)
93
+
94
+ [See complete loader documentation and examples →](#loader-advanced-usage)
95
+
96
+ ---
97
+
54
98
  ## 📦 Installation
55
99
 
56
- ### Option 1: NPM (For React/Node Projects)
100
+ ### Option 1: Auto-Update Loader (Recommended)
101
+
102
+ Use the loader for automatic updates:
103
+
104
+ ```html
105
+ <!-- jsDelivr (Recommended) -->
106
+ <script src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@latest/dist/loader.min.js"></script>
107
+
108
+ <!-- unpkg -->
109
+ <script src="https://unpkg.com/tia-gpc-widget@latest/dist/loader.min.js"></script>
110
+ ```
111
+
112
+ Then use the widget as normal:
113
+ ```html
114
+ <tia-gpc-widget token="your-token" theme="auto"></tia-gpc-widget>
115
+ ```
116
+
117
+ ### Option 2: NPM (For React/Node Projects)
57
118
 
58
119
  ```bash
59
120
  npm install tia-gpc-widget
@@ -71,37 +132,35 @@ or with pnpm:
71
132
  pnpm add tia-gpc-widget
72
133
  ```
73
134
 
74
- ### Option 2: CDN (For HTML, Angular, ASP.NET, etc.)
135
+ ### Option 3: Direct CDN (Legacy - Not Recommended)
75
136
 
76
- You can include the widget directly from a CDN:
137
+ ⚠️ **Note:** This method is still supported but **not recommended** for new installations.
138
+ It requires manual updates every time we release a new version.
139
+ **Use the Auto-Update Loader instead** (see Option 1 above).
77
140
 
78
- #### jsDelivr (Recommended)
141
+ #### jsDelivr - Fixed Version
79
142
 
80
143
  ```html
81
- <!-- JavaScript -->
82
- <script src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.0.6/dist/tia-gpc-widget.standalone.js"></script>
83
-
84
- <!-- CSS -->
85
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.0.6/dist/tia-gpc-widget.standalone.css">
144
+ <!-- ⚠️ Legacy method: Requires manual version updates -->
145
+ <script src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.0.9/dist/tia-gpc-widget.standalone.js"></script>
146
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.0.9/dist/tia-gpc-widget.standalone.css">
86
147
  ```
87
148
 
88
- #### unpkg
149
+ #### unpkg - Fixed Version
89
150
 
90
151
  ```html
91
- <!-- JavaScript -->
92
- <script src="https://unpkg.com/tia-gpc-widget@1.0.6/dist/tia-gpc-widget.standalone.js"></script>
93
-
94
- <!-- CSS -->
95
- <link rel="stylesheet" href="https://unpkg.com/tia-gpc-widget@1.0.6/dist/tia-gpc-widget.standalone.css">
152
+ <!-- ⚠️ Legacy method: Requires manual version updates -->
153
+ <script src="https://unpkg.com/tia-gpc-widget@1.0.9/dist/tia-gpc-widget.standalone.js"></script>
154
+ <link rel="stylesheet" href="https://unpkg.com/tia-gpc-widget@1.0.9/dist/tia-gpc-widget.standalone.css">
96
155
  ```
97
156
 
98
- #### Latest Version (Development Only)
157
+ **Why use the loader instead?**
158
+ - ✅ Automatic updates - no code changes needed
159
+ - ✅ Always get bug fixes and improvements
160
+ - ✅ Smaller initial load (~2KB vs ~420KB until needed)
161
+ - ✅ Built-in error handling and fallbacks
99
162
 
100
- ```html
101
- <!-- Always use specific versions in production! -->
102
- <script src="https://cdn.jsdelivr.net/npm/tia-gpc-widget/dist/tia-gpc-widget.standalone.js"></script>
103
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tia-gpc-widget/dist/tia-gpc-widget.standalone.css">
104
- ```
163
+ **For existing installations:** See [Migration Guide](MIGRATION.md) to upgrade to the auto-update loader.
105
164
 
106
165
  ---
107
166
 
@@ -116,9 +175,6 @@ You can include the widget directly from a CDN:
116
175
  <meta charset="UTF-8">
117
176
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
118
177
  <title>My App with TIA GPC</title>
119
-
120
- <!-- Widget CSS -->
121
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.0.6/dist/tia-gpc-widget.standalone.css">
122
178
  </head>
123
179
  <body>
124
180
  <h1>My Application</h1>
@@ -131,8 +187,8 @@ You can include the widget directly from a CDN:
131
187
  language="en"
132
188
  ></tia-gpc-widget>
133
189
 
134
- <!-- Widget JavaScript -->
135
- <script src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.0.6/dist/tia-gpc-widget.standalone.js"></script>
190
+ <!-- Auto-Update Loader (loads latest version automatically) -->
191
+ <script src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@latest/dist/loader.min.js"></script>
136
192
  </body>
137
193
  </html>
138
194
  ```
@@ -164,6 +220,12 @@ export default App;
164
220
 
165
221
  ## 📚 Framework Examples
166
222
 
223
+ > **💡 Important:** The examples below may show both installation methods:
224
+ > - **Recommended:** Auto-Update Loader (install once, updates automatically)
225
+ > - **Legacy:** Direct CDN with fixed version (requires manual updates)
226
+ >
227
+ > **For new installations, always use the Auto-Update Loader** shown in [Option 1](#option-1-auto-update-loader-recommended).
228
+
167
229
  ### 1. React
168
230
 
169
231
  #### Installation
@@ -1089,4 +1151,238 @@ For technical support:
1089
1151
 
1090
1152
  ---
1091
1153
 
1154
+ ## 📚 Loader Advanced Usage
1155
+
1156
+ ### What is the Auto-Update Loader?
1157
+
1158
+ The **TIA GPC Widget Loader** is a revolutionary approach to widget distribution that solves the update problem:
1159
+
1160
+ - **Traditional approach**: Clients must manually update the version number in their code every time you release
1161
+ - **Loader approach**: Clients install once, you control which version they receive via `version.json`
1162
+
1163
+ ### How it Works
1164
+
1165
+ 1. **Client installs the loader** (one time only):
1166
+ ```html
1167
+ <script src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@latest/dist/loader.min.js"></script>
1168
+ ```
1169
+
1170
+ 2. **Loader fetches** `version.json` to determine which widget version to load
1171
+
1172
+ 3. **Loader dynamically loads** the appropriate widget version
1173
+
1174
+ 4. **You publish a new version**:
1175
+ ```bash
1176
+ npm run build # Automatically updates version.json
1177
+ npm publish
1178
+ ```
1179
+
1180
+ 5. **All clients automatically receive the new version** (within minutes, when CDN syncs)
1181
+
1182
+ ### Configuration Options
1183
+
1184
+ #### Loader Attributes
1185
+
1186
+ | Attribute | Type | Default | Description |
1187
+ |-----------|------|---------|-------------|
1188
+ | `data-channel` | `'stable' \| 'beta'` | `'stable'` | Distribution channel |
1189
+ | `data-version` | `string` | `null` | Pin to specific version (disables auto-update) |
1190
+ | `data-debug` | `boolean` | `false` | Enable debug logging |
1191
+ | `data-api-url` | `string` | `null` | Analytics endpoint URL |
1192
+
1193
+ #### Examples
1194
+
1195
+ **Use beta channel:**
1196
+ ```html
1197
+ <script
1198
+ src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@latest/dist/loader.min.js"
1199
+ data-channel="beta"
1200
+ ></script>
1201
+ ```
1202
+
1203
+ **Pin to specific version (no auto-update):**
1204
+ ```html
1205
+ <script
1206
+ src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@latest/dist/loader.min.js"
1207
+ data-version="1.0.8"
1208
+ ></script>
1209
+ ```
1210
+
1211
+ **Enable debug mode:**
1212
+ ```html
1213
+ <script
1214
+ src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@latest/dist/loader.min.js"
1215
+ data-debug="true"
1216
+ ></script>
1217
+ ```
1218
+
1219
+ ### Loader Events
1220
+
1221
+ The loader emits custom events you can listen to:
1222
+
1223
+ ```javascript
1224
+ // Widget loaded successfully
1225
+ window.addEventListener('tia-gpc-loader-ready', (event) => {
1226
+ console.log('Widget loaded:', event.detail);
1227
+ // event.detail = {
1228
+ // version: "1.0.9",
1229
+ // loadTime: 1234, // milliseconds
1230
+ // attempts: 1,
1231
+ // channel: "stable"
1232
+ // }
1233
+ });
1234
+
1235
+ // Widget failed to load
1236
+ window.addEventListener('tia-gpc-loader-error', (event) => {
1237
+ console.error('Widget error:', event.detail);
1238
+ // event.detail = {
1239
+ // error: "Failed to load...",
1240
+ // attempts: 3,
1241
+ // version: "1.0.9"
1242
+ // }
1243
+ });
1244
+ ```
1245
+
1246
+ ### Loader API
1247
+
1248
+ The loader exposes a global `TiaGPCLoader` object:
1249
+
1250
+ ```javascript
1251
+ // Get loader version
1252
+ console.log(window.TiaGPCLoader.version); // "1.0.0"
1253
+
1254
+ // Reload widget
1255
+ window.TiaGPCLoader.reload();
1256
+
1257
+ // Get configuration
1258
+ console.log(window.TiaGPCLoader.config);
1259
+ ```
1260
+
1261
+ ### Version Control with version.json
1262
+
1263
+ The `version.json` file controls which version is served to clients:
1264
+
1265
+ ```json
1266
+ {
1267
+ "version": "1.0.9",
1268
+ "stable": {
1269
+ "version": "1.0.9",
1270
+ "js": "https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.0.9/dist/tia-gpc-widget.standalone.js",
1271
+ "css": "https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.0.9/dist/tia-gpc-widget.standalone.css",
1272
+ "cdn": "jsdelivr"
1273
+ },
1274
+ "beta": {
1275
+ "version": "1.1.0-beta",
1276
+ "js": "https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.1.0-beta/dist/tia-gpc-widget.standalone.js",
1277
+ "css": "https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.1.0-beta/dist/tia-gpc-widget.standalone.css",
1278
+ "cdn": "jsdelivr"
1279
+ }
1280
+ }
1281
+ ```
1282
+
1283
+ This file is automatically generated when you run `npm run build`.
1284
+
1285
+ ### Deployment Workflow
1286
+
1287
+ #### Before (without loader):
1288
+ ```bash
1289
+ # 1. Make changes to widget
1290
+ # 2. Build
1291
+ npm run build
1292
+
1293
+ # 3. Publish to npm
1294
+ npm publish
1295
+
1296
+ # ❌ Clients must manually update their code:
1297
+ # <script src="...@1.0.6/..."></script> → <script src="...@1.0.7/..."></script>
1298
+ ```
1299
+
1300
+ #### After (with loader):
1301
+ ```bash
1302
+ # 1. Make changes to widget
1303
+ # 2. Build (automatically updates version.json)
1304
+ npm run build
1305
+
1306
+ # 3. Publish to npm
1307
+ npm publish
1308
+
1309
+ # ✅ All clients automatically receive the new version!
1310
+ # No manual updates required!
1311
+ ```
1312
+
1313
+ ### Advanced: Gradual Rollout
1314
+
1315
+ You can manually edit `version.json` to implement gradual rollouts:
1316
+
1317
+ ```json
1318
+ {
1319
+ "stable": {
1320
+ "version": "1.0.9",
1321
+ "rollout": {
1322
+ "percentage": 50, // Only 50% of users get this version
1323
+ "whitelist": ["client-id-1", "client-id-2"],
1324
+ "blacklist": ["problematic-client"]
1325
+ }
1326
+ }
1327
+ }
1328
+ ```
1329
+
1330
+ Note: Rollout logic must be implemented on your backend.
1331
+
1332
+ ### Migration Guide
1333
+
1334
+ #### Migrating from Direct CDN Links
1335
+
1336
+ **Before:**
1337
+ ```html
1338
+ <script src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.0.6/dist/tia-gpc-widget.standalone.js"></script>
1339
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tia-gpc-widget@1.0.6/dist/tia-gpc-widget.standalone.css">
1340
+
1341
+ <tia-gpc-widget token="xxx"></tia-gpc-widget>
1342
+ ```
1343
+
1344
+ **After:**
1345
+ ```html
1346
+ <script src="https://cdn.jsdelivr.net/npm/tia-gpc-widget@latest/dist/loader.min.js"></script>
1347
+
1348
+ <tia-gpc-widget token="xxx"></tia-gpc-widget>
1349
+ ```
1350
+
1351
+ That's it! The loader handles everything else.
1352
+
1353
+ ### Troubleshooting
1354
+
1355
+ #### Loader not loading widget
1356
+
1357
+ 1. Open browser console and check for errors
1358
+ 2. Enable debug mode: `data-debug="true"`
1359
+ 3. Check network tab for failed requests
1360
+ 4. Verify `version.json` is accessible
1361
+
1362
+ #### Widget not updating
1363
+
1364
+ 1. Clear browser cache
1365
+ 2. Check that `version.json` has the correct version
1366
+ 3. Wait for CDN to sync (can take 5-10 minutes)
1367
+ 4. Check if client is using `data-version` (which pins to specific version)
1368
+
1369
+ #### Using with Content Security Policy (CSP)
1370
+
1371
+ If your site uses CSP, you may need to add:
1372
+
1373
+ ```html
1374
+ <meta http-equiv="Content-Security-Policy" content="
1375
+ script-src 'self' https://cdn.jsdelivr.net https://unpkg.com;
1376
+ style-src 'self' https://cdn.jsdelivr.net https://unpkg.com;
1377
+ connect-src 'self' https://cdn.jsdelivr.net https://unpkg.com;
1378
+ ">
1379
+ ```
1380
+
1381
+ ### Examples
1382
+
1383
+ See complete examples in the `/examples` folder:
1384
+ - `examples/loader-usage.html` - Complete loader demo with all features
1385
+
1386
+ ---
1387
+
1092
1388
  **Built with ❤️ by the TIA team**
package/dist/loader.js ADDED
@@ -0,0 +1,271 @@
1
+ /**
2
+ * TIA GPC Widget Loader
3
+ * @version 1.0.0
4
+ */
5
+
6
+ (function() {
7
+ 'use strict';
8
+
9
+ const CONFIG = {
10
+ versionUrl: 'https://cdn.jsdelivr.net/npm/tia-gpc-widget@latest/dist/version.json',
11
+ defaultChannel: 'stable',
12
+ timeout: 15000,
13
+ maxRetries: 3,
14
+ retryDelay: 2000,
15
+ fallbackVersion: '1.0.9',
16
+ fallbackCdn: 'https://cdn.jsdelivr.net/npm/tia-gpc-widget'
17
+ };
18
+
19
+ let loadAttempts = 0;
20
+ let loadStartTime = Date.now();
21
+
22
+ const log = {
23
+ info: function(msg, data) {
24
+ console.log('[TIA GPC Loader]', msg, data || '');
25
+ },
26
+ warn: function(msg, data) {
27
+ console.warn('[TIA GPC Loader]', msg, data || '');
28
+ },
29
+ error: function(msg, data) {
30
+ console.error('[TIA GPC Loader]', msg, data || '');
31
+ }
32
+ };
33
+
34
+ function isAlreadyLoaded() {
35
+ return window.TiaGPCWidgetLoaded === true || window.TiaGPC !== undefined;
36
+ }
37
+
38
+ function getLoaderConfig() {
39
+ const scriptTag = document.currentScript ||
40
+ document.querySelector('script[src*="loader"]');
41
+
42
+ if (!scriptTag) return {};
43
+
44
+ return {
45
+ channel: scriptTag.getAttribute('data-channel') || CONFIG.defaultChannel,
46
+ version: scriptTag.getAttribute('data-version') || null,
47
+ debug: scriptTag.getAttribute('data-debug') === 'true',
48
+ apiUrl: scriptTag.getAttribute('data-api-url') || null
49
+ };
50
+ }
51
+
52
+ function emit(eventName, detail) {
53
+ window.dispatchEvent(new CustomEvent(eventName, { detail }));
54
+ }
55
+
56
+ function loadScript(url, timeout) {
57
+ return new Promise((resolve, reject) => {
58
+ const script = document.createElement('script');
59
+ script.src = url;
60
+ script.async = true;
61
+ script.crossOrigin = 'anonymous';
62
+
63
+ let timeoutId;
64
+
65
+ script.onload = function() {
66
+ clearTimeout(timeoutId);
67
+ resolve();
68
+ };
69
+
70
+ script.onerror = function() {
71
+ clearTimeout(timeoutId);
72
+ reject(new Error(`Failed to load script: ${url}`));
73
+ };
74
+
75
+ timeoutId = setTimeout(() => {
76
+ reject(new Error(`Timeout loading script: ${url}`));
77
+ }, timeout || CONFIG.timeout);
78
+
79
+ document.head.appendChild(script);
80
+ });
81
+ }
82
+
83
+ function loadStyles(url) {
84
+ return new Promise((resolve, reject) => {
85
+ const existingLink = document.querySelector(`link[href*="${url}"]`);
86
+ if (existingLink) {
87
+ resolve();
88
+ return;
89
+ }
90
+
91
+ const link = document.createElement('link');
92
+ link.rel = 'stylesheet';
93
+ link.href = url;
94
+ link.crossOrigin = 'anonymous';
95
+
96
+ link.onload = resolve;
97
+ link.onerror = () => reject(new Error(`Failed to load CSS: ${url}`));
98
+
99
+ document.head.appendChild(link);
100
+ });
101
+ }
102
+
103
+ async function fetchVersionInfo(loaderConfig) {
104
+ try {
105
+ if (loaderConfig.version) {
106
+ return buildFallbackUrls(loaderConfig.version);
107
+ }
108
+
109
+ const response = await fetch(CONFIG.versionUrl, {
110
+ cache: 'no-cache',
111
+ headers: {
112
+ 'Cache-Control': 'no-cache, no-store, must-revalidate',
113
+ 'Pragma': 'no-cache',
114
+ 'Expires': '0'
115
+ }
116
+ });
117
+
118
+ if (!response.ok) {
119
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
120
+ }
121
+
122
+ const data = await response.json();
123
+ const channelData = data[loaderConfig.channel] || data.stable;
124
+
125
+ return {
126
+ version: data.version,
127
+ js: channelData.js,
128
+ css: channelData.css,
129
+ timestamp: data.timestamp
130
+ };
131
+
132
+ } catch (error) {
133
+ log.warn('Failed to fetch version info, using fallback', error.message);
134
+ return buildFallbackUrls(CONFIG.fallbackVersion);
135
+ }
136
+ }
137
+
138
+ function buildFallbackUrls(version) {
139
+ const baseUrl = CONFIG.fallbackCdn;
140
+ return {
141
+ version: version,
142
+ js: `${baseUrl}@${version}/dist/tia-gpc-widget.standalone.js`,
143
+ css: `${baseUrl}@${version}/dist/tia-gpc-widget.standalone.css`,
144
+ timestamp: null
145
+ };
146
+ }
147
+
148
+ async function loadWidgetWithRetry(versionInfo, loaderConfig) {
149
+ loadAttempts++;
150
+
151
+ try {
152
+ log.info(`Loading widget v${versionInfo.version} (attempt ${loadAttempts}/${CONFIG.maxRetries})...`);
153
+
154
+ loadStyles(versionInfo.css).catch(err => {
155
+ log.warn('CSS loading failed, continuing anyway', err);
156
+ });
157
+
158
+ await loadScript(versionInfo.js, CONFIG.timeout);
159
+
160
+ if (!window.TiaGPC) {
161
+ throw new Error('Widget loaded but TiaGPC global not found');
162
+ }
163
+
164
+ const loadTime = Date.now() - loadStartTime;
165
+
166
+ log.info(`Widget v${versionInfo.version} loaded successfully in ${loadTime}ms`);
167
+
168
+ window.TiaGPCWidgetLoaded = true;
169
+ window.TiaGPCWidgetVersion = versionInfo.version;
170
+
171
+ emit('tia-gpc-loader-ready', {
172
+ version: versionInfo.version,
173
+ loadTime: loadTime,
174
+ attempts: loadAttempts,
175
+ channel: loaderConfig.channel
176
+ });
177
+
178
+ if (loaderConfig.apiUrl) {
179
+ sendAnalytics(loaderConfig.apiUrl, {
180
+ event: 'widget_loaded',
181
+ version: versionInfo.version,
182
+ loadTime: loadTime,
183
+ url: window.location.href
184
+ });
185
+ }
186
+
187
+ return true;
188
+
189
+ } catch (error) {
190
+ log.error(`Failed to load widget (attempt ${loadAttempts})`, error.message);
191
+
192
+ if (loadAttempts < CONFIG.maxRetries) {
193
+ log.info(`Retrying in ${CONFIG.retryDelay}ms...`);
194
+ await new Promise(resolve => setTimeout(resolve, CONFIG.retryDelay));
195
+ return loadWidgetWithRetry(versionInfo, loaderConfig);
196
+ } else {
197
+ emit('tia-gpc-loader-error', {
198
+ error: error.message,
199
+ attempts: loadAttempts,
200
+ version: versionInfo.version
201
+ });
202
+
203
+ throw new Error(`Failed to load widget after ${loadAttempts} attempts: ${error.message}`);
204
+ }
205
+ }
206
+ }
207
+
208
+ function sendAnalytics(apiUrl, data) {
209
+ try {
210
+ fetch(apiUrl, {
211
+ method: 'POST',
212
+ headers: { 'Content-Type': 'application/json' },
213
+ body: JSON.stringify(data)
214
+ }).catch(() => {});
215
+ } catch (e) {
216
+ }
217
+ }
218
+
219
+ async function init() {
220
+ try {
221
+ if (isAlreadyLoaded()) {
222
+ log.warn('Widget already loaded, skipping');
223
+ return;
224
+ }
225
+
226
+ log.info('Initializing TIA GPC Widget Loader...');
227
+
228
+ const loaderConfig = getLoaderConfig();
229
+
230
+ if (loaderConfig.debug) {
231
+ log.info('Loader config:', loaderConfig);
232
+ }
233
+
234
+ const versionInfo = await fetchVersionInfo(loaderConfig);
235
+
236
+ if (loaderConfig.debug) {
237
+ log.info('Version info:', versionInfo);
238
+ }
239
+
240
+ await loadWidgetWithRetry(versionInfo, loaderConfig);
241
+
242
+ } catch (error) {
243
+ log.error('Fatal error initializing widget', error);
244
+
245
+ const widgets = document.querySelectorAll('tia-gpc-widget');
246
+ if (widgets.length > 0) {
247
+ widgets.forEach(widget => {
248
+ widget.innerHTML = `
249
+ <div style="padding: 20px; background: #fee; border: 2px solid #c00; border-radius: 8px; font-family: sans-serif;">
250
+ <strong>Error loading TIA GPC Widget</strong>
251
+ <p style="margin: 10px 0 0 0; font-size: 14px;">${error.message}</p>
252
+ </div>
253
+ `;
254
+ });
255
+ }
256
+ }
257
+ }
258
+
259
+ if (document.readyState === 'loading') {
260
+ document.addEventListener('DOMContentLoaded', init);
261
+ } else {
262
+ init();
263
+ }
264
+
265
+ window.TiaGPCLoader = {
266
+ version: '1.0.0',
267
+ reload: init,
268
+ config: CONFIG
269
+ };
270
+
271
+ })();
@@ -0,0 +1,3 @@
1
+ /*! TIA GPC Widget Loader v1.0.0 | (c) 2025 TIA | UNLICENSED */
2
+ !function(){"use strict";const e={versionUrl:"https://cdn.jsdelivr.net/npm/tia-gpc-widget@latest/dist/version.json",defaultChannel:"stable",timeout:15e3,maxRetries:3,retryDelay:2e3,fallbackVersion:"1.0.9",fallbackCdn:"https://cdn.jsdelivr.net/npm/tia-gpc-widget"};let t=0,n=Date.now();const o=function(e,t){console.log("[TIA GPC Loader]",e,t||"")},i=function(e,t){console.warn("[TIA GPC Loader]",e,t||"")},r=function(e,t){console.error("[TIA GPC Loader]",e,t||"")};function a(e,t){window.dispatchEvent(new CustomEvent(e,{detail:t}))}function s(t){const n=e.fallbackCdn;return{version:t,js:`${n}@${t}/dist/tia-gpc-widget.standalone.js`,css:`${n}@${t}/dist/tia-gpc-widget.standalone.css`,timestamp:null}}async function d(s,c){t++;try{if(o(`Loading widget v${s.version} (attempt ${t}/${e.maxRetries})...`),(l=s.css,new Promise((e,t)=>{if(document.querySelector(`link[href*="${l}"]`))return void e();const n=document.createElement("link");n.rel="stylesheet",n.href=l,n.crossOrigin="anonymous",n.onload=e,n.onerror=()=>t(new Error(`Failed to load CSS: ${l}`)),document.head.appendChild(n)})).catch(e=>{i("CSS loading failed, continuing anyway",e)}),await function(t,n){return new Promise((o,i)=>{const r=document.createElement("script");let a;r.src=t,r.async=!0,r.crossOrigin="anonymous",r.onload=function(){clearTimeout(a),o()},r.onerror=function(){clearTimeout(a),i(new Error(`Failed to load script: ${t}`))},a=setTimeout(()=>{i(new Error(`Timeout loading script: ${t}`))},n||e.timeout),document.head.appendChild(r)})}(s.js,e.timeout),!window.TiaGPC)throw new Error("Widget loaded but TiaGPC global not found");const r=Date.now()-n;return o(`Widget v${s.version} loaded successfully in ${r}ms`),window.TiaGPCWidgetLoaded=!0,window.TiaGPCWidgetVersion=s.version,a("tia-gpc-loader-ready",{version:s.version,loadTime:r,attempts:t,channel:c.channel}),c.apiUrl&&function(e,t){try{fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}).catch(()=>{})}catch(e){}}(c.apiUrl,{event:"widget_loaded",version:s.version,loadTime:r,url:window.location.href}),!0}catch(n){if(r(`Failed to load widget (attempt ${t})`,n.message),t<e.maxRetries)return o(`Retrying in ${e.retryDelay}ms...`),await new Promise(t=>setTimeout(t,e.retryDelay)),d(s,c);throw a("tia-gpc-loader-error",{error:n.message,attempts:t,version:s.version}),new Error(`Failed to load widget after ${t} attempts: ${n.message}`)}var l}async function c(){try{if(!0===window.TiaGPCWidgetLoaded||void 0!==window.TiaGPC)return void i("Widget already loaded, skipping");o("Initializing TIA GPC Widget Loader...");const t=function(){const t=document.currentScript||document.querySelector('script[src*="loader"]');return t?{channel:t.getAttribute("data-channel")||e.defaultChannel,version:t.getAttribute("data-version")||null,debug:"true"===t.getAttribute("data-debug"),apiUrl:t.getAttribute("data-api-url")||null}:{}}();t.debug&&o("Loader config:",t);const n=await async function(t){try{if(t.version)return s(t.version);const n=await fetch(e.versionUrl,{cache:"no-cache",headers:{"Cache-Control":"no-cache, no-store, must-revalidate",Pragma:"no-cache",Expires:"0"}});if(!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText}`);const o=await n.json(),i=o[t.channel]||o.stable;return{version:o.version,js:i.js,css:i.css,timestamp:o.timestamp}}catch(t){return i("Failed to fetch version info, using fallback",t.message),s(e.fallbackVersion)}}(t);t.debug&&o("Version info:",n),await d(n,t)}catch(e){r("Fatal error initializing widget",e);const t=document.querySelectorAll("tia-gpc-widget");t.length>0&&t.forEach(t=>{t.innerHTML=`\n <div style="padding: 20px; background: #fee; border: 2px solid #c00; border-radius: 8px; font-family: sans-serif;">\n <strong>Error loading TIA GPC Widget</strong>\n <p style="margin: 10px 0 0 0; font-size: 14px;">${e.message}</p>\n </div>\n `})}}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",c):c(),window.TiaGPCLoader={version:"1.0.0",reload:c,config:e}}();
3
+ //# sourceMappingURL=loader.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.min.js","names":["CONFIG","versionUrl","defaultChannel","timeout","maxRetries","retryDelay","fallbackVersion","fallbackCdn","loadAttempts","loadStartTime","Date","now","log","msg","data","console","warn","error","emit","eventName","detail","window","dispatchEvent","CustomEvent","buildFallbackUrls","version","baseUrl","js","css","timestamp","async","loadWidgetWithRetry","versionInfo","loaderConfig","url","Promise","resolve","reject","document","querySelector","link","createElement","rel","href","crossOrigin","onload","onerror","Error","head","appendChild","catch","err","script","timeoutId","src","clearTimeout","setTimeout","loadScript","TiaGPC","loadTime","TiaGPCWidgetLoaded","TiaGPCWidgetVersion","attempts","channel","apiUrl","fetch","method","headers","body","JSON","stringify","e","sendAnalytics","event","location","message","init","undefined","scriptTag","currentScript","getAttribute","debug","getLoaderConfig","response","cache","Pragma","Expires","ok","status","statusText","json","channelData","stable","fetchVersionInfo","widgets","querySelectorAll","length","forEach","widget","innerHTML","readyState","addEventListener","TiaGPCLoader","reload","config"],"sources":["0"],"mappings":"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","ignoreList":[]}