@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 +21 -0
- package/README.md +228 -0
- package/dist/index.d.mts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +154 -0
- package/dist/index.mjs +127 -0
- package/package.json +68 -0
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.
|
package/dist/index.d.mts
ADDED
|
@@ -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.d.ts
ADDED
|
@@ -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+IHtcclxuICAgICAgICAgICAgY29yZS5kZXN0cm95KCk7IC8vIFx1OTUwMFx1NkJDMVx1NjgzOFx1NUZDM1xyXG4gICAgICAgICAgICBjbGVhbnVwRm5zLmZvckVhY2goZm4gPT4gZm4oKSk7IC8vIFx1OTUwMFx1NkJDMVx1NjI0MFx1NjcwOVx1NjNEMlx1NEVGNlxyXG4gICAgICAgIH1cclxuICAgIH07XHJcbn0iXSwKICAibWFwcGluZ3MiOiAiO0FBY08sU0FBUyxpQkFBaUIsU0FBMEM7QUFFdkUsTUFBSSxVQUF5QjtBQUM3QixNQUFJO0FBQ0osTUFBSSxhQUFhO0FBQ2pCLE1BQUksY0FBYztBQUlsQixRQUFNLGNBQWMsTUFBYztBQUM5QixRQUFJO0FBQ0EsWUFBTSxTQUFTLFFBQVEsWUFBWSxPQUFPLFNBQVM7QUFDbkQsWUFBTSxZQUFZLElBQUksSUFBSSxRQUFRLE9BQU8sU0FBUyxJQUFJO0FBQ3RELGdCQUFVLGFBQWEsSUFBSSxLQUFLLE9BQU8sS0FBSyxJQUFJLENBQUMsQ0FBQztBQUNsRCxhQUFPLFVBQVUsU0FBUztBQUFBLElBQzlCLFFBQVE7QUFDSixhQUFPLEdBQUcsUUFBUSxZQUFZLE9BQU8sU0FBUyxJQUFJLE1BQU0sS0FBSyxJQUFJLENBQUM7QUFBQSxJQUN0RTtBQUFBLEVBQ0o7QUFJQSxRQUFNLFFBQVEsWUFBWTtBQUN0QixRQUFJLGVBQWUsV0FBWTtBQUMvQixpQkFBYTtBQUViLFFBQUk7QUFDQSxZQUFNLFdBQVcsTUFBTSxNQUFNLFlBQVksR0FBRyxFQUFFLFFBQVEsUUFBUSxPQUFPLFdBQVcsQ0FBQztBQUNqRixZQUFNLFVBQVUsU0FBUyxRQUFRLElBQUksTUFBTSxLQUFLLFNBQVMsUUFBUSxJQUFJLGVBQWU7QUFFcEYsVUFBSSxDQUFDLFFBQVM7QUFFZCxVQUFJLENBQUMsU0FBUztBQUVWLGtCQUFVO0FBQUEsTUFDZCxXQUFXLFlBQVksU0FBUztBQUM1QixrQkFBVTtBQUVWLFlBQUksUUFBUSxhQUFhO0FBQ3JCLGlCQUFPLFNBQVMsT0FBTztBQUFBLFFBQzNCLE9BQU87QUFDSCxrQkFBUSxXQUFXO0FBQUEsUUFDdkI7QUFBQSxNQUNKO0FBQUEsSUFDSixTQUFTLEdBQUc7QUFBQSxJQUVaLFVBQUU7QUFDRSxVQUFJLENBQUMsYUFBYTtBQUNkLHFCQUFhO0FBQUEsTUFDakI7QUFBQSxJQUNKO0FBQUEsRUFDSjtBQUVBLFFBQU0sUUFBUSxNQUFNO0FBQ2hCLFVBQU07QUFDTixRQUFJLFFBQVEsWUFBWSxRQUFRLFdBQVcsR0FBRztBQUMxQyxjQUFRLFlBQVksT0FBTyxRQUFRLFFBQVE7QUFBQSxJQUMvQztBQUFBLEVBQ0o7QUFFQSxRQUFNLFVBQVUsTUFBTTtBQUNsQixrQkFBYztBQUNkLFFBQUksT0FBTztBQUNQLG9CQUFjLEtBQUs7QUFDbkIsY0FBUTtBQUFBLElBQ1o7QUFBQSxFQUNKO0FBR0EsU0FBTztBQUFBLElBQ0g7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLEVBQ0o7QUFDSjs7O0FDakZPLElBQU0sb0JBQWtDLENBQUMsU0FBUztBQUNyRCxRQUFNLFFBQVEsQ0FBQyxXQUF5QztBQUNwRCxVQUFNLFdBQVcsT0FBTyxRQUFRLE1BQU07QUFHdEMsUUFBSyxTQUFpQixXQUFZO0FBRWxDLFdBQU8sUUFBUSxNQUFNLElBQUksWUFBYSxNQUFNO0FBQ3hDLFlBQU0sU0FBUyxTQUFTLE1BQU0sTUFBTSxJQUFJO0FBQ3hDLFdBQUssTUFBTTtBQUNYLGFBQU87QUFBQSxJQUNYO0FBQ0EsSUFBQyxPQUFPLFFBQVEsTUFBTSxFQUFVLGFBQWE7QUFBQSxFQUNqRDtBQUdBLFFBQU0sV0FBVztBQUNqQixRQUFNLGNBQWM7QUFHcEIsUUFBTSxhQUFhLE1BQU0sS0FBSyxNQUFNO0FBQ3BDLFNBQU8saUJBQWlCLFlBQVksVUFBVTtBQUc5QyxTQUFPLE1BQU07QUFDVCxXQUFPLG9CQUFvQixZQUFZLFVBQVU7QUFBQSxFQUNyRDtBQUNKO0FBSU8sSUFBTSw0QkFBMEMsQ0FBQyxTQUFTO0FBQzdELFFBQU0sVUFBVSxDQUFDLFVBQWlCO0FBQzlCLFVBQU0sU0FBUyxNQUFNO0FBQ3JCLFFBQUksQ0FBQyxVQUFXLE9BQU8sWUFBWSxZQUFZLE9BQU8sWUFBWSxPQUFTO0FBRTNFLFVBQU0sTUFBTyxPQUE2QixPQUFRLE9BQTJCO0FBQzdFLFFBQUksS0FBSztBQUNMLFdBQUssTUFBTTtBQUFBLElBQ2Y7QUFBQSxFQUNKO0FBR0EsU0FBTyxpQkFBaUIsU0FBUyxTQUFTLElBQUk7QUFFOUMsU0FBTyxNQUFNO0FBQ1QsV0FBTyxvQkFBb0IsU0FBUyxTQUFTLElBQUk7QUFBQSxFQUNyRDtBQUNKOzs7QUM3Q08sU0FBUyxrQkFBa0IsVUFBOEIsQ0FBQyxHQUFHO0FBRWhFLFFBQU07QUFBQSxJQUNGLFdBQVcsS0FBSyxLQUFLO0FBQUEsSUFDckIsdUJBQXVCO0FBQUEsSUFDdkIsMkJBQTJCO0FBQUEsSUFDM0IsR0FBRztBQUFBLEVBQ1AsSUFBSTtBQUdKLFFBQU0sT0FBTyxpQkFBaUIsRUFBRSxVQUFVLEdBQUcsWUFBWSxDQUFDO0FBRzFELFFBQU0sYUFBZ0MsQ0FBQztBQUV2QyxRQUFNLE1BQU0sQ0FBQyxXQUF5QjtBQUNsQyxlQUFXLEtBQUssT0FBTyxJQUFJLENBQUM7QUFBQSxFQUNoQztBQUdBLE1BQUksc0JBQXNCO0FBQ3RCLFFBQUksaUJBQWlCO0FBQUEsRUFDekI7QUFFQSxNQUFJLDBCQUEwQjtBQUMxQixRQUFJLHlCQUF5QjtBQUFBLEVBQ2pDO0FBR0EsT0FBSyxNQUFNO0FBR1gsU0FBTztBQUFBLElBQ0gsT0FBTyxLQUFLO0FBQUEsSUFDWixTQUFTLE1BQU07QUFDWCxXQUFLLFFBQVE7QUFDYixpQkFBVyxRQUFRLFFBQU0sR0FBRyxDQUFDO0FBQUEsSUFDakM7QUFBQSxFQUNKO0FBQ0o7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
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
|
+
}
|