swpp-backends 0.0.1-alpha.0 → 0.0.2-alpha

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/dist/swppRules.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SwppRulesLoadError = exports.loadRules = void 0;
6
+ exports.loadRules = exports.addRulesMapEvent = exports.readRules = void 0;
7
7
  const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const defConfig = {
@@ -33,19 +33,41 @@ const defConfig = {
33
33
  json: {
34
34
  maxHtml: 15,
35
35
  charLimit: 1024,
36
- precisionMode: {
37
- 'default': false
38
- },
39
36
  merge: [],
40
- exclude: [/^\/sw\.js$/]
37
+ exclude: {
38
+ localhost: [/^\/sw\.js$/],
39
+ other: []
40
+ }
41
41
  },
42
42
  external: {
43
43
  timeout: 5000,
44
44
  js: [],
45
- skip: [],
45
+ stable: [],
46
46
  replacer: it => it
47
47
  }
48
48
  };
49
+ const eventList = [];
50
+ let _rules;
51
+ /**
52
+ * 读取最后一次构建的 rules
53
+ *
54
+ * **执行该函数前必须调用过 [loadRules]**
55
+ */
56
+ function readRules() {
57
+ if (!_rules)
58
+ throw 'rules 尚未初始化';
59
+ return _rules;
60
+ }
61
+ exports.readRules = readRules;
62
+ /**
63
+ * 添加一个 rules 映射事件,这个事件允许用户修改 rules 的内容
64
+ *
65
+ * 执行时按照注册的顺序执行
66
+ */
67
+ function addRulesMapEvent(mapper) {
68
+ eventList.push(mapper);
69
+ }
70
+ exports.addRulesMapEvent = addRulesMapEvent;
49
71
  /**
50
72
  * 加载 rules 文件
51
73
  * @param root 项目根目录
@@ -54,14 +76,14 @@ const defConfig = {
54
76
  */
55
77
  function loadRules(root, fileName, selects) {
56
78
  // 支持的拓展名
57
- const extensions = ['ts', 'cjs', 'js'];
79
+ const extensions = ['cjs', 'js'];
58
80
  // 根目录下的 rules 文件
59
81
  const rootPath = extensions.map(it => path_1.default.resolve(root, `${fileName}.${it}`))
60
82
  .find(it => fs_1.default.existsSync(it));
61
83
  // 其它可选目录下的 rules 文件
62
84
  const selectPath = selects.flatMap(value => extensions.map(it => path_1.default.resolve(value, `${fileName}.${it}`))).find(it => fs_1.default.existsSync(it));
63
85
  if (!(rootPath || selectPath))
64
- throw new SwppRulesLoadError('未查询到 rules 文件');
86
+ throw '未查询到 rules 文件';
65
87
  const rootRules = rootPath ? { ...require(rootPath) } : {};
66
88
  const selectRules = selectPath ? require(selectPath) : {};
67
89
  const config = rootRules.config ?? {};
@@ -69,7 +91,10 @@ function loadRules(root, fileName, selects) {
69
91
  mergeConfig(config, defConfig);
70
92
  Object.assign(rootRules, selectRules);
71
93
  rootRules.config = config;
72
- return rootRules;
94
+ for (let event of eventList) {
95
+ event(rootRules);
96
+ }
97
+ return _rules = rootRules;
73
98
  }
74
99
  exports.loadRules = loadRules;
75
100
  /** 合并配置项 */
@@ -90,10 +115,3 @@ function mergeConfig(dist, that) {
90
115
  }
91
116
  return dist;
92
117
  }
93
- /** rules 加载异常 */
94
- class SwppRulesLoadError {
95
- constructor(message) {
96
- this.message = message;
97
- }
98
- }
99
- exports.SwppRulesLoadError = SwppRulesLoadError;
package/dist/utils.js CHANGED
@@ -3,23 +3,35 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.replaceDevRequest = exports.fetchFile = exports.getSource = exports.readEjectData = exports.calcEjectValues = void 0;
6
+ exports.replaceDevRequest = exports.fetchFile = exports.getSource = exports.readEjectData = exports.calcEjectValues = exports.warn = exports.error = void 0;
7
7
  const node_fetch_1 = __importDefault(require("node-fetch"));
8
+ const SwppRules_1 = require("./SwppRules");
8
9
  const logger = require('hexo-log').default({
9
10
  debug: false,
10
11
  silent: false
11
12
  });
13
+ function error(type, message) {
14
+ logger.error(`[SWPP ${type}] ${message}`);
15
+ }
16
+ exports.error = error;
17
+ function warn(type, message) {
18
+ logger.warn(`[SWPP ${type}] ${message}`);
19
+ }
20
+ exports.warn = warn;
12
21
  let ejectData = undefined;
13
22
  /**
14
23
  * 获取 eject values
24
+ *
25
+ * + **执行该函数前必须调用过 [loadRules]**
26
+ *
15
27
  * @param framework 框架对象
16
- * @param rules swpp rules 对象
17
28
  */
18
- function calcEjectValues(framework, rules) {
29
+ function calcEjectValues(framework) {
30
+ const rules = (0, SwppRules_1.readRules)();
19
31
  if (!('ejectValues' in rules))
20
32
  return;
21
33
  // noinspection JSUnresolvedReference
22
- const eject = rules.ejectValues(framework, rules);
34
+ const eject = rules.ejectValues?.(framework, rules);
23
35
  const nodeEject = {};
24
36
  let ejectStr = '';
25
37
  for (let key in eject) {
@@ -43,7 +55,12 @@ function calcEjectValues(framework, rules) {
43
55
  };
44
56
  }
45
57
  exports.calcEjectValues = calcEjectValues;
46
- /** 读取最近的已计算的 eject 数据 */
58
+ /**
59
+ * 读取最近的已计算的 eject 数据
60
+ *
61
+ * + **执行该函数前必须调用过 [loadRules]**
62
+ * + **执行该函数前必须调用过 [calcEjectValues]**
63
+ */
47
64
  function readEjectData() {
48
65
  if (!ejectData)
49
66
  throw 'eject data 尚未初始化';
@@ -85,8 +102,9 @@ function getSource(obj, typeChecker = undefined, whiteList = undefined, isTop =
85
102
  if (str.length === 0)
86
103
  return '';
87
104
  if (isTop && whiteList && ['cacheList', 'modifyRequest'].includes(key)) {
88
- str = str.replace(/\(\s*(.*?)\s*,\s*\$eject\s*\)/g, "$1")
89
- .replaceAll(/\$eject\.(\w+)/g, (_, match) => `eject${match[0].toUpperCase()}${match.substring(1)}`);
105
+ str = str
106
+ .replace(/\(\s*(.*?)\s*,\s*\$eject\s*\)/g, "$1") // 去掉箭头函数参数表中的 $eject
107
+ .replaceAll(/\$eject\.(\w+)/g, (_, match) => `eject${match[0].toUpperCase()}${match.substring(1)}`); // 将函数体中的 $eject.xxx 替换为 ejectXxx
90
108
  }
91
109
  return isTop ? `let ${key} = ${str}` : `${key}: ${str}`;
92
110
  })
@@ -112,9 +130,14 @@ function getSource(obj, typeChecker = undefined, whiteList = undefined, isTop =
112
130
  }
113
131
  }
114
132
  exports.getSource = getSource;
115
- /** 拉取文件 */
116
- async function fetchFile(config, link) {
117
- const url = replaceDevRequest(config, link);
133
+ /**
134
+ * 拉取文件
135
+ *
136
+ * **调用该函数前必须调用过 [loadRules]**
137
+ */
138
+ async function fetchFile(link) {
139
+ const config = (0, SwppRules_1.readRules)().config;
140
+ const url = replaceDevRequest(link);
118
141
  const opts = {
119
142
  headers: {
120
143
  referer: 'kmar-swpp',
@@ -141,12 +164,17 @@ async function fetchFile(config, link) {
141
164
  }
142
165
  }
143
166
  exports.fetchFile = fetchFile;
144
- function replaceDevRequest(config, link) {
145
- if (typeof config.external === 'boolean')
146
- return link;
147
- return config.external.replacer(link);
167
+ /**
168
+ * 替换编译期的 URL(CDN 竞速)
169
+ *
170
+ * **调用该函数前必须调用过 [loadRules]**
171
+ */
172
+ function replaceDevRequest(link) {
173
+ const config = (0, SwppRules_1.readRules)().config;
174
+ return config.external?.replacer(link) ?? link;
148
175
  }
149
176
  exports.replaceDevRequest = replaceDevRequest;
177
+ /** 通过 CDN 竞速的方式拉取文件 */
150
178
  async function fetchSpeed(list) {
151
179
  const controllers = new Array(list.length);
152
180
  const result = await Promise.any(list.map((it, index) => (0, node_fetch_1.default)(it, {
package/package.json CHANGED
@@ -1,22 +1,37 @@
1
- {
2
- "name": "swpp-backends",
3
- "version": "0.0.1-alpha.0",
4
- "main": "dist/index.js",
5
- "typings": "types/index.d.ts",
6
- "scripts": {
7
- "build": "tsc"
8
- },
9
- "devDependencies": {
10
- "@types/css": "^0.0.33",
11
- "@types/fast-html-parser": "^1.0.2",
12
- "@types/node": "^20.4.5",
13
- "gulp": "^4.0.2",
14
- "typescript": "^5.1.6"
15
- },
16
- "dependencies": {
17
- "css": "^3.0.0",
18
- "fast-html-parser": "^1.0.1",
19
- "hexo-log": "^4.1.0",
20
- "node-fetch": "^3.3.2"
21
- }
1
+ {
2
+ "name": "swpp-backends",
3
+ "version": "0.0.2-alpha",
4
+ "main": "dist/index.js",
5
+ "typings": "types/index.d.ts",
6
+ "description": "Generate a powerful ServiceWorker for your website.",
7
+ "author": "kmar",
8
+ "license": "AGPL-3.0",
9
+ "files": [
10
+ "dist",
11
+ "types"
12
+ ],
13
+ "devDependencies": {
14
+ "@types/css": "^0.0.33",
15
+ "@types/fast-html-parser": "^1.0.2",
16
+ "@types/node": "^20.4.5",
17
+ "gulp": "^4.0.2",
18
+ "typescript": "^5.1.6"
19
+ },
20
+ "dependencies": {
21
+ "@types/node-fetch": "^2.6.4",
22
+ "css": "^3.0.0",
23
+ "fast-html-parser": "^1.0.1",
24
+ "hexo-log": "^4.1.0",
25
+ "node-fetch": "^2.6.12"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+ssh://git@github.com/EmptyDreams/swpp-backends.git"
30
+ },
31
+ "homepage": "https://github.com/EmptyDreams/swpp-backends",
32
+ "keywords": [
33
+ "ServiceWorker",
34
+ "sw"
35
+ ],
36
+ "scripts": {}
22
37
  }
@@ -1,125 +1,125 @@
1
- /** Service Worker Plus Plus 的配置项 */
2
- export interface SwppConfig {
3
- serviceWorker?: ServiceWorkerConfig,
4
- register?: RegisterConfig,
5
- dom?: DomConfig,
6
- json?: VersionJsonConfig,
7
- external?: ExternalMonitorConfig
8
- }
9
-
10
- /** ServiceWorker 有关的配置 */
11
- export interface ServiceWorkerConfig {
12
- /** 逃生门 */
13
- escape: number,
14
- /** 缓存库名称 */
15
- cacheName: string,
16
- /** 是否启用调试 */
17
- debug: boolean
18
- }
19
-
20
- /** ServiceWorker 注册有关的配置 */
21
- export interface RegisterConfig {
22
- /** 注册成功后执行的代码 */
23
- onsuccess?: VoidFunction,
24
- /** 注册失败后执行的代码 */
25
- onerror: VoidFunction
26
- /**
27
- * 生成注册 ServiceWorker 的 HTML 代码片段
28
- * @param root 网页根目录的 URL
29
- * @param framework 框架对象
30
- * @param pluginConfig swpp 插件配置项
31
- */
32
- builder: (root: string, framework: any, pluginConfig: SwppConfig) => string
33
- }
34
-
35
- /** 与 DOM 端有关的配置 */
36
- export interface DomConfig {
37
- /** 缓存更新成功后触发的操作 */
38
- onsuccess: VoidFunction
39
- }
40
-
41
- /** 与版本文件相关的配置项 */
42
- export interface VersionJsonConfig {
43
- /** 更新缓存时允许更新的最大 HTML 数量 */
44
- maxHtml: number,
45
- /** update.json 文件的字符数量限制 */
46
- charLimit: number,
47
- /** 是否合并指定项目 */
48
- merge: string[],
49
- /** 生成 cacheList.json 时忽略的文件 */
50
- exclude: {
51
- localhost: RegExp[],
52
- other: RegExp[]
53
- }
54
- }
55
-
56
- /** 外部文件更新监听 */
57
- export interface ExternalMonitorConfig {
58
- /** 拉取网络文件的超时时间 */
59
- timeout: number,
60
- /** 匹配 JS 代码中的 URL */
61
- js: ({ head: string, tail: string } | ((jsCode: string) => string[]))[],
62
- /** 链接不变内容就不变的 URL */
63
- stable: RegExp[],
64
- /** 构建过程中将原始 URL 映射为新的 URL */
65
- replacer: (srcUrl: string) => string[] | string
66
- }
67
-
68
- /** Service Worker Plus Plus 的配置项模板 */
69
- export interface SwppConfigTemplate {
70
- /** 有关 ServiceWorker 的配置 */
71
- serviceWorker?: boolean | {
72
- /** 逃生门 */
73
- escape?: number,
74
- /** 缓存库名称 */
75
- cacheName?: string,
76
- /** 是否启用调试 */
77
- debug?: boolean
78
- },
79
- /** 与 ServiceWorker 注册有关的配置 */
80
- register: boolean | {
81
- /** 注册成功后执行的代码 */
82
- onsuccess?: VoidFunction,
83
- /** 注册失败后执行的代码 */
84
- onerror?: VoidFunction,
85
- /**
86
- * 生成注册 ServiceWorker HTML 代码片段
87
- * @param root 网页根目录的 URL
88
- * @param framework 框架对象
89
- * @param pluginConfig swpp 插件配置项
90
- */
91
- builder?: ((root: string, framework: any, pluginConfig: SwppConfig) => string) | undefined
92
- },
93
- /** 与 DOM 端有关的配置 */
94
- dom?: boolean | {
95
- /** 缓存更新成功后触发的操作 */
96
- onsuccess?: VoidFunction
97
- },
98
- /** 与版本文件相关的配置项 */
99
- json?: boolean | {
100
- /** 更新缓存时允许更新的最大 HTML 数量 */
101
- maxHtml?: number,
102
- /** update.json 文件的字符数量限制 */
103
- charLimit?: number,
104
- /** 是否合并指定项目 */
105
- merge?: string[],
106
- /** 生成 cacheList.json 时忽略的文件 */
107
- exclude?: {
108
- /** 当前网站的 URL */
109
- localhost?: RegExp[],
110
- /** 其它网站的 URL */
111
- other?: RegExp[]
112
- }
113
- },
114
- /** 外部文件更新监听 */
115
- external?: boolean | {
116
- /** 拉取网络文件的超时时间 */
117
- timeout?: number,
118
- /** 匹配 JS 代码中的 URL */
119
- js?: ({ head: string, tail: string } | ((jsCode: string) => string[]))[],
120
- /** 链接不变内容就不变的 URL */
121
- stable?: RegExp[],
122
- /** 构建过程中将原始 URL 映射为新的 URL */
123
- replacer?: (srcUrl: string) => string[] | string
124
- }
125
- }
1
+ /** Service Worker Plus Plus 的配置项 */
2
+ export interface SwppConfig {
3
+ serviceWorker?: ServiceWorkerConfig;
4
+ register?: RegisterConfig;
5
+ dom?: DomConfig;
6
+ json?: VersionJsonConfig;
7
+ external?: ExternalMonitorConfig;
8
+ }
9
+ /** 与 ServiceWorker 有关的配置 */
10
+ export interface ServiceWorkerConfig {
11
+ /** 逃生门 */
12
+ escape: number;
13
+ /** 缓存库名称 */
14
+ cacheName: string;
15
+ /** 是否启用调试 */
16
+ debug: boolean;
17
+ }
18
+ /** 与 ServiceWorker 注册有关的配置 */
19
+ export interface RegisterConfig {
20
+ /** 注册成功后执行的代码 */
21
+ onsuccess?: VoidFunction;
22
+ /** 注册失败后执行的代码 */
23
+ onerror: VoidFunction;
24
+ /**
25
+ * 生成注册 ServiceWorker 的 HTML 代码片段
26
+ * @param root 网页根目录的 URL
27
+ * @param framework 框架对象
28
+ * @param pluginConfig swpp 插件配置项
29
+ */
30
+ builder: (root: string, framework: any, pluginConfig: SwppConfig) => string;
31
+ }
32
+ /** DOM 端有关的配置 */
33
+ export interface DomConfig {
34
+ /** 缓存更新成功后触发的操作 */
35
+ onsuccess: VoidFunction;
36
+ }
37
+ /** 与版本文件相关的配置项 */
38
+ export interface VersionJsonConfig {
39
+ /** 更新缓存时允许更新的最大 HTML 数量 */
40
+ maxHtml: number;
41
+ /** update.json 文件的字符数量限制 */
42
+ charLimit: number;
43
+ /** 是否合并指定项目 */
44
+ merge: string[];
45
+ /** 生成 cacheList.json 时忽略的文件 */
46
+ exclude: {
47
+ localhost: RegExp[];
48
+ other: RegExp[];
49
+ };
50
+ }
51
+ /** 外部文件更新监听 */
52
+ export interface ExternalMonitorConfig {
53
+ /** 拉取网络文件的超时时间 */
54
+ timeout: number;
55
+ /** 匹配 JS 代码中的 URL */
56
+ js: ({
57
+ head: string;
58
+ tail: string;
59
+ } | ((jsCode: string) => string[]))[];
60
+ /** 链接不变内容就不变的 URL */
61
+ stable: RegExp[];
62
+ /** 构建过程中将原始 URL 映射为新的 URL */
63
+ replacer: (srcUrl: string) => string[] | string;
64
+ }
65
+ /** Service Worker Plus Plus 的配置项模板 */
66
+ export interface SwppConfigTemplate {
67
+ /** 有关 ServiceWorker 的配置 */
68
+ serviceWorker?: boolean | {
69
+ /** 逃生门 */
70
+ escape?: number;
71
+ /** 缓存库名称 */
72
+ cacheName?: string;
73
+ /** 是否启用调试 */
74
+ debug?: boolean;
75
+ };
76
+ /** ServiceWorker 注册有关的配置 */
77
+ register: boolean | {
78
+ /** 注册成功后执行的代码 */
79
+ onsuccess?: VoidFunction;
80
+ /** 注册失败后执行的代码 */
81
+ onerror?: VoidFunction;
82
+ /**
83
+ * 生成注册 ServiceWorker 的 HTML 代码片段
84
+ * @param root 网页根目录的 URL
85
+ * @param framework 框架对象
86
+ * @param pluginConfig swpp 插件配置项
87
+ */
88
+ builder?: ((root: string, framework: any, pluginConfig: SwppConfig) => string) | undefined;
89
+ };
90
+ /** 与 DOM 端有关的配置 */
91
+ dom?: boolean | {
92
+ /** 缓存更新成功后触发的操作 */
93
+ onsuccess?: VoidFunction;
94
+ };
95
+ /** 与版本文件相关的配置项 */
96
+ json?: boolean | {
97
+ /** 更新缓存时允许更新的最大 HTML 数量 */
98
+ maxHtml?: number;
99
+ /** update.json 文件的字符数量限制 */
100
+ charLimit?: number;
101
+ /** 是否合并指定项目 */
102
+ merge?: string[];
103
+ /** 生成 cacheList.json 时忽略的文件 */
104
+ exclude?: {
105
+ /** 当前网站的 URL */
106
+ localhost?: RegExp[];
107
+ /** 其它网站的 URL */
108
+ other?: RegExp[];
109
+ };
110
+ };
111
+ /** 外部文件更新监听 */
112
+ external?: boolean | {
113
+ /** 拉取网络文件的超时时间 */
114
+ timeout?: number;
115
+ /** 匹配 JS 代码中的 URL */
116
+ js?: ({
117
+ head: string;
118
+ tail: string;
119
+ } | ((jsCode: string) => string[]))[];
120
+ /** 链接不变内容就不变的 URL */
121
+ stable?: RegExp[];
122
+ /** 构建过程中将原始 URL 映射为新的 URL */
123
+ replacer?: (srcUrl: string) => string[] | string;
124
+ };
125
+ }
@@ -0,0 +1,50 @@
1
+ import { AnalyzerResult } from './VersionAnalyzer';
2
+ /** 提交修改 */
3
+ export declare function submitChange(...change: ChangeExpression[]): void;
4
+ /**
5
+ * 加载版本文件
6
+ *
7
+ * + **调用该函数前必须调用过 [loadRules]**
8
+ */
9
+ export declare function loadUpdateJson(url: string): Promise<UpdateJson | null>;
10
+ /**
11
+ * 读取最后一次加载的版本文件
12
+ *
13
+ * + **调用该函数前必须调用过 [loadRules]**
14
+ * + **调用该函数前必须调用过 [loadUpdateJson]**
15
+ */
16
+ export declare function readUpdateJson(): UpdateJson | null;
17
+ /**
18
+ * 构建新的 update json
19
+ *
20
+ * + **执行该函数前必须调用过 [loadRules]**
21
+ * + **调用该函数前必须调用过 [loadCacheJson]**
22
+ * + **执行该函数前必须调用过 [buildVersionJson]**
23
+ * + **执行该函数前必须调用过 [calcEjectValues]**
24
+ *
25
+ * @param root 网站根路径(包括网络协议)
26
+ * @param dif 网站文件变化
27
+ */
28
+ export declare function buildNewInfo(root: string, dif: AnalyzerResult): UpdateJson;
29
+ /**
30
+ * 获取 URL 的缩写形式
31
+ *
32
+ * + **执行该函数前必须调用过 [loadRules]**
33
+ * + **调用该函数前必须调用过 [loadCacheJson]**
34
+ * + **执行该函数前必须调用过 [buildVersionJson]**
35
+ * + **执行该函数前必须调用过 [calcEjectValues]**
36
+ */
37
+ export declare function getShorthand(url: string, offset?: number): string;
38
+ export interface UpdateJson {
39
+ global: number;
40
+ info: UpdateVersionInfo[];
41
+ }
42
+ export interface UpdateVersionInfo {
43
+ version: number;
44
+ change?: ChangeExpression[];
45
+ }
46
+ export interface ChangeExpression {
47
+ flag: FlagStr;
48
+ value?: string | string[];
49
+ }
50
+ export type FlagStr = 'html' | 'end' | 'begin' | 'str' | 'reg';
@@ -0,0 +1,29 @@
1
+ import { VersionJson } from './FileAnalyzer';
2
+ /**
3
+ * 分析两个版本信息的不同
4
+ *
5
+ * + **执行该函数前必须调用过 [loadRules]**
6
+ * + **调用该函数前必须调用过 [loadCacheJson]**
7
+ *
8
+ * @param version 新的版本信息
9
+ */
10
+ export declare function analyzer(version: VersionJson): AnalyzerResult;
11
+ /** 手动添加一个要刷新的 URL */
12
+ export declare function refreshUrl(url: string): void;
13
+ export interface AnalyzerResult {
14
+ /** 是否强制刷新所有缓存 */
15
+ force: boolean;
16
+ /** 被删除的 URL */
17
+ deleted: string[];
18
+ /** 内容变化的 URL */
19
+ variational: string[];
20
+ /** 手动刷新的 URL */
21
+ refresh: string[];
22
+ /** 因 stable 规则变化导致数据变动的 URL */
23
+ rules: {
24
+ /** 新规则将其识别为 stable */
25
+ add: string[];
26
+ /** 新规则将其识别为非 stable */
27
+ remove: string[];
28
+ };
29
+ }