@chaochao12138/check-update-sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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,228 @@
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
+ - **Zero Runtime Dependencies** - Lightweight and tree-shakeable
13
+ - **TypeScript Support** - Full TypeScript definitions included
14
+ - **Framework Agnostic** - Works with any frontend framework
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @dezhen/check-update-sdk
20
+ # or
21
+ pnpm add @dezhen/check-update-sdk
22
+ # or
23
+ yarn add @dezhen/check-update-sdk
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ```typescript
29
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
30
+
31
+ const updater = createCheckUpdate({
32
+ interval: 5 * 60 * 1000, // Check every 5 minutes
33
+ onUpdate: () => {
34
+ // Show update notification to user
35
+ if (confirm('A new version is available. Refresh now?')) {
36
+ window.location.reload();
37
+ }
38
+ }
39
+ });
40
+
41
+ // Later, if needed
42
+ updater.destroy();
43
+ ```
44
+
45
+ ## Options
46
+
47
+ ```typescript
48
+ interface CheckUpdateOptions {
49
+ /** Polling interval in milliseconds (default: 10 minutes) */
50
+ interval?: number;
51
+
52
+ /** Callback when update is detected */
53
+ onUpdate?: () => void;
54
+
55
+ /** Auto-refresh when update is detected (default: false) */
56
+ autoRefresh?: boolean;
57
+
58
+ /** Enable route change detection (default: true) */
59
+ enableRouteDetection?: boolean;
60
+
61
+ /** Enable resource load error detection (default: false) */
62
+ enableLoadErrorDetection?: boolean;
63
+
64
+ /** Custom URL to check for updates (default: current page URL) */
65
+ checkUrl?: string;
66
+ }
67
+ ```
68
+
69
+ ## Usage Examples
70
+
71
+ ### Auto-Refresh Mode
72
+
73
+ ```typescript
74
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
75
+
76
+ createCheckUpdate({
77
+ interval: 5 * 60 * 1000,
78
+ autoRefresh: true // Automatically refresh when update detected
79
+ });
80
+ ```
81
+
82
+ ### Custom Update Notification
83
+
84
+ ```typescript
85
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
86
+
87
+ const updater = createCheckUpdate({
88
+ interval: 10 * 60 * 1000,
89
+ onUpdate: () => {
90
+ // Show a custom notification
91
+ const notification = document.createElement('div');
92
+ notification.textContent = 'New version available!';
93
+ notification.style.cssText = `
94
+ position: fixed;
95
+ top: 20px;
96
+ right: 20px;
97
+ padding: 16px;
98
+ background: #4CAF50;
99
+ color: white;
100
+ border-radius: 8px;
101
+ cursor: pointer;
102
+ z-index: 9999;
103
+ `;
104
+ notification.onclick = () => window.location.reload();
105
+ document.body.appendChild(notification);
106
+ }
107
+ });
108
+ ```
109
+
110
+ ### Vue 3 Application
111
+
112
+ ```typescript
113
+ // main.ts
114
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
115
+
116
+ const app = createApp(App);
117
+
118
+ // Initialize update checker
119
+ const updater = createCheckUpdate({
120
+ interval: 5 * 60 * 1000,
121
+ onUpdate: () => {
122
+ // You can use your UI framework's notification system
123
+ console.log('New version available!');
124
+ }
125
+ });
126
+
127
+ // Cleanup on app unmount
128
+ app.config.globalProperties.$updater = updater;
129
+ ```
130
+
131
+ ### Disable Route Detection
132
+
133
+ ```typescript
134
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
135
+
136
+ createCheckUpdate({
137
+ enableRouteDetection: false, // Don't check on route changes
138
+ interval: 10 * 60 * 1000
139
+ });
140
+ ```
141
+
142
+ ### Enable Resource Error Detection
143
+
144
+ ```typescript
145
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
146
+
147
+ createCheckUpdate({
148
+ enableLoadErrorDetection: true, // Check on script/link load errors
149
+ onUpdate: () => {
150
+ console.log('Update detected due to resource error');
151
+ }
152
+ });
153
+ ```
154
+
155
+ ### Manual Check
156
+
157
+ ```typescript
158
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
159
+
160
+ const updater = createCheckUpdate();
161
+
162
+ // Manually trigger a check
163
+ updater.check();
164
+ ```
165
+
166
+ ### Cleanup
167
+
168
+ ```typescript
169
+ import { createCheckUpdate } from '@dezhen/check-update-sdk';
170
+
171
+ const updater = createCheckUpdate();
172
+
173
+ // Later, when you want to stop checking
174
+ updater.destroy();
175
+ ```
176
+
177
+ ## How It Works
178
+
179
+ The SDK detects updates by:
180
+
181
+ 1. **Initial Check**: Makes a HEAD request to get the current ETag or Last-Modified header
182
+ 2. **Periodic Polling**: At configured intervals, checks if the header has changed
183
+ 3. **Route Changes**: (Optional) Triggers a check when the user navigates to a new route
184
+ 4. **Resource Errors**: (Optional) Triggers a check when scripts or stylesheets fail to load
185
+ 5. **Tab Visibility**: Pauses polling when tab is hidden, resumes when visible
186
+
187
+ When an update is detected:
188
+ - If `autoRefresh` is `true`, the page reloads automatically
189
+ - Otherwise, the `onUpdate` callback is invoked
190
+
191
+ ## Server Configuration
192
+
193
+ 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.
194
+
195
+ ### Example Server Responses
196
+
197
+ **Before Update:**
198
+ ```
199
+ HTTP/1.1 200 OK
200
+ ETag: "abc123"
201
+ ```
202
+
203
+ **After Update:**
204
+ ```
205
+ HTTP/1.1 200 OK
206
+ ETag: "def456"
207
+ ```
208
+
209
+ The SDK detects the ETag change and triggers the update notification.
210
+
211
+ ## Browser Support
212
+
213
+ - Chrome/Edge (last 2 versions)
214
+ - Firefox (last 2 versions)
215
+ - Safari (last 2 versions)
216
+ - Modern mobile browsers
217
+
218
+ ## License
219
+
220
+ MIT
221
+
222
+ ## Contributing
223
+
224
+ Contributions are welcome! Please feel free to submit a Pull Request.
225
+
226
+ ## Support
227
+
228
+ 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": "0.0.1",
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
+ }