swpp-backends 2.0.8 → 2.1.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/README.md +2 -0
- package/dist/FileAnalyzer.js +8 -4
- package/dist/ServiceWorkerBuilder.js +6 -90
- package/dist/UpdateJsonBuilder.js +10 -2
- package/dist/index.js +1 -1
- package/dist/resources/sw-fetch.js +92 -0
- package/dist/resources/sw-template.js +51 -16
- package/package.json +1 -1
- package/types/UpdateJsonBuilder.d.ts +1 -1
package/README.md
CHANGED
package/dist/FileAnalyzer.js
CHANGED
|
@@ -175,13 +175,17 @@ exports.isStable = isStable;
|
|
|
175
175
|
async function loadVersionJson(url) {
|
|
176
176
|
const key = 'oldVersionJson';
|
|
177
177
|
const response = await (0, Utils_1.fetchFile)(url).catch(err => err);
|
|
178
|
-
if (response
|
|
179
|
-
(0, Utils_1.warn)('
|
|
178
|
+
if (response.status === 404 || response?.code === 'ENOTFOUND') {
|
|
179
|
+
(0, Utils_1.warn)('VersionJsonLoader', `拉取 ${url} 时出现 404 错误,如果您是第一次构建请忽略这个警告。`);
|
|
180
180
|
return (0, Variant_1.writeVariant)(key, null);
|
|
181
181
|
}
|
|
182
|
-
else {
|
|
183
|
-
|
|
182
|
+
else if (![200, 301, 302, 307, 308].includes(response.status)) {
|
|
183
|
+
(0, Utils_1.error)('VersionJsonLoader', `拉取 ${url} 时出现 ${response.status} 错误!`);
|
|
184
|
+
if ('status' in response)
|
|
185
|
+
throw `拉取时出现 ${response.status} 异常`;
|
|
186
|
+
throw response;
|
|
184
187
|
}
|
|
188
|
+
return (0, Variant_1.writeVariant)(key, await response.json());
|
|
185
189
|
}
|
|
186
190
|
exports.loadVersionJson = loadVersionJson;
|
|
187
191
|
/** 提交要存储到 version json 的值 */
|
|
@@ -30,6 +30,7 @@ function buildServiceWorker() {
|
|
|
30
30
|
...('external' in rules && Array.isArray(rules.external) ? rules.external : [])
|
|
31
31
|
], true) + '\n';
|
|
32
32
|
if (!fetchFile) {
|
|
33
|
+
const { JS_CODE_GET_CDN_LIST, JS_CODE_GET_SPARE_URLS, JS_CODE_DEF_FETCH_FILE } = require('./resources/sw-fetch.js');
|
|
33
34
|
if (getRaceUrls)
|
|
34
35
|
cache += JS_CODE_GET_CDN_LIST;
|
|
35
36
|
else if (getSpareUrls)
|
|
@@ -53,9 +54,12 @@ function buildServiceWorker() {
|
|
|
53
54
|
if (modifyRequest) {
|
|
54
55
|
content = content.replaceAll('// [modifyRequest call]', `
|
|
55
56
|
const modify = modifyRequest(request)
|
|
56
|
-
if (modify)
|
|
57
|
+
if (modify) {
|
|
58
|
+
request = modify
|
|
59
|
+
url = new URL(request.url)
|
|
60
|
+
}
|
|
57
61
|
`).replaceAll('// [modifyRequest else-if]', `
|
|
58
|
-
else if (modify)
|
|
62
|
+
else if (modify) handleFetch(fetchFile(request, false))
|
|
59
63
|
`);
|
|
60
64
|
}
|
|
61
65
|
if (blockRequest) {
|
|
@@ -79,91 +83,3 @@ function buildServiceWorker() {
|
|
|
79
83
|
return content;
|
|
80
84
|
}
|
|
81
85
|
exports.buildServiceWorker = buildServiceWorker;
|
|
82
|
-
// 缺省的 fetchFile 函数的代码
|
|
83
|
-
const JS_CODE_DEF_FETCH_FILE = `
|
|
84
|
-
const fetchFile = (request, banCache) => fetch(request, {
|
|
85
|
-
cache: banCache ? "no-store" : "default",
|
|
86
|
-
mode: 'cors',
|
|
87
|
-
credentials: 'same-origin'
|
|
88
|
-
})
|
|
89
|
-
`;
|
|
90
|
-
// getRaceUrls 函数的代码
|
|
91
|
-
const JS_CODE_GET_CDN_LIST = `
|
|
92
|
-
const fetchFile = (request, banCache) => {
|
|
93
|
-
const fetchArgs = {
|
|
94
|
-
cache: banCache ? 'no-store' : 'default',
|
|
95
|
-
mode: 'cors',
|
|
96
|
-
credentials: 'same-origin'
|
|
97
|
-
}
|
|
98
|
-
const list = getRaceUrls(request.url)
|
|
99
|
-
if (!list || !Promise.any) return fetch(request, fetchArgs)
|
|
100
|
-
const res = list.map(url => new Request(url, request))
|
|
101
|
-
const controllers = []
|
|
102
|
-
return Promise.any(res.map(
|
|
103
|
-
(it, index) => fetch(it, Object.assign(
|
|
104
|
-
{signal: (controllers[index] = new AbortController()).signal},
|
|
105
|
-
fetchArgs
|
|
106
|
-
)).then(response => checkResponse(response) ? {index, response} : Promise.reject())
|
|
107
|
-
)).then(it => {
|
|
108
|
-
for (let i in controllers) {
|
|
109
|
-
if (i != it.index) controllers[i].abort()
|
|
110
|
-
}
|
|
111
|
-
return it.response
|
|
112
|
-
})
|
|
113
|
-
}
|
|
114
|
-
`;
|
|
115
|
-
// getSpareUrls 函数的代码
|
|
116
|
-
const JS_CODE_GET_SPARE_URLS = `
|
|
117
|
-
const fetchFile = (request, banCache, spare = null) => {
|
|
118
|
-
const fetchArgs = {
|
|
119
|
-
cache: banCache ? 'no-store' : 'default',
|
|
120
|
-
mode: 'cors',
|
|
121
|
-
credentials: 'same-origin'
|
|
122
|
-
}
|
|
123
|
-
if (!spare) {
|
|
124
|
-
spare = getSpareUrls(request.url)
|
|
125
|
-
if (!spare) return fetch(request, fetchArgs)
|
|
126
|
-
}
|
|
127
|
-
const list = spare.list
|
|
128
|
-
const controllers = new Array(list.length)
|
|
129
|
-
const startFetch =
|
|
130
|
-
index => fetch(
|
|
131
|
-
new Request(list[index], request),
|
|
132
|
-
Object.assign({
|
|
133
|
-
signal: (controllers[index] = new AbortController()).signal
|
|
134
|
-
}, fetchArgs)
|
|
135
|
-
).then(response => checkResponse(response) ? {r: response, i: index} : Promise.reject())
|
|
136
|
-
return new Promise((resolve, reject) => {
|
|
137
|
-
let flag = true
|
|
138
|
-
const startAll = () => {
|
|
139
|
-
flag = false
|
|
140
|
-
Promise.any([
|
|
141
|
-
first,
|
|
142
|
-
...Array.from({
|
|
143
|
-
length: list.length - 1
|
|
144
|
-
}, (_, index) => index + 1).map(index => startFetch(index))
|
|
145
|
-
]).then(res => {
|
|
146
|
-
for (let i = 0; i !== list.length; ++i) {
|
|
147
|
-
if (i !== res.i)
|
|
148
|
-
controllers[i].abort()
|
|
149
|
-
}
|
|
150
|
-
resolve(res.r)
|
|
151
|
-
}).catch(() => reject(\`请求 \${request.url} 失败\`))
|
|
152
|
-
}
|
|
153
|
-
const id = setTimeout(startAll, spare.timeout)
|
|
154
|
-
const first = startFetch(0)
|
|
155
|
-
.then(res => {
|
|
156
|
-
if (flag) {
|
|
157
|
-
clearTimeout(id)
|
|
158
|
-
resolve(res.r)
|
|
159
|
-
}
|
|
160
|
-
}).catch(() => {
|
|
161
|
-
if (flag) {
|
|
162
|
-
clearTimeout(id)
|
|
163
|
-
startAll()
|
|
164
|
-
}
|
|
165
|
-
return Promise.reject()
|
|
166
|
-
})
|
|
167
|
-
})
|
|
168
|
-
}
|
|
169
|
-
`;
|
|
@@ -34,6 +34,8 @@ function buildUpdateJson(root, dif) {
|
|
|
34
34
|
if (userUpdate.flag === (0, Variant_1.readOldVersionJson)()?.external?.swppFlag)
|
|
35
35
|
userUpdate = undefined;
|
|
36
36
|
}
|
|
37
|
+
if (!dif)
|
|
38
|
+
dif = (0, Variant_1.readAnalyzeResult)();
|
|
37
39
|
// 如果需要强制刷新直接返回
|
|
38
40
|
if (dif.force || userUpdate?.force)
|
|
39
41
|
return {
|
|
@@ -113,10 +115,16 @@ exports.submitChange = submitChange;
|
|
|
113
115
|
async function loadUpdateJson(url) {
|
|
114
116
|
const key = 'oldUpdateJson';
|
|
115
117
|
const response = await (0, Utils_1.fetchFile)(url).catch(err => err);
|
|
116
|
-
if (response
|
|
117
|
-
(0, Utils_1.warn)('
|
|
118
|
+
if (response.status === 404 || response.code === 'ENOTFOUND') {
|
|
119
|
+
(0, Utils_1.warn)('UpdateJsonLoader', `拉取 ${url} 时出现 404 错误,如果您是第一次构建请忽略这个警告。`);
|
|
118
120
|
return (0, Variant_1.writeVariant)(key, null);
|
|
119
121
|
}
|
|
122
|
+
else if (![200, 301, 302, 307, 308].includes(response.status)) {
|
|
123
|
+
(0, Utils_1.error)('UpdateJsonLoader', `拉取 ${url} 时出现 ${response.status} 错误!`);
|
|
124
|
+
if ('status' in response)
|
|
125
|
+
throw `拉取时出现 ${response.status} 异常`;
|
|
126
|
+
throw response;
|
|
127
|
+
}
|
|
120
128
|
return (0, Variant_1.writeVariant)(key, await response.json());
|
|
121
129
|
}
|
|
122
130
|
exports.loadUpdateJson = loadUpdateJson;
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ const VersionAnalyzer_1 = require("./VersionAnalyzer");
|
|
|
10
10
|
const DomBuilder_1 = require("./DomBuilder");
|
|
11
11
|
// noinspection JSUnusedGlobalSymbols
|
|
12
12
|
exports.default = {
|
|
13
|
-
version: '2.
|
|
13
|
+
version: '2.1.1',
|
|
14
14
|
cache: {
|
|
15
15
|
readEjectData: Utils_1.readEjectData, readUpdateJson: Variant_1.readUpdateJson,
|
|
16
16
|
readRules: Variant_1.readRules, readMergeVersionMap: Variant_1.readMergeVersionMap,
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/** @type function */
|
|
2
|
+
let getRaceUrls, checkResponse, getSpareUrls
|
|
3
|
+
|
|
4
|
+
module.exports.JS_CODE_DEF_FETCH_FILE = 'const fetchFile = ' + (
|
|
5
|
+
(request, banCache) => fetch(request, {
|
|
6
|
+
cache: banCache ? "no-store" : "default",
|
|
7
|
+
mode: 'cors',
|
|
8
|
+
credentials: 'same-origin'
|
|
9
|
+
})
|
|
10
|
+
).toString()
|
|
11
|
+
|
|
12
|
+
module.exports.JS_CODE_GET_CDN_LIST= 'const fetchFile = ' + (
|
|
13
|
+
(request, banCache) => {
|
|
14
|
+
const fetchArgs = {
|
|
15
|
+
cache: banCache ? 'no-store' : 'default',
|
|
16
|
+
mode: 'cors',
|
|
17
|
+
credentials: 'same-origin'
|
|
18
|
+
}
|
|
19
|
+
const list = getRaceUrls(request.url)
|
|
20
|
+
if (!list || !Promise.any) return fetch(request, fetchArgs)
|
|
21
|
+
const res = list.map(url => new Request(url, request))
|
|
22
|
+
const controllers = []
|
|
23
|
+
// noinspection JSCheckFunctionSignatures
|
|
24
|
+
return Promise.any(res.map(
|
|
25
|
+
(it, index) => fetch(it, Object.assign(
|
|
26
|
+
{signal: (controllers[index] = new AbortController()).signal},
|
|
27
|
+
fetchArgs
|
|
28
|
+
)).then(response => checkResponse(response) ? {index, response} : Promise.reject())
|
|
29
|
+
)).then(it => {
|
|
30
|
+
for (let i in controllers) {
|
|
31
|
+
if (i !== it.index) controllers[i].abort()
|
|
32
|
+
}
|
|
33
|
+
return it.response
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
).toString()
|
|
37
|
+
|
|
38
|
+
module.exports.JS_CODE_GET_SPARE_URLS = 'const fetchFile = ' + (
|
|
39
|
+
(request, banCache, spare = null) => {
|
|
40
|
+
const fetchArgs = {
|
|
41
|
+
cache: banCache ? 'no-store' : 'default',
|
|
42
|
+
mode: 'cors',
|
|
43
|
+
credentials: 'same-origin'
|
|
44
|
+
}
|
|
45
|
+
if (!spare) {
|
|
46
|
+
spare = getSpareUrls(request.url)
|
|
47
|
+
if (!spare) return fetch(request, fetchArgs)
|
|
48
|
+
}
|
|
49
|
+
const list = spare.list
|
|
50
|
+
const controllers = new Array(list.length)
|
|
51
|
+
// noinspection JSCheckFunctionSignatures
|
|
52
|
+
const startFetch =
|
|
53
|
+
index => fetch(
|
|
54
|
+
new Request(list[index], request),
|
|
55
|
+
Object.assign({
|
|
56
|
+
signal: (controllers[index] = new AbortController()).signal
|
|
57
|
+
}, fetchArgs)
|
|
58
|
+
).then(response => checkResponse(response) ? {r: response, i: index} : Promise.reject())
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
let flag = true
|
|
61
|
+
const startAll = () => {
|
|
62
|
+
flag = false
|
|
63
|
+
Promise.any([
|
|
64
|
+
first,
|
|
65
|
+
...Array.from({
|
|
66
|
+
length: list.length - 1
|
|
67
|
+
}, (_, index) => index + 1).map(index => startFetch(index))
|
|
68
|
+
]).then(res => {
|
|
69
|
+
for (let i = 0; i !== list.length; ++i) {
|
|
70
|
+
if (i !== res.i)
|
|
71
|
+
controllers[i].abort()
|
|
72
|
+
}
|
|
73
|
+
resolve(res.r)
|
|
74
|
+
}).catch(() => reject(`请求 ${request.url} 失败`))
|
|
75
|
+
}
|
|
76
|
+
const id = setTimeout(startAll, spare.timeout)
|
|
77
|
+
const first = startFetch(0)
|
|
78
|
+
.then(res => {
|
|
79
|
+
if (flag) {
|
|
80
|
+
clearTimeout(id)
|
|
81
|
+
resolve(res.r)
|
|
82
|
+
}
|
|
83
|
+
}).catch(() => {
|
|
84
|
+
if (flag) {
|
|
85
|
+
clearTimeout(id)
|
|
86
|
+
startAll()
|
|
87
|
+
}
|
|
88
|
+
return Promise.reject()
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
).toString()
|
|
@@ -63,33 +63,65 @@
|
|
|
63
63
|
)).then(list => list.filter(it => it))
|
|
64
64
|
)
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* 缓存列表
|
|
68
|
+
* @type {Map<string, {s, e}[]>}
|
|
69
|
+
*/
|
|
70
|
+
const cacheMap = new Map()
|
|
71
|
+
|
|
66
72
|
self.addEventListener('fetch', event => {
|
|
67
73
|
let request = event.request
|
|
74
|
+
let url = new URL(request.url)
|
|
75
|
+
// [blockRequest call]
|
|
68
76
|
if (request.method !== 'GET' || !request.url.startsWith('http')) return
|
|
69
77
|
// [modifyRequest call]
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
let cacheKey = url.hostname + url.pathname + url.search
|
|
79
|
+
let cache = cacheMap.get(cacheKey)
|
|
80
|
+
if (cache) {
|
|
81
|
+
return event.respondWith(
|
|
82
|
+
new Promise((resolve, reject) => {
|
|
83
|
+
cacheMap.get(cacheKey).push({s: resolve, e: reject})
|
|
84
|
+
})
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
cacheMap.set(cacheKey, cache = [])
|
|
88
|
+
/** 处理拉取 */
|
|
89
|
+
const handleFetch = promise =>
|
|
90
|
+
event.respondWith(promise.then(response => {
|
|
91
|
+
for (let item of cache) {
|
|
92
|
+
item.s(response.clone())
|
|
93
|
+
}
|
|
94
|
+
}).catch(err => {
|
|
95
|
+
for (let item of cache) {
|
|
96
|
+
item.e(err)
|
|
97
|
+
}
|
|
98
|
+
}).then(() => {
|
|
99
|
+
cacheMap.delete(cacheKey)
|
|
100
|
+
return promise
|
|
101
|
+
}))
|
|
72
102
|
const cacheRule = findCache(url)
|
|
73
103
|
if (cacheRule) {
|
|
74
104
|
let key = `https://${url.host}${url.pathname}`
|
|
75
105
|
if (key.endsWith('/index.html')) key = key.substring(0, key.length - 10)
|
|
76
106
|
if (cacheRule.search) key += url.search
|
|
77
|
-
|
|
78
|
-
.then(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
107
|
+
handleFetch(
|
|
108
|
+
caches.match(key).then(
|
|
109
|
+
cache => cache ?? fetchFile(request, true)
|
|
110
|
+
.then(response => {
|
|
111
|
+
if (checkResponse(response)) {
|
|
112
|
+
const clone = response.clone()
|
|
113
|
+
caches.open(CACHE_NAME).then(it => it.put(key, clone))
|
|
114
|
+
// [debug put]
|
|
115
|
+
}
|
|
116
|
+
return response
|
|
117
|
+
})
|
|
87
118
|
)
|
|
88
119
|
)
|
|
89
120
|
} else {
|
|
90
121
|
const spare = getSpareUrls(request.url)
|
|
91
|
-
if (spare)
|
|
122
|
+
if (spare) handleFetch(fetchFile(request, false, spare))
|
|
92
123
|
// [modifyRequest else-if]
|
|
124
|
+
else handleFetch(fetch(request))
|
|
93
125
|
}
|
|
94
126
|
})
|
|
95
127
|
|
|
@@ -106,8 +138,11 @@
|
|
|
106
138
|
)
|
|
107
139
|
})
|
|
108
140
|
|
|
109
|
-
/**
|
|
110
|
-
|
|
141
|
+
/**
|
|
142
|
+
* 判断指定 url 击中了哪一种缓存,都没有击中则返回 null
|
|
143
|
+
* @param url {URL}
|
|
144
|
+
*/
|
|
145
|
+
const findCache = url => {
|
|
111
146
|
if (url.hostname === 'localhost') return
|
|
112
147
|
for (let key in cacheRules) {
|
|
113
148
|
const value = cacheRules[key]
|
|
@@ -233,7 +268,7 @@
|
|
|
233
268
|
const getMatch = () => {
|
|
234
269
|
switch (json['flag']) {
|
|
235
270
|
case 'html':
|
|
236
|
-
return url => url.match(/(\/|\.html)$/)
|
|
271
|
+
return url => url.pathname.match(/(\/|\.html)$/)
|
|
237
272
|
case 'end':
|
|
238
273
|
return url => forEachValues(value => url.href.endsWith(value))
|
|
239
274
|
case 'begin':
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@ import { AnalyzeResult } from './VersionAnalyzer';
|
|
|
10
10
|
* @param root 网站根路径(包括网络协议)
|
|
11
11
|
* @param dif 网站文件变化
|
|
12
12
|
*/
|
|
13
|
-
export declare function buildUpdateJson(root: string, dif
|
|
13
|
+
export declare function buildUpdateJson(root: string, dif?: AnalyzeResult): UpdateJson;
|
|
14
14
|
/** 提交修改 */
|
|
15
15
|
export declare function submitChange(...change: ChangeExpression[]): void;
|
|
16
16
|
/**
|