@chaochao12138/check-update-sdk 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Dezhen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # @dezhen/check-update-sdk
2
+
3
+ > Frontend automatic update detection SDK for web applications
4
+
5
+ A lightweight, zero-dependency SDK that automatically detects when a new version of your web application has been deployed and notifies users or refreshes the page.
6
+
7
+ ## Features
8
+
9
+ - **ETag/Last-Monified Detection** - Monitors HTTP headers to detect deployment changes
10
+ - **Route Change Detection** - Triggers checks when users navigate (optional)
11
+ - **Resource Load Error Detection** - Detects broken scripts/styles (optional)
12
+ - **Tab Visibility Detection** - Automatically resumes checking when user returns to tab
13
+ - **Zero Runtime Dependencies** - Lightweight and tree-shakeable
14
+ - **TypeScript Support** - Full TypeScript definitions included
15
+ - **Framework Agnostic** - Works with any frontend framework
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @dezhen/check-update-sdk
21
+ # or
22
+ pnpm add @dezhen/check-update-sdk
23
+ # or
24
+ yarn add @dezhen/check-update-sdk
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ```typescript
30
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
31
+
32
+ const updater = createCheckUpdate({
33
+ interval: 5 * 60 * 1000, // Check every 5 minutes
34
+ onUpdate: () => {
35
+ // Show update notification to user
36
+ if (confirm('A new version is available. Refresh now?')) {
37
+ window.location.reload();
38
+ }
39
+ }
40
+ });
41
+
42
+ // Later, if needed
43
+ updater.destroy();
44
+ ```
45
+
46
+ ## Options
47
+
48
+ ```typescript
49
+ interface CheckUpdateOptions {
50
+ /** Polling interval in milliseconds (default: 10 minutes) */
51
+ interval?: number;
52
+
53
+ /** Callback when update is detected */
54
+ onUpdate?: () => void;
55
+
56
+ /** Auto-refresh when update is detected (default: false) */
57
+ autoRefresh?: boolean;
58
+
59
+ /** Enable route change detection (default: true) */
60
+ enableRouteDetection?: boolean;
61
+
62
+ /** Enable resource load error detection (default: false) */
63
+ enableLoadErrorDetection?: boolean;
64
+
65
+ /** Custom URL to check for updates (default: current page URL) */
66
+ checkUrl?: string;
67
+ }
68
+ ```
69
+
70
+ ## Usage Examples
71
+
72
+ ### Auto-Refresh Mode
73
+
74
+ ```typescript
75
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
76
+
77
+ createCheckUpdate({
78
+ interval: 5 * 60 * 1000,
79
+ autoRefresh: true // Automatically refresh when update detected
80
+ });
81
+ ```
82
+
83
+ ### Custom Update Notification
84
+
85
+ ```typescript
86
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
87
+
88
+ const updater = createCheckUpdate({
89
+ interval: 10 * 60 * 1000,
90
+ onUpdate: () => {
91
+ // Show a custom notification
92
+ const notification = document.createElement('div');
93
+ notification.textContent = 'New version available!';
94
+ notification.style.cssText = `
95
+ position: fixed;
96
+ top: 20px;
97
+ right: 20px;
98
+ padding: 16px;
99
+ background: #4CAF50;
100
+ color: white;
101
+ border-radius: 8px;
102
+ cursor: pointer;
103
+ z-index: 9999;
104
+ `;
105
+ notification.onclick = () => window.location.reload();
106
+ document.body.appendChild(notification);
107
+ }
108
+ });
109
+ ```
110
+
111
+ ### Vue 3 Application
112
+
113
+ ```typescript
114
+ // main.ts
115
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
116
+
117
+ const app = createApp(App);
118
+
119
+ // Initialize update checker
120
+ const updater = createCheckUpdate({
121
+ interval: 5 * 60 * 1000,
122
+ onUpdate: () => {
123
+ // You can use your UI framework's notification system
124
+ console.log('New version available!');
125
+ }
126
+ });
127
+
128
+ // Cleanup on app unmount
129
+ app.config.globalProperties.$updater = updater;
130
+ ```
131
+
132
+ ### Disable Route Detection
133
+
134
+ ```typescript
135
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
136
+
137
+ createCheckUpdate({
138
+ enableRouteDetection: false, // Don't check on route changes
139
+ interval: 10 * 60 * 1000
140
+ });
141
+ ```
142
+
143
+ ### Enable Resource Error Detection
144
+
145
+ ```typescript
146
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
147
+
148
+ createCheckUpdate({
149
+ enableLoadErrorDetection: true, // Check on script/link load errors
150
+ onUpdate: () => {
151
+ console.log('Update detected due to resource error');
152
+ }
153
+ });
154
+ ```
155
+
156
+ ### Manual Check
157
+
158
+ ```typescript
159
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
160
+
161
+ const updater = createCheckUpdate();
162
+
163
+ // Manually trigger a check
164
+ updater.check();
165
+ ```
166
+
167
+ ### Cleanup
168
+
169
+ ```typescript
170
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
171
+
172
+ const updater = createCheckUpdate();
173
+
174
+ // Later, when you want to stop checking
175
+ updater.destroy();
176
+ ```
177
+
178
+ ## How It Works
179
+
180
+ The SDK detects updates by:
181
+
182
+ 1. **Initial Check**: Makes a HEAD request to get the current ETag or Last-Modified header
183
+ 2. **Periodic Polling**: At configured intervals, checks if the header has changed
184
+ 3. **Route Changes**: (Optional) Triggers a check when the user navigates to a new route
185
+ 4. **Resource Errors**: (Optional) Triggers a check when scripts or stylesheets fail to load
186
+ 5. **Tab Visibility**: Pauses polling when tab is hidden, resumes when visible
187
+
188
+ When an update is detected:
189
+ - If `autoRefresh` is `true`, the page reloads automatically
190
+ - Otherwise, the `onUpdate` callback is invoked
191
+
192
+ ## Server Configuration
193
+
194
+ The SDK works by checking the `ETag` or `Last-Modified` HTTP headers. Most web servers (Nginx, Apache, Vercel, Netlify, etc.) generate these headers automatically by default.
195
+
196
+ ### Example Server Responses
197
+
198
+ **Before Update:**
199
+ ```
200
+ HTTP/1.1 200 OK
201
+ ETag: "abc123"
202
+ ```
203
+
204
+ **After Update:**
205
+ ```
206
+ HTTP/1.1 200 OK
207
+ ETag: "def456"
208
+ ```
209
+
210
+ The SDK detects the ETag change and triggers the update notification.
211
+
212
+ ## Browser Support
213
+
214
+ - Chrome/Edge (last 2 versions)
215
+ - Firefox (last 2 versions)
216
+ - Safari (last 2 versions)
217
+ - Modern mobile browsers
218
+
219
+ ## License
220
+
221
+ MIT
222
+
223
+ ## Contributing
224
+
225
+ Contributions are welcome! Please feel free to submit a Pull Request.
226
+
227
+ ## Support
228
+
229
+ For issues and questions, please visit the [GitHub Issues](https://github.com/dezhen/check-update-sdk/issues) page.
@@ -0,0 +1,19 @@
1
+ interface CoreOptions {
2
+ interval?: number;
3
+ checkUrl?: string;
4
+ autoRefresh?: boolean;
5
+ onUpdate?: () => void;
6
+ }
7
+
8
+ interface CheckUpdateOptions extends CoreOptions {
9
+ /** 是否开启路由切换检测 (默认 true) */
10
+ enableRouteDetection?: boolean;
11
+ /** 是否开启资源加载错误检测 (默认 false) */
12
+ enableLoadErrorDetection?: boolean;
13
+ }
14
+ declare function createCheckUpdate(options?: CheckUpdateOptions): {
15
+ check: () => Promise<void>;
16
+ destroy: () => void;
17
+ };
18
+
19
+ export { type CheckUpdateOptions, createCheckUpdate };
@@ -0,0 +1,19 @@
1
+ interface CoreOptions {
2
+ interval?: number;
3
+ checkUrl?: string;
4
+ autoRefresh?: boolean;
5
+ onUpdate?: () => void;
6
+ }
7
+
8
+ interface CheckUpdateOptions extends CoreOptions {
9
+ /** 是否开启路由切换检测 (默认 true) */
10
+ enableRouteDetection?: boolean;
11
+ /** 是否开启资源加载错误检测 (默认 false) */
12
+ enableLoadErrorDetection?: boolean;
13
+ }
14
+ declare function createCheckUpdate(options?: CheckUpdateOptions): {
15
+ check: () => Promise<void>;
16
+ destroy: () => void;
17
+ };
18
+
19
+ export { type CheckUpdateOptions, createCheckUpdate };
package/dist/index.js ADDED
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ createCheckUpdate: () => createCheckUpdate
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/core.ts
28
+ function createUpdateCore(options) {
29
+ let oldEtag = null;
30
+ let timer;
31
+ let isChecking = false;
32
+ let isDestroyed = false;
33
+ const getCheckUrl = () => {
34
+ try {
35
+ const urlStr = options.checkUrl || window.location.href;
36
+ const targetUrl = new URL(urlStr, window.location.href);
37
+ targetUrl.searchParams.set("t", String(Date.now()));
38
+ return targetUrl.toString();
39
+ } catch {
40
+ return `${options.checkUrl || window.location.href}?t=${Date.now()}`;
41
+ }
42
+ };
43
+ const check = async () => {
44
+ if (isDestroyed || isChecking) return;
45
+ isChecking = true;
46
+ try {
47
+ const response = await fetch(getCheckUrl(), { method: "HEAD", cache: "no-cache" });
48
+ const newEtag = response.headers.get("etag") || response.headers.get("last-modified");
49
+ if (!newEtag) return;
50
+ if (!oldEtag) {
51
+ oldEtag = newEtag;
52
+ } else if (newEtag !== oldEtag) {
53
+ oldEtag = newEtag;
54
+ if (options.autoRefresh) {
55
+ window.location.reload();
56
+ } else {
57
+ options.onUpdate?.();
58
+ }
59
+ }
60
+ } catch (e) {
61
+ } finally {
62
+ if (!isDestroyed) {
63
+ isChecking = false;
64
+ }
65
+ }
66
+ };
67
+ const start = () => {
68
+ check();
69
+ if (options.interval && options.interval > 0) {
70
+ timer = setInterval(check, options.interval);
71
+ }
72
+ };
73
+ const destroy = () => {
74
+ isDestroyed = true;
75
+ if (timer) {
76
+ clearInterval(timer);
77
+ timer = void 0;
78
+ }
79
+ };
80
+ return {
81
+ check,
82
+ start,
83
+ destroy
84
+ };
85
+ }
86
+
87
+ // src/plugins.ts
88
+ var createRoutePlugin = (core) => {
89
+ const patch = (method) => {
90
+ const original = window.history[method];
91
+ if (original._isPatched) return;
92
+ window.history[method] = function(...args) {
93
+ const result = original.apply(this, args);
94
+ core.check();
95
+ return result;
96
+ };
97
+ window.history[method]._isPatched = true;
98
+ };
99
+ patch("pushState");
100
+ patch("replaceState");
101
+ const onPopState = () => core.check();
102
+ window.addEventListener("popstate", onPopState);
103
+ return () => {
104
+ window.removeEventListener("popstate", onPopState);
105
+ };
106
+ };
107
+ var createResourceErrorPlugin = (core) => {
108
+ const onError = (event) => {
109
+ const target = event.target;
110
+ if (!target || target.tagName !== "SCRIPT" && target.tagName !== "LINK") return;
111
+ const src = target.src || target.href;
112
+ if (src) {
113
+ core.check();
114
+ }
115
+ };
116
+ window.addEventListener("error", onError, true);
117
+ return () => {
118
+ window.removeEventListener("error", onError, true);
119
+ };
120
+ };
121
+
122
+ // src/index.ts
123
+ function createCheckUpdate(options = {}) {
124
+ const {
125
+ interval = 10 * 60 * 1e3,
126
+ enableRouteDetection = true,
127
+ enableLoadErrorDetection = false,
128
+ ...coreOptions
129
+ } = options;
130
+ const core = createUpdateCore({ interval, ...coreOptions });
131
+ const cleanupFns = [];
132
+ const use = (plugin) => {
133
+ cleanupFns.push(plugin(core));
134
+ };
135
+ if (enableRouteDetection) {
136
+ use(createRoutePlugin);
137
+ }
138
+ if (enableLoadErrorDetection) {
139
+ use(createResourceErrorPlugin);
140
+ }
141
+ core.start();
142
+ return {
143
+ check: core.check,
144
+ destroy: () => {
145
+ core.destroy();
146
+ cleanupFns.forEach((fn) => fn());
147
+ }
148
+ };
149
+ }
150
+ // Annotate the CommonJS export names for ESM import in node:
151
+ 0 && (module.exports = {
152
+ createCheckUpdate
153
+ });
154
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIiwgIi4uL3NyYy9jb3JlLnRzIiwgIi4uL3NyYy9wbHVnaW5zLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyBjcmVhdGVVcGRhdGVDb3JlLCB0eXBlIENvcmVPcHRpb25zIH0gZnJvbSAnLi9jb3JlJztcclxuaW1wb3J0IHsgY3JlYXRlUm91dGVQbHVnaW4sIGNyZWF0ZVJlc291cmNlRXJyb3JQbHVnaW4sIHR5cGUgVXBkYXRlUGx1Z2luIH0gZnJvbSAnLi9wbHVnaW5zJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQ2hlY2tVcGRhdGVPcHRpb25zIGV4dGVuZHMgQ29yZU9wdGlvbnMge1xyXG4gICAgLyoqIFx1NjYyRlx1NTQyNlx1NUYwMFx1NTQyRlx1OERFRlx1NzUzMVx1NTIwN1x1NjM2Mlx1NjhDMFx1NkQ0QiAoXHU5RUQ4XHU4QkE0IHRydWUpICovXHJcbiAgICBlbmFibGVSb3V0ZURldGVjdGlvbj86IGJvb2xlYW47XHJcbiAgICAvKiogXHU2NjJGXHU1NDI2XHU1RjAwXHU1NDJGXHU4RDQ0XHU2RTkwXHU1MkEwXHU4RjdEXHU5NTE5XHU4QkVGXHU2OEMwXHU2RDRCIChcdTlFRDhcdThCQTQgZmFsc2UpICovXHJcbiAgICBlbmFibGVMb2FkRXJyb3JEZXRlY3Rpb24/OiBib29sZWFuO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ2hlY2tVcGRhdGUob3B0aW9uczogQ2hlY2tVcGRhdGVPcHRpb25zID0ge30pIHtcclxuICAgIC8vIDEuIFx1NTIwNlx1NzlCQlx1OTE0RFx1N0Y2RVxyXG4gICAgY29uc3Qge1xyXG4gICAgICAgIGludGVydmFsID0gMTAgKiA2MCAqIDEwMDAsXHJcbiAgICAgICAgZW5hYmxlUm91dGVEZXRlY3Rpb24gPSB0cnVlLFxyXG4gICAgICAgIGVuYWJsZUxvYWRFcnJvckRldGVjdGlvbiA9IGZhbHNlLFxyXG4gICAgICAgIC4uLmNvcmVPcHRpb25zXHJcbiAgICB9ID0gb3B0aW9ucztcclxuXHJcbiAgICAvLyAyLiBcdTUyMUJcdTVFRkFcdTY4MzhcdTVGQzNcdTVCOUVcdTRGOEJcclxuICAgIGNvbnN0IGNvcmUgPSBjcmVhdGVVcGRhdGVDb3JlKHsgaW50ZXJ2YWwsIC4uLmNvcmVPcHRpb25zIH0pO1xyXG5cclxuICAgIC8vIDMuIFx1NjNEMlx1NEVGNlx1N0JBMVx1NzQwNlxyXG4gICAgY29uc3QgY2xlYW51cEZuczogQXJyYXk8KCkgPT4gdm9pZD4gPSBbXTtcclxuXHJcbiAgICBjb25zdCB1c2UgPSAocGx1Z2luOiBVcGRhdGVQbHVnaW4pID0+IHtcclxuICAgICAgICBjbGVhbnVwRm5zLnB1c2gocGx1Z2luKGNvcmUpKTtcclxuICAgIH07XHJcblxyXG4gICAgLy8gNC4gXHU2MzA5XHU5NzAwXHU1MkEwXHU4RjdEXHU2M0QyXHU0RUY2XHJcbiAgICBpZiAoZW5hYmxlUm91dGVEZXRlY3Rpb24pIHtcclxuICAgICAgICB1c2UoY3JlYXRlUm91dGVQbHVnaW4pO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChlbmFibGVMb2FkRXJyb3JEZXRlY3Rpb24pIHtcclxuICAgICAgICB1c2UoY3JlYXRlUmVzb3VyY2VFcnJvclBsdWdpbik7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gNS4gXHU1NDJGXHU1MkE4XHU2ODM4XHU1RkMzXHJcbiAgICBjb3JlLnN0YXJ0KCk7XHJcblxyXG4gICAgLy8gNi4gXHU4RkQ0XHU1NkRFXHU1QkY5XHU1OTE2IEFQSVxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgICBjaGVjazogY29yZS5jaGVjayxcclxuICAgICAgICBkZXN0cm95OiAoKSA9PiB7XHJcbiAgICAgICAgICAgIGNvcmUuZGVzdHJveSgpOyAvLyBcdTk1MDBcdTZCQzFcdTY4MzhcdTVGQzNcclxuICAgICAgICAgICAgY2xlYW51cEZucy5mb3JFYWNoKGZuID0+IGZuKCkpOyAvLyBcdTk1MDBcdTZCQzFcdTYyNDBcdTY3MDlcdTYzRDJcdTRFRjZcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG59IiwgImV4cG9ydCBpbnRlcmZhY2UgQ29yZU9wdGlvbnMge1xyXG4gICAgaW50ZXJ2YWw/OiBudW1iZXI7XHJcbiAgICBjaGVja1VybD86IHN0cmluZztcclxuICAgIGF1dG9SZWZyZXNoPzogYm9vbGVhbjtcclxuICAgIG9uVXBkYXRlPzogKCkgPT4gdm9pZDtcclxufVxyXG5cclxuLy8gXHU1QjlBXHU0RTQ5XHU2ODM4XHU1RkMzXHU1QjlFXHU0RjhCXHU1QkY5XHU1OTE2XHU2NkI0XHU5NzMyXHU3Njg0XHU2M0E1XHU1M0UzXHJcbmV4cG9ydCBpbnRlcmZhY2UgVXBkYXRlQ29yZUluc3RhbmNlIHtcclxuICAgIGNoZWNrOiAoKSA9PiBQcm9taXNlPHZvaWQ+O1xyXG4gICAgc3RhcnQ6ICgpID0+IHZvaWQ7XHJcbiAgICBkZXN0cm95OiAoKSA9PiB2b2lkO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlVXBkYXRlQ29yZShvcHRpb25zOiBDb3JlT3B0aW9ucyk6IFVwZGF0ZUNvcmVJbnN0YW5jZSB7XHJcbiAgICAvLyAtLS0gXHU3OUMxXHU2NzA5XHU3MkI2XHU2MDAxIChcdTk1RURcdTUzMDUpIC0tLVxyXG4gICAgbGV0IG9sZEV0YWc6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG4gICAgbGV0IHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRJbnRlcnZhbD4gfCB1bmRlZmluZWQ7XHJcbiAgICBsZXQgaXNDaGVja2luZyA9IGZhbHNlO1xyXG4gICAgbGV0IGlzRGVzdHJveWVkID0gZmFsc2U7XHJcblxyXG4gICAgLy8gLS0tIFx1NTE4NVx1OTBFOFx1OEY4NVx1NTJBOVx1NTFGRFx1NjU3MCAtLS1cclxuXHJcbiAgICBjb25zdCBnZXRDaGVja1VybCA9ICgpOiBzdHJpbmcgPT4ge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHVybFN0ciA9IG9wdGlvbnMuY2hlY2tVcmwgfHwgd2luZG93LmxvY2F0aW9uLmhyZWY7XHJcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldFVybCA9IG5ldyBVUkwodXJsU3RyLCB3aW5kb3cubG9jYXRpb24uaHJlZik7XHJcbiAgICAgICAgICAgIHRhcmdldFVybC5zZWFyY2hQYXJhbXMuc2V0KCd0JywgU3RyaW5nKERhdGUubm93KCkpKTtcclxuICAgICAgICAgICAgcmV0dXJuIHRhcmdldFVybC50b1N0cmluZygpO1xyXG4gICAgICAgIH0gY2F0Y2gge1xyXG4gICAgICAgICAgICByZXR1cm4gYCR7b3B0aW9ucy5jaGVja1VybCB8fCB3aW5kb3cubG9jYXRpb24uaHJlZn0/dD0ke0RhdGUubm93KCl9YDtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIC0tLSBcdTY4MzhcdTVGQzNcdTY1QjlcdTZDRDUgLS0tXHJcblxyXG4gICAgY29uc3QgY2hlY2sgPSBhc3luYyAoKSA9PiB7XHJcbiAgICAgICAgaWYgKGlzRGVzdHJveWVkIHx8IGlzQ2hlY2tpbmcpIHJldHVybjtcclxuICAgICAgICBpc0NoZWNraW5nID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChnZXRDaGVja1VybCgpLCB7IG1ldGhvZDogJ0hFQUQnLCBjYWNoZTogJ25vLWNhY2hlJyB9KTtcclxuICAgICAgICAgICAgY29uc3QgbmV3RXRhZyA9IHJlc3BvbnNlLmhlYWRlcnMuZ2V0KCdldGFnJykgfHwgcmVzcG9uc2UuaGVhZGVycy5nZXQoJ2xhc3QtbW9kaWZpZWQnKTtcclxuXHJcbiAgICAgICAgICAgIGlmICghbmV3RXRhZykgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgaWYgKCFvbGRFdGFnKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBcdTUyMURcdTU5Q0JcdTUzMTZcdTU3RkFcdTUxQzZcclxuICAgICAgICAgICAgICAgIG9sZEV0YWcgPSBuZXdFdGFnO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKG5ld0V0YWcgIT09IG9sZEV0YWcpIHtcclxuICAgICAgICAgICAgICAgIG9sZEV0YWcgPSBuZXdFdGFnO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmF1dG9SZWZyZXNoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBvcHRpb25zLm9uVXBkYXRlPy4oKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgLy8gXHU3RjUxXHU3RURDXHU5NTE5XHU4QkVGXHU1RkZEXHU3NTY1XHJcbiAgICAgICAgfSBmaW5hbGx5IHtcclxuICAgICAgICAgICAgaWYgKCFpc0Rlc3Ryb3llZCkge1xyXG4gICAgICAgICAgICAgICAgaXNDaGVja2luZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxuXHJcbiAgICBjb25zdCBzdGFydCA9ICgpID0+IHtcclxuICAgICAgICBjaGVjaygpOyAvLyBcdTdBQ0JcdTUzNzNcdTY4QzBcdTY3RTVcdTRFMDBcdTZCMjFcclxuICAgICAgICBpZiAob3B0aW9ucy5pbnRlcnZhbCAmJiBvcHRpb25zLmludGVydmFsID4gMCkge1xyXG4gICAgICAgICAgICB0aW1lciA9IHNldEludGVydmFsKGNoZWNrLCBvcHRpb25zLmludGVydmFsKTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IGRlc3Ryb3kgPSAoKSA9PiB7XHJcbiAgICAgICAgaXNEZXN0cm95ZWQgPSB0cnVlO1xyXG4gICAgICAgIGlmICh0aW1lcikge1xyXG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRpbWVyKTtcclxuICAgICAgICAgICAgdGltZXIgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBcdThGRDRcdTU2REVcdTY4MzhcdTVGQzNcdTVCOUVcdTRGOEJcclxuICAgIHJldHVybiB7XHJcbiAgICAgICAgY2hlY2ssXHJcbiAgICAgICAgc3RhcnQsXHJcbiAgICAgICAgZGVzdHJveVxyXG4gICAgfTtcclxufSIsICJpbXBvcnQgdHlwZSB7IFVwZGF0ZUNvcmVJbnN0YW5jZSB9IGZyb20gJy4vY29yZSc7XHJcblxyXG4vLyBcdTYzRDJcdTRFRjZcdTdDN0JcdTU3OEJcdTVCOUFcdTRFNDlcdUZGMUFcdTYzQTVcdTY1MzZcdTY4MzhcdTVGQzNcdTVCOUVcdTRGOEJcdUZGMENcdThGRDRcdTU2REVcdTZFMDVcdTc0MDZcdTUxRkRcdTY1NzBcclxuZXhwb3J0IHR5cGUgVXBkYXRlUGx1Z2luID0gKGNvcmU6IFVwZGF0ZUNvcmVJbnN0YW5jZSkgPT4gKCkgPT4gdm9pZDtcclxuXHJcbi8qKiAqIFx1RDgzRFx1REQwQyBcdTYzRDJcdTRFRjZcdUZGMUFcdThERUZcdTc1MzFcdTUyMDdcdTYzNjJcdTY4QzBcdTZENEJcclxuICovXHJcbmV4cG9ydCBjb25zdCBjcmVhdGVSb3V0ZVBsdWdpbjogVXBkYXRlUGx1Z2luID0gKGNvcmUpID0+IHtcclxuICAgIGNvbnN0IHBhdGNoID0gKG1ldGhvZDogJ3B1c2hTdGF0ZScgfCAncmVwbGFjZVN0YXRlJykgPT4ge1xyXG4gICAgICAgIGNvbnN0IG9yaWdpbmFsID0gd2luZG93Lmhpc3RvcnlbbWV0aG9kXTtcclxuXHJcbiAgICAgICAgLy8gXHU5NjMyXHU2QjYyXHU5MUNEXHU1OTBEIFBhdGNoXHJcbiAgICAgICAgaWYgKChvcmlnaW5hbCBhcyBhbnkpLl9pc1BhdGNoZWQpIHJldHVybjtcclxuXHJcbiAgICAgICAgd2luZG93Lmhpc3RvcnlbbWV0aG9kXSA9IGZ1bmN0aW9uICguLi5hcmdzKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IG9yaWdpbmFsLmFwcGx5KHRoaXMsIGFyZ3MpO1xyXG4gICAgICAgICAgICBjb3JlLmNoZWNrKCk7IC8vIFx1OEMwM1x1NzUyOFx1NjgzOFx1NUZDM1x1NjhDMFx1NkQ0QlxyXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgKHdpbmRvdy5oaXN0b3J5W21ldGhvZF0gYXMgYW55KS5faXNQYXRjaGVkID0gdHJ1ZTtcclxuICAgIH07XHJcblxyXG4gICAgLy8gMS4gXHU1MkFCXHU2MzAxIEhpc3RvcnkgQVBJXHJcbiAgICBwYXRjaCgncHVzaFN0YXRlJyk7XHJcbiAgICBwYXRjaCgncmVwbGFjZVN0YXRlJyk7XHJcblxyXG4gICAgLy8gMi4gXHU3NkQxXHU1NDJDIHBvcHN0YXRlXHJcbiAgICBjb25zdCBvblBvcFN0YXRlID0gKCkgPT4gY29yZS5jaGVjaygpO1xyXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgb25Qb3BTdGF0ZSk7XHJcblxyXG4gICAgLy8gXHU4RkQ0XHU1NkRFXHU2RTA1XHU3NDA2XHU1MUZEXHU2NTcwXHJcbiAgICByZXR1cm4gKCkgPT4ge1xyXG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdwb3BzdGF0ZScsIG9uUG9wU3RhdGUpO1xyXG4gICAgfTtcclxufTtcclxuXHJcbi8qKiAqIFx1RDgzRFx1REQwQyBcdTYzRDJcdTRFRjZcdUZGMUFcdThENDRcdTZFOTBcdTUyQTBcdThGN0RcdTk1MTlcdThCRUZcdTY4QzBcdTZENEJcclxuICovXHJcbmV4cG9ydCBjb25zdCBjcmVhdGVSZXNvdXJjZUVycm9yUGx1Z2luOiBVcGRhdGVQbHVnaW4gPSAoY29yZSkgPT4ge1xyXG4gICAgY29uc3Qgb25FcnJvciA9IChldmVudDogRXZlbnQpID0+IHtcclxuICAgICAgICBjb25zdCB0YXJnZXQgPSBldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICAgICAgaWYgKCF0YXJnZXQgfHwgKHRhcmdldC50YWdOYW1lICE9PSAnU0NSSVBUJyAmJiB0YXJnZXQudGFnTmFtZSAhPT0gJ0xJTksnKSkgcmV0dXJuO1xyXG5cclxuICAgICAgICBjb25zdCBzcmMgPSAodGFyZ2V0IGFzIEhUTUxTY3JpcHRFbGVtZW50KS5zcmMgfHwgKHRhcmdldCBhcyBIVE1MTGlua0VsZW1lbnQpLmhyZWY7XHJcbiAgICAgICAgaWYgKHNyYykge1xyXG4gICAgICAgICAgICBjb3JlLmNoZWNrKCk7IC8vIFx1OEQ0NFx1NkU5MFx1NjMwMlx1NEU4Nlx1RkYwQ1x1N0FDQlx1NTM3M1x1NjhDMFx1NjdFNVxyXG4gICAgICAgIH1cclxuICAgIH07XHJcblxyXG4gICAgLy8gXHU2MzU1XHU4M0I3XHU5NjM2XHU2QkI1XHU3NkQxXHU1NDJDXHJcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignZXJyb3InLCBvbkVycm9yLCB0cnVlKTtcclxuXHJcbiAgICByZXR1cm4gKCkgPT4ge1xyXG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdlcnJvcicsIG9uRXJyb3IsIHRydWUpO1xyXG4gICAgfTtcclxufTsiXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQ2NPLFNBQVMsaUJBQWlCLFNBQTBDO0FBRXZFLE1BQUksVUFBeUI7QUFDN0IsTUFBSTtBQUNKLE1BQUksYUFBYTtBQUNqQixNQUFJLGNBQWM7QUFJbEIsUUFBTSxjQUFjLE1BQWM7QUFDOUIsUUFBSTtBQUNBLFlBQU0sU0FBUyxRQUFRLFlBQVksT0FBTyxTQUFTO0FBQ25ELFlBQU0sWUFBWSxJQUFJLElBQUksUUFBUSxPQUFPLFNBQVMsSUFBSTtBQUN0RCxnQkFBVSxhQUFhLElBQUksS0FBSyxPQUFPLEtBQUssSUFBSSxDQUFDLENBQUM7QUFDbEQsYUFBTyxVQUFVLFNBQVM7QUFBQSxJQUM5QixRQUFRO0FBQ0osYUFBTyxHQUFHLFFBQVEsWUFBWSxPQUFPLFNBQVMsSUFBSSxNQUFNLEtBQUssSUFBSSxDQUFDO0FBQUEsSUFDdEU7QUFBQSxFQUNKO0FBSUEsUUFBTSxRQUFRLFlBQVk7QUFDdEIsUUFBSSxlQUFlLFdBQVk7QUFDL0IsaUJBQWE7QUFFYixRQUFJO0FBQ0EsWUFBTSxXQUFXLE1BQU0sTUFBTSxZQUFZLEdBQUcsRUFBRSxRQUFRLFFBQVEsT0FBTyxXQUFXLENBQUM7QUFDakYsWUFBTSxVQUFVLFNBQVMsUUFBUSxJQUFJLE1BQU0sS0FBSyxTQUFTLFFBQVEsSUFBSSxlQUFlO0FBRXBGLFVBQUksQ0FBQyxRQUFTO0FBRWQsVUFBSSxDQUFDLFNBQVM7QUFFVixrQkFBVTtBQUFBLE1BQ2QsV0FBVyxZQUFZLFNBQVM7QUFDNUIsa0JBQVU7QUFFVixZQUFJLFFBQVEsYUFBYTtBQUNyQixpQkFBTyxTQUFTLE9BQU87QUFBQSxRQUMzQixPQUFPO0FBQ0gsa0JBQVEsV0FBVztBQUFBLFFBQ3ZCO0FBQUEsTUFDSjtBQUFBLElBQ0osU0FBUyxHQUFHO0FBQUEsSUFFWixVQUFFO0FBQ0UsVUFBSSxDQUFDLGFBQWE7QUFDZCxxQkFBYTtBQUFBLE1BQ2pCO0FBQUEsSUFDSjtBQUFBLEVBQ0o7QUFFQSxRQUFNLFFBQVEsTUFBTTtBQUNoQixVQUFNO0FBQ04sUUFBSSxRQUFRLFlBQVksUUFBUSxXQUFXLEdBQUc7QUFDMUMsY0FBUSxZQUFZLE9BQU8sUUFBUSxRQUFRO0FBQUEsSUFDL0M7QUFBQSxFQUNKO0FBRUEsUUFBTSxVQUFVLE1BQU07QUFDbEIsa0JBQWM7QUFDZCxRQUFJLE9BQU87QUFDUCxvQkFBYyxLQUFLO0FBQ25CLGNBQVE7QUFBQSxJQUNaO0FBQUEsRUFDSjtBQUdBLFNBQU87QUFBQSxJQUNIO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxFQUNKO0FBQ0o7OztBQ2pGTyxJQUFNLG9CQUFrQyxDQUFDLFNBQVM7QUFDckQsUUFBTSxRQUFRLENBQUMsV0FBeUM7QUFDcEQsVUFBTSxXQUFXLE9BQU8sUUFBUSxNQUFNO0FBR3RDLFFBQUssU0FBaUIsV0FBWTtBQUVsQyxXQUFPLFFBQVEsTUFBTSxJQUFJLFlBQWEsTUFBTTtBQUN4QyxZQUFNLFNBQVMsU0FBUyxNQUFNLE1BQU0sSUFBSTtBQUN4QyxXQUFLLE1BQU07QUFDWCxhQUFPO0FBQUEsSUFDWDtBQUNBLElBQUMsT0FBTyxRQUFRLE1BQU0sRUFBVSxhQUFhO0FBQUEsRUFDakQ7QUFHQSxRQUFNLFdBQVc7QUFDakIsUUFBTSxjQUFjO0FBR3BCLFFBQU0sYUFBYSxNQUFNLEtBQUssTUFBTTtBQUNwQyxTQUFPLGlCQUFpQixZQUFZLFVBQVU7QUFHOUMsU0FBTyxNQUFNO0FBQ1QsV0FBTyxvQkFBb0IsWUFBWSxVQUFVO0FBQUEsRUFDckQ7QUFDSjtBQUlPLElBQU0sNEJBQTBDLENBQUMsU0FBUztBQUM3RCxRQUFNLFVBQVUsQ0FBQyxVQUFpQjtBQUM5QixVQUFNLFNBQVMsTUFBTTtBQUNyQixRQUFJLENBQUMsVUFBVyxPQUFPLFlBQVksWUFBWSxPQUFPLFlBQVksT0FBUztBQUUzRSxVQUFNLE1BQU8sT0FBNkIsT0FBUSxPQUEyQjtBQUM3RSxRQUFJLEtBQUs7QUFDTCxXQUFLLE1BQU07QUFBQSxJQUNmO0FBQUEsRUFDSjtBQUdBLFNBQU8saUJBQWlCLFNBQVMsU0FBUyxJQUFJO0FBRTlDLFNBQU8sTUFBTTtBQUNULFdBQU8sb0JBQW9CLFNBQVMsU0FBUyxJQUFJO0FBQUEsRUFDckQ7QUFDSjs7O0FGN0NPLFNBQVMsa0JBQWtCLFVBQThCLENBQUMsR0FBRztBQUVoRSxRQUFNO0FBQUEsSUFDRixXQUFXLEtBQUssS0FBSztBQUFBLElBQ3JCLHVCQUF1QjtBQUFBLElBQ3ZCLDJCQUEyQjtBQUFBLElBQzNCLEdBQUc7QUFBQSxFQUNQLElBQUk7QUFHSixRQUFNLE9BQU8saUJBQWlCLEVBQUUsVUFBVSxHQUFHLFlBQVksQ0FBQztBQUcxRCxRQUFNLGFBQWdDLENBQUM7QUFFdkMsUUFBTSxNQUFNLENBQUMsV0FBeUI7QUFDbEMsZUFBVyxLQUFLLE9BQU8sSUFBSSxDQUFDO0FBQUEsRUFDaEM7QUFHQSxNQUFJLHNCQUFzQjtBQUN0QixRQUFJLGlCQUFpQjtBQUFBLEVBQ3pCO0FBRUEsTUFBSSwwQkFBMEI7QUFDMUIsUUFBSSx5QkFBeUI7QUFBQSxFQUNqQztBQUdBLE9BQUssTUFBTTtBQUdYLFNBQU87QUFBQSxJQUNILE9BQU8sS0FBSztBQUFBLElBQ1osU0FBUyxNQUFNO0FBQ1gsV0FBSyxRQUFRO0FBQ2IsaUJBQVcsUUFBUSxRQUFNLEdBQUcsQ0FBQztBQUFBLElBQ2pDO0FBQUEsRUFDSjtBQUNKOyIsCiAgIm5hbWVzIjogW10KfQo=
package/dist/index.mjs ADDED
@@ -0,0 +1,127 @@
1
+ // src/core.ts
2
+ function createUpdateCore(options) {
3
+ let oldEtag = null;
4
+ let timer;
5
+ let isChecking = false;
6
+ let isDestroyed = false;
7
+ const getCheckUrl = () => {
8
+ try {
9
+ const urlStr = options.checkUrl || window.location.href;
10
+ const targetUrl = new URL(urlStr, window.location.href);
11
+ targetUrl.searchParams.set("t", String(Date.now()));
12
+ return targetUrl.toString();
13
+ } catch {
14
+ return `${options.checkUrl || window.location.href}?t=${Date.now()}`;
15
+ }
16
+ };
17
+ const check = async () => {
18
+ if (isDestroyed || isChecking) return;
19
+ isChecking = true;
20
+ try {
21
+ const response = await fetch(getCheckUrl(), { method: "HEAD", cache: "no-cache" });
22
+ const newEtag = response.headers.get("etag") || response.headers.get("last-modified");
23
+ if (!newEtag) return;
24
+ if (!oldEtag) {
25
+ oldEtag = newEtag;
26
+ } else if (newEtag !== oldEtag) {
27
+ oldEtag = newEtag;
28
+ if (options.autoRefresh) {
29
+ window.location.reload();
30
+ } else {
31
+ options.onUpdate?.();
32
+ }
33
+ }
34
+ } catch (e) {
35
+ } finally {
36
+ if (!isDestroyed) {
37
+ isChecking = false;
38
+ }
39
+ }
40
+ };
41
+ const start = () => {
42
+ check();
43
+ if (options.interval && options.interval > 0) {
44
+ timer = setInterval(check, options.interval);
45
+ }
46
+ };
47
+ const destroy = () => {
48
+ isDestroyed = true;
49
+ if (timer) {
50
+ clearInterval(timer);
51
+ timer = void 0;
52
+ }
53
+ };
54
+ return {
55
+ check,
56
+ start,
57
+ destroy
58
+ };
59
+ }
60
+
61
+ // src/plugins.ts
62
+ var createRoutePlugin = (core) => {
63
+ const patch = (method) => {
64
+ const original = window.history[method];
65
+ if (original._isPatched) return;
66
+ window.history[method] = function(...args) {
67
+ const result = original.apply(this, args);
68
+ core.check();
69
+ return result;
70
+ };
71
+ window.history[method]._isPatched = true;
72
+ };
73
+ patch("pushState");
74
+ patch("replaceState");
75
+ const onPopState = () => core.check();
76
+ window.addEventListener("popstate", onPopState);
77
+ return () => {
78
+ window.removeEventListener("popstate", onPopState);
79
+ };
80
+ };
81
+ var createResourceErrorPlugin = (core) => {
82
+ const onError = (event) => {
83
+ const target = event.target;
84
+ if (!target || target.tagName !== "SCRIPT" && target.tagName !== "LINK") return;
85
+ const src = target.src || target.href;
86
+ if (src) {
87
+ core.check();
88
+ }
89
+ };
90
+ window.addEventListener("error", onError, true);
91
+ return () => {
92
+ window.removeEventListener("error", onError, true);
93
+ };
94
+ };
95
+
96
+ // src/index.ts
97
+ function createCheckUpdate(options = {}) {
98
+ const {
99
+ interval = 10 * 60 * 1e3,
100
+ enableRouteDetection = true,
101
+ enableLoadErrorDetection = false,
102
+ ...coreOptions
103
+ } = options;
104
+ const core = createUpdateCore({ interval, ...coreOptions });
105
+ const cleanupFns = [];
106
+ const use = (plugin) => {
107
+ cleanupFns.push(plugin(core));
108
+ };
109
+ if (enableRouteDetection) {
110
+ use(createRoutePlugin);
111
+ }
112
+ if (enableLoadErrorDetection) {
113
+ use(createResourceErrorPlugin);
114
+ }
115
+ core.start();
116
+ return {
117
+ check: core.check,
118
+ destroy: () => {
119
+ core.destroy();
120
+ cleanupFns.forEach((fn) => fn());
121
+ }
122
+ };
123
+ }
124
+ export {
125
+ createCheckUpdate
126
+ };
127
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2NvcmUudHMiLCAiLi4vc3JjL3BsdWdpbnMudHMiLCAiLi4vc3JjL2luZGV4LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJleHBvcnQgaW50ZXJmYWNlIENvcmVPcHRpb25zIHtcclxuICAgIGludGVydmFsPzogbnVtYmVyO1xyXG4gICAgY2hlY2tVcmw/OiBzdHJpbmc7XHJcbiAgICBhdXRvUmVmcmVzaD86IGJvb2xlYW47XHJcbiAgICBvblVwZGF0ZT86ICgpID0+IHZvaWQ7XHJcbn1cclxuXHJcbi8vIFx1NUI5QVx1NEU0OVx1NjgzOFx1NUZDM1x1NUI5RVx1NEY4Qlx1NUJGOVx1NTkxNlx1NjZCNFx1OTczMlx1NzY4NFx1NjNBNVx1NTNFM1xyXG5leHBvcnQgaW50ZXJmYWNlIFVwZGF0ZUNvcmVJbnN0YW5jZSB7XHJcbiAgICBjaGVjazogKCkgPT4gUHJvbWlzZTx2b2lkPjtcclxuICAgIHN0YXJ0OiAoKSA9PiB2b2lkO1xyXG4gICAgZGVzdHJveTogKCkgPT4gdm9pZDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVVwZGF0ZUNvcmUob3B0aW9uczogQ29yZU9wdGlvbnMpOiBVcGRhdGVDb3JlSW5zdGFuY2Uge1xyXG4gICAgLy8gLS0tIFx1NzlDMVx1NjcwOVx1NzJCNlx1NjAwMSAoXHU5NUVEXHU1MzA1KSAtLS1cclxuICAgIGxldCBvbGRFdGFnOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcclxuICAgIGxldCB0aW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0SW50ZXJ2YWw+IHwgdW5kZWZpbmVkO1xyXG4gICAgbGV0IGlzQ2hlY2tpbmcgPSBmYWxzZTtcclxuICAgIGxldCBpc0Rlc3Ryb3llZCA9IGZhbHNlO1xyXG5cclxuICAgIC8vIC0tLSBcdTUxODVcdTkwRThcdThGODVcdTUyQTlcdTUxRkRcdTY1NzAgLS0tXHJcblxyXG4gICAgY29uc3QgZ2V0Q2hlY2tVcmwgPSAoKTogc3RyaW5nID0+IHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBjb25zdCB1cmxTdHIgPSBvcHRpb25zLmNoZWNrVXJsIHx8IHdpbmRvdy5sb2NhdGlvbi5ocmVmO1xyXG4gICAgICAgICAgICBjb25zdCB0YXJnZXRVcmwgPSBuZXcgVVJMKHVybFN0ciwgd2luZG93LmxvY2F0aW9uLmhyZWYpO1xyXG4gICAgICAgICAgICB0YXJnZXRVcmwuc2VhcmNoUGFyYW1zLnNldCgndCcsIFN0cmluZyhEYXRlLm5vdygpKSk7XHJcbiAgICAgICAgICAgIHJldHVybiB0YXJnZXRVcmwudG9TdHJpbmcoKTtcclxuICAgICAgICB9IGNhdGNoIHtcclxuICAgICAgICAgICAgcmV0dXJuIGAke29wdGlvbnMuY2hlY2tVcmwgfHwgd2luZG93LmxvY2F0aW9uLmhyZWZ9P3Q9JHtEYXRlLm5vdygpfWA7XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxuXHJcbiAgICAvLyAtLS0gXHU2ODM4XHU1RkMzXHU2NUI5XHU2Q0Q1IC0tLVxyXG5cclxuICAgIGNvbnN0IGNoZWNrID0gYXN5bmMgKCkgPT4ge1xyXG4gICAgICAgIGlmIChpc0Rlc3Ryb3llZCB8fCBpc0NoZWNraW5nKSByZXR1cm47XHJcbiAgICAgICAgaXNDaGVja2luZyA9IHRydWU7XHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goZ2V0Q2hlY2tVcmwoKSwgeyBtZXRob2Q6ICdIRUFEJywgY2FjaGU6ICduby1jYWNoZScgfSk7XHJcbiAgICAgICAgICAgIGNvbnN0IG5ld0V0YWcgPSByZXNwb25zZS5oZWFkZXJzLmdldCgnZXRhZycpIHx8IHJlc3BvbnNlLmhlYWRlcnMuZ2V0KCdsYXN0LW1vZGlmaWVkJyk7XHJcblxyXG4gICAgICAgICAgICBpZiAoIW5ld0V0YWcpIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgIGlmICghb2xkRXRhZykge1xyXG4gICAgICAgICAgICAgICAgLy8gXHU1MjFEXHU1OUNCXHU1MzE2XHU1N0ZBXHU1MUM2XHJcbiAgICAgICAgICAgICAgICBvbGRFdGFnID0gbmV3RXRhZztcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChuZXdFdGFnICE9PSBvbGRFdGFnKSB7XHJcbiAgICAgICAgICAgICAgICBvbGRFdGFnID0gbmV3RXRhZztcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5hdXRvUmVmcmVzaCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5vblVwZGF0ZT8uKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIC8vIFx1N0Y1MVx1N0VEQ1x1OTUxOVx1OEJFRlx1NUZGRFx1NzU2NVxyXG4gICAgICAgIH0gZmluYWxseSB7XHJcbiAgICAgICAgICAgIGlmICghaXNEZXN0cm95ZWQpIHtcclxuICAgICAgICAgICAgICAgIGlzQ2hlY2tpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH07XHJcblxyXG4gICAgY29uc3Qgc3RhcnQgPSAoKSA9PiB7XHJcbiAgICAgICAgY2hlY2soKTsgLy8gXHU3QUNCXHU1MzczXHU2OEMwXHU2N0U1XHU0RTAwXHU2QjIxXHJcbiAgICAgICAgaWYgKG9wdGlvbnMuaW50ZXJ2YWwgJiYgb3B0aW9ucy5pbnRlcnZhbCA+IDApIHtcclxuICAgICAgICAgICAgdGltZXIgPSBzZXRJbnRlcnZhbChjaGVjaywgb3B0aW9ucy5pbnRlcnZhbCk7XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxuXHJcbiAgICBjb25zdCBkZXN0cm95ID0gKCkgPT4ge1xyXG4gICAgICAgIGlzRGVzdHJveWVkID0gdHJ1ZTtcclxuICAgICAgICBpZiAodGltZXIpIHtcclxuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aW1lcik7XHJcbiAgICAgICAgICAgIHRpbWVyID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcblxyXG4gICAgLy8gXHU4RkQ0XHU1NkRFXHU2ODM4XHU1RkMzXHU1QjlFXHU0RjhCXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIGNoZWNrLFxyXG4gICAgICAgIHN0YXJ0LFxyXG4gICAgICAgIGRlc3Ryb3lcclxuICAgIH07XHJcbn0iLCAiaW1wb3J0IHR5cGUgeyBVcGRhdGVDb3JlSW5zdGFuY2UgfSBmcm9tICcuL2NvcmUnO1xyXG5cclxuLy8gXHU2M0QyXHU0RUY2XHU3QzdCXHU1NzhCXHU1QjlBXHU0RTQ5XHVGRjFBXHU2M0E1XHU2NTM2XHU2ODM4XHU1RkMzXHU1QjlFXHU0RjhCXHVGRjBDXHU4RkQ0XHU1NkRFXHU2RTA1XHU3NDA2XHU1MUZEXHU2NTcwXHJcbmV4cG9ydCB0eXBlIFVwZGF0ZVBsdWdpbiA9IChjb3JlOiBVcGRhdGVDb3JlSW5zdGFuY2UpID0+ICgpID0+IHZvaWQ7XHJcblxyXG4vKiogKiBcdUQ4M0RcdUREMEMgXHU2M0QyXHU0RUY2XHVGRjFBXHU4REVGXHU3NTMxXHU1MjA3XHU2MzYyXHU2OEMwXHU2RDRCXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgY3JlYXRlUm91dGVQbHVnaW46IFVwZGF0ZVBsdWdpbiA9IChjb3JlKSA9PiB7XHJcbiAgICBjb25zdCBwYXRjaCA9IChtZXRob2Q6ICdwdXNoU3RhdGUnIHwgJ3JlcGxhY2VTdGF0ZScpID0+IHtcclxuICAgICAgICBjb25zdCBvcmlnaW5hbCA9IHdpbmRvdy5oaXN0b3J5W21ldGhvZF07XHJcblxyXG4gICAgICAgIC8vIFx1OTYzMlx1NkI2Mlx1OTFDRFx1NTkwRCBQYXRjaFxyXG4gICAgICAgIGlmICgob3JpZ2luYWwgYXMgYW55KS5faXNQYXRjaGVkKSByZXR1cm47XHJcblxyXG4gICAgICAgIHdpbmRvdy5oaXN0b3J5W21ldGhvZF0gPSBmdW5jdGlvbiAoLi4uYXJncykge1xyXG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBvcmlnaW5hbC5hcHBseSh0aGlzLCBhcmdzKTtcclxuICAgICAgICAgICAgY29yZS5jaGVjaygpOyAvLyBcdThDMDNcdTc1MjhcdTY4MzhcdTVGQzNcdTY4QzBcdTZENEJcclxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgICAgICB9O1xyXG4gICAgICAgICh3aW5kb3cuaGlzdG9yeVttZXRob2RdIGFzIGFueSkuX2lzUGF0Y2hlZCA9IHRydWU7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIDEuIFx1NTJBQlx1NjMwMSBIaXN0b3J5IEFQSVxyXG4gICAgcGF0Y2goJ3B1c2hTdGF0ZScpO1xyXG4gICAgcGF0Y2goJ3JlcGxhY2VTdGF0ZScpO1xyXG5cclxuICAgIC8vIDIuIFx1NzZEMVx1NTQyQyBwb3BzdGF0ZVxyXG4gICAgY29uc3Qgb25Qb3BTdGF0ZSA9ICgpID0+IGNvcmUuY2hlY2soKTtcclxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdwb3BzdGF0ZScsIG9uUG9wU3RhdGUpO1xyXG5cclxuICAgIC8vIFx1OEZENFx1NTZERVx1NkUwNVx1NzQwNlx1NTFGRFx1NjU3MFxyXG4gICAgcmV0dXJuICgpID0+IHtcclxuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncG9wc3RhdGUnLCBvblBvcFN0YXRlKTtcclxuICAgIH07XHJcbn07XHJcblxyXG4vKiogKiBcdUQ4M0RcdUREMEMgXHU2M0QyXHU0RUY2XHVGRjFBXHU4RDQ0XHU2RTkwXHU1MkEwXHU4RjdEXHU5NTE5XHU4QkVGXHU2OEMwXHU2RDRCXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgY3JlYXRlUmVzb3VyY2VFcnJvclBsdWdpbjogVXBkYXRlUGx1Z2luID0gKGNvcmUpID0+IHtcclxuICAgIGNvbnN0IG9uRXJyb3IgPSAoZXZlbnQ6IEV2ZW50KSA9PiB7XHJcbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xyXG4gICAgICAgIGlmICghdGFyZ2V0IHx8ICh0YXJnZXQudGFnTmFtZSAhPT0gJ1NDUklQVCcgJiYgdGFyZ2V0LnRhZ05hbWUgIT09ICdMSU5LJykpIHJldHVybjtcclxuXHJcbiAgICAgICAgY29uc3Qgc3JjID0gKHRhcmdldCBhcyBIVE1MU2NyaXB0RWxlbWVudCkuc3JjIHx8ICh0YXJnZXQgYXMgSFRNTExpbmtFbGVtZW50KS5ocmVmO1xyXG4gICAgICAgIGlmIChzcmMpIHtcclxuICAgICAgICAgICAgY29yZS5jaGVjaygpOyAvLyBcdThENDRcdTZFOTBcdTYzMDJcdTRFODZcdUZGMENcdTdBQ0JcdTUzNzNcdTY4QzBcdTY3RTVcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFx1NjM1NVx1ODNCN1x1OTYzNlx1NkJCNVx1NzZEMVx1NTQyQ1xyXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgb25FcnJvciwgdHJ1ZSk7XHJcblxyXG4gICAgcmV0dXJuICgpID0+IHtcclxuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignZXJyb3InLCBvbkVycm9yLCB0cnVlKTtcclxuICAgIH07XHJcbn07IiwgImltcG9ydCB7IGNyZWF0ZVVwZGF0ZUNvcmUsIHR5cGUgQ29yZU9wdGlvbnMgfSBmcm9tICcuL2NvcmUnO1xyXG5pbXBvcnQgeyBjcmVhdGVSb3V0ZVBsdWdpbiwgY3JlYXRlUmVzb3VyY2VFcnJvclBsdWdpbiwgdHlwZSBVcGRhdGVQbHVnaW4gfSBmcm9tICcuL3BsdWdpbnMnO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBDaGVja1VwZGF0ZU9wdGlvbnMgZXh0ZW5kcyBDb3JlT3B0aW9ucyB7XHJcbiAgICAvKiogXHU2NjJGXHU1NDI2XHU1RjAwXHU1NDJGXHU4REVGXHU3NTMxXHU1MjA3XHU2MzYyXHU2OEMwXHU2RDRCIChcdTlFRDhcdThCQTQgdHJ1ZSkgKi9cclxuICAgIGVuYWJsZVJvdXRlRGV0ZWN0aW9uPzogYm9vbGVhbjtcclxuICAgIC8qKiBcdTY2MkZcdTU0MjZcdTVGMDBcdTU0MkZcdThENDRcdTZFOTBcdTUyQTBcdThGN0RcdTk1MTlcdThCRUZcdTY4QzBcdTZENEIgKFx1OUVEOFx1OEJBNCBmYWxzZSkgKi9cclxuICAgIGVuYWJsZUxvYWRFcnJvckRldGVjdGlvbj86IGJvb2xlYW47XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDaGVja1VwZGF0ZShvcHRpb25zOiBDaGVja1VwZGF0ZU9wdGlvbnMgPSB7fSkge1xyXG4gICAgLy8gMS4gXHU1MjA2XHU3OUJCXHU5MTREXHU3RjZFXHJcbiAgICBjb25zdCB7XHJcbiAgICAgICAgaW50ZXJ2YWwgPSAxMCAqIDYwICogMTAwMCxcclxuICAgICAgICBlbmFibGVSb3V0ZURldGVjdGlvbiA9IHRydWUsXHJcbiAgICAgICAgZW5hYmxlTG9hZEVycm9yRGV0ZWN0aW9uID0gZmFsc2UsXHJcbiAgICAgICAgLi4uY29yZU9wdGlvbnNcclxuICAgIH0gPSBvcHRpb25zO1xyXG5cclxuICAgIC8vIDIuIFx1NTIxQlx1NUVGQVx1NjgzOFx1NUZDM1x1NUI5RVx1NEY4QlxyXG4gICAgY29uc3QgY29yZSA9IGNyZWF0ZVVwZGF0ZUNvcmUoeyBpbnRlcnZhbCwgLi4uY29yZU9wdGlvbnMgfSk7XHJcblxyXG4gICAgLy8gMy4gXHU2M0QyXHU0RUY2XHU3QkExXHU3NDA2XHJcbiAgICBjb25zdCBjbGVhbnVwRm5zOiBBcnJheTwoKSA9PiB2b2lkPiA9IFtdO1xyXG5cclxuICAgIGNvbnN0IHVzZSA9IChwbHVnaW46IFVwZGF0ZVBsdWdpbikgPT4ge1xyXG4gICAgICAgIGNsZWFudXBGbnMucHVzaChwbHVnaW4oY29yZSkpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyA0LiBcdTYzMDlcdTk3MDBcdTUyQTBcdThGN0RcdTYzRDJcdTRFRjZcclxuICAgIGlmIChlbmFibGVSb3V0ZURldGVjdGlvbikge1xyXG4gICAgICAgIHVzZShjcmVhdGVSb3V0ZVBsdWdpbik7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGVuYWJsZUxvYWRFcnJvckRldGVjdGlvbikge1xyXG4gICAgICAgIHVzZShjcmVhdGVSZXNvdXJjZUVycm9yUGx1Z2luKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyA1LiBcdTU0MkZcdTUyQThcdTY4MzhcdTVGQzNcclxuICAgIGNvcmUuc3RhcnQoKTtcclxuXHJcbiAgICAvLyA2LiBcdThGRDRcdTU2REVcdTVCRjlcdTU5MTYgQVBJXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIGNoZWNrOiBjb3JlLmNoZWNrLFxyXG4gICAgICAgIGRlc3Ryb3k6ICgpID0+IHtcclxuICAgICAgICAgICAgY29yZS5kZXN0cm95KCk7IC8vIFx1OTUwMFx1NkJDMVx1NjgzOFx1NUZDM1xyXG4gICAgICAgICAgICBjbGVhbnVwRm5zLmZvckVhY2goZm4gPT4gZm4oKSk7IC8vIFx1OTUwMFx1NkJDMVx1NjI0MFx1NjcwOVx1NjNEMlx1NEVGNlxyXG4gICAgICAgIH1cclxuICAgIH07XHJcbn0iXSwKICAibWFwcGluZ3MiOiAiO0FBY08sU0FBUyxpQkFBaUIsU0FBMEM7QUFFdkUsTUFBSSxVQUF5QjtBQUM3QixNQUFJO0FBQ0osTUFBSSxhQUFhO0FBQ2pCLE1BQUksY0FBYztBQUlsQixRQUFNLGNBQWMsTUFBYztBQUM5QixRQUFJO0FBQ0EsWUFBTSxTQUFTLFFBQVEsWUFBWSxPQUFPLFNBQVM7QUFDbkQsWUFBTSxZQUFZLElBQUksSUFBSSxRQUFRLE9BQU8sU0FBUyxJQUFJO0FBQ3RELGdCQUFVLGFBQWEsSUFBSSxLQUFLLE9BQU8sS0FBSyxJQUFJLENBQUMsQ0FBQztBQUNsRCxhQUFPLFVBQVUsU0FBUztBQUFBLElBQzlCLFFBQVE7QUFDSixhQUFPLEdBQUcsUUFBUSxZQUFZLE9BQU8sU0FBUyxJQUFJLE1BQU0sS0FBSyxJQUFJLENBQUM7QUFBQSxJQUN0RTtBQUFBLEVBQ0o7QUFJQSxRQUFNLFFBQVEsWUFBWTtBQUN0QixRQUFJLGVBQWUsV0FBWTtBQUMvQixp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
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@chaochao12138/check-update-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Frontend automatic update detection SDK for web applications",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean --sourcemap inline",
22
+ "prepublishOnly": "npm run build",
23
+ "release": "pnpm build && npm publish",
24
+ "test": "vitest",
25
+ "test:coverage": "vitest --coverage"
26
+ },
27
+ "peerDependencies": {
28
+ "vue": "^3.0.0"
29
+ },
30
+ "peerDependenciesMeta": {
31
+ "vue": {
32
+ "optional": true
33
+ }
34
+ },
35
+ "keywords": [
36
+ "update",
37
+ "notification",
38
+ "version-check",
39
+ "auto-refresh",
40
+ "etag",
41
+ "hot-reload",
42
+ "frontend",
43
+ "vue3"
44
+ ],
45
+ "author": {
46
+ "name": "Dezhen"
47
+ },
48
+ "license": "MIT",
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/dezhen/check-update-sdk.git"
52
+ },
53
+ "bugs": {
54
+ "url": "https://github.com/dezhen/check-update-sdk/issues"
55
+ },
56
+ "homepage": "https://github.com/dezhen/check-update-sdk#readme",
57
+ "engines": {
58
+ "node": ">=14.0.0"
59
+ },
60
+ "devDependencies": {
61
+ "@vitest/coverage-v8": "^4.0.16",
62
+ "@vitest/ui": "4.0.16",
63
+ "happy-dom": "^20.0.11",
64
+ "tsup": "^8.5.1",
65
+ "typescript": "^5.9.3",
66
+ "vitest": "^4.0.16"
67
+ }
68
+ }