swpp-backends 3.0.0-alpha.0 → 3.0.0-alpha.100

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.
Files changed (52) hide show
  1. package/dist/index.d.ts +19 -0
  2. package/dist/index.js +49 -3
  3. package/{types → dist}/swpp/FileParser.d.ts +11 -7
  4. package/dist/swpp/FileParser.js +29 -15
  5. package/dist/swpp/JsonBuilder.js +3 -2
  6. package/dist/swpp/NetworkFileHandler.js +3 -3
  7. package/{types → dist}/swpp/ResourcesScanner.d.ts +12 -4
  8. package/dist/swpp/ResourcesScanner.js +136 -27
  9. package/{types → dist}/swpp/SwCompiler.d.ts +12 -8
  10. package/dist/swpp/SwCompiler.js +17 -6
  11. package/{types/swpp/config/ConfigLoader.d.ts → dist/swpp/config/ConfigCluster.d.ts} +72 -29
  12. package/dist/swpp/config/ConfigCluster.js +86 -0
  13. package/dist/swpp/config/ConfigLoader.d.ts +56 -0
  14. package/dist/swpp/config/ConfigLoader.js +61 -59
  15. package/dist/swpp/database/CompilationEnv.d.ts +56 -0
  16. package/dist/swpp/database/CompilationEnv.js +98 -41
  17. package/{types → dist}/swpp/database/CrossDepCode.d.ts +7 -0
  18. package/dist/swpp/database/CrossDepCode.js +16 -0
  19. package/dist/swpp/database/DomCode.d.ts +32 -0
  20. package/dist/swpp/database/DomCode.js +114 -0
  21. package/{types → dist}/swpp/database/KeyValueDatabase.d.ts +21 -13
  22. package/dist/swpp/database/KeyValueDatabase.js +52 -19
  23. package/{types → dist}/swpp/database/RuntimeCoreCode.d.ts +5 -3
  24. package/dist/swpp/database/RuntimeCoreCode.js +6 -6
  25. package/{types → dist}/swpp/database/RuntimeDepCode.d.ts +1 -5
  26. package/dist/swpp/database/RuntimeDepCode.js +0 -11
  27. package/{types → dist}/swpp/database/RuntimeEventCode.d.ts +1 -1
  28. package/dist/swpp/database/RuntimeEventCode.js +20 -4
  29. package/{types → dist}/swpp/untils.d.ts +31 -14
  30. package/dist/swpp/untils.js +59 -32
  31. package/package.json +4 -4
  32. package/dist/resources/sw-dom.js +0 -45
  33. package/dist/resources/sw-fetch.js +0 -76
  34. package/types/DomBuilder.d.ts +0 -6
  35. package/types/FileAnalyzer.d.ts +0 -96
  36. package/types/ServiceWorkerBuilder.d.ts +0 -7
  37. package/types/SwppConfig.d.ts +0 -139
  38. package/types/SwppRules.d.ts +0 -117
  39. package/types/UpdateJsonBuilder.d.ts +0 -44
  40. package/types/Utils.d.ts +0 -43
  41. package/types/Variant.d.ts +0 -58
  42. package/types/VersionAnalyzer.d.ts +0 -27
  43. package/types/browser/ServiceWorkerRuntimeTypes.d.ts +0 -18
  44. package/types/index.d.ts +0 -2
  45. package/types/swpp/RuntimeEnv.d.ts +0 -39
  46. package/types/swpp/SwCodeInject.d.ts +0 -17
  47. package/types/swpp/database/CompilationEnv.d.ts +0 -33
  48. package/types/swpp/database/RuntimeEnv.d.ts +0 -5
  49. /package/{types → dist}/swpp/JsonBuilder.d.ts +0 -0
  50. /package/{types → dist}/swpp/NetworkFileHandler.d.ts +0 -0
  51. /package/{types → dist}/swpp/database/CrossEnv.d.ts +0 -0
  52. /package/{types → dist}/swpp/database/RuntimeKeyValueDatabase.d.ts +0 -0
@@ -0,0 +1,19 @@
1
+ /** 版本号 */
2
+ export declare const swppVersion: any;
3
+ export { utils, RuntimeException } from './swpp/untils';
4
+ export { ResourcesScanner, FileUpdateTracker, } from './swpp/ResourcesScanner';
5
+ export { JsonBuilder, UpdateJson, UpdateChangeExp, TrackerHeaderDiff } from './swpp/JsonBuilder';
6
+ export { FileParserRegistry, FileParser, FileMark } from './swpp/FileParser';
7
+ export { SwCompiler, CompilationData, RuntimeData, BrowserVersion } from './swpp/SwCompiler';
8
+ export { NetworkFileHandler, FiniteConcurrencyFetcher } from './swpp/NetworkFileHandler';
9
+ export { ConfigLoader } from './swpp/config/ConfigLoader';
10
+ export { KeyValueDatabase } from './swpp/database/KeyValueDatabase';
11
+ export { RuntimeKeyValueDatabase } from './swpp/database/RuntimeKeyValueDatabase';
12
+ export { RuntimeEventCode } from './swpp/database/RuntimeEventCode';
13
+ export { RuntimeCoreCode } from './swpp/database/RuntimeCoreCode';
14
+ export { RuntimeDepCode } from './swpp/database/RuntimeDepCode';
15
+ export { CrossEnv } from './swpp/database/CrossEnv';
16
+ export { CrossDepCode } from './swpp/database/CrossDepCode';
17
+ export { CompilationEnv, AllowNotFoundEnum } from './swpp/database/CompilationEnv';
18
+ export { DomCode } from './swpp/database/DomCode';
19
+ export { defineIndivisibleConfig, defineConfig, defineRuntimeEvent, defineDomConfig, defineRuntimeCore, defineCrossDep, defineRuntimeDep, defineCrossEnv, defineCompilationEnv } from './swpp/config/ConfigCluster';
package/dist/index.js CHANGED
@@ -1,7 +1,53 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.version = void 0;
3
+ exports.defineCompilationEnv = exports.defineCrossEnv = exports.defineRuntimeDep = exports.defineCrossDep = exports.defineRuntimeCore = exports.defineDomConfig = exports.defineRuntimeEvent = exports.defineConfig = exports.defineIndivisibleConfig = exports.DomCode = exports.AllowNotFoundEnum = exports.CompilationEnv = exports.CrossDepCode = exports.CrossEnv = exports.RuntimeDepCode = exports.RuntimeCoreCode = exports.RuntimeEventCode = exports.RuntimeKeyValueDatabase = exports.KeyValueDatabase = exports.ConfigLoader = exports.FiniteConcurrencyFetcher = exports.RuntimeData = exports.CompilationData = exports.SwCompiler = exports.FileParserRegistry = exports.JsonBuilder = exports.FileUpdateTracker = exports.ResourcesScanner = exports.utils = exports.swppVersion = void 0;
4
4
  const untils_1 = require("./swpp/untils");
5
5
  /** 版本号 */
6
- exports.version = require('../package.json').version;
7
- untils_1.utils.printInfo('INDEX', `欢迎使用 swpp@${exports.version}`);
6
+ exports.swppVersion = require('../package.json').version;
7
+ var untils_2 = require("./swpp/untils");
8
+ Object.defineProperty(exports, "utils", { enumerable: true, get: function () { return untils_2.utils; } });
9
+ var ResourcesScanner_1 = require("./swpp/ResourcesScanner");
10
+ Object.defineProperty(exports, "ResourcesScanner", { enumerable: true, get: function () { return ResourcesScanner_1.ResourcesScanner; } });
11
+ Object.defineProperty(exports, "FileUpdateTracker", { enumerable: true, get: function () { return ResourcesScanner_1.FileUpdateTracker; } });
12
+ var JsonBuilder_1 = require("./swpp/JsonBuilder");
13
+ Object.defineProperty(exports, "JsonBuilder", { enumerable: true, get: function () { return JsonBuilder_1.JsonBuilder; } });
14
+ var FileParser_1 = require("./swpp/FileParser");
15
+ Object.defineProperty(exports, "FileParserRegistry", { enumerable: true, get: function () { return FileParser_1.FileParserRegistry; } });
16
+ var SwCompiler_1 = require("./swpp/SwCompiler");
17
+ Object.defineProperty(exports, "SwCompiler", { enumerable: true, get: function () { return SwCompiler_1.SwCompiler; } });
18
+ Object.defineProperty(exports, "CompilationData", { enumerable: true, get: function () { return SwCompiler_1.CompilationData; } });
19
+ Object.defineProperty(exports, "RuntimeData", { enumerable: true, get: function () { return SwCompiler_1.RuntimeData; } });
20
+ var NetworkFileHandler_1 = require("./swpp/NetworkFileHandler");
21
+ Object.defineProperty(exports, "FiniteConcurrencyFetcher", { enumerable: true, get: function () { return NetworkFileHandler_1.FiniteConcurrencyFetcher; } });
22
+ var ConfigLoader_1 = require("./swpp/config/ConfigLoader");
23
+ Object.defineProperty(exports, "ConfigLoader", { enumerable: true, get: function () { return ConfigLoader_1.ConfigLoader; } });
24
+ var KeyValueDatabase_1 = require("./swpp/database/KeyValueDatabase");
25
+ Object.defineProperty(exports, "KeyValueDatabase", { enumerable: true, get: function () { return KeyValueDatabase_1.KeyValueDatabase; } });
26
+ var RuntimeKeyValueDatabase_1 = require("./swpp/database/RuntimeKeyValueDatabase");
27
+ Object.defineProperty(exports, "RuntimeKeyValueDatabase", { enumerable: true, get: function () { return RuntimeKeyValueDatabase_1.RuntimeKeyValueDatabase; } });
28
+ var RuntimeEventCode_1 = require("./swpp/database/RuntimeEventCode");
29
+ Object.defineProperty(exports, "RuntimeEventCode", { enumerable: true, get: function () { return RuntimeEventCode_1.RuntimeEventCode; } });
30
+ var RuntimeCoreCode_1 = require("./swpp/database/RuntimeCoreCode");
31
+ Object.defineProperty(exports, "RuntimeCoreCode", { enumerable: true, get: function () { return RuntimeCoreCode_1.RuntimeCoreCode; } });
32
+ var RuntimeDepCode_1 = require("./swpp/database/RuntimeDepCode");
33
+ Object.defineProperty(exports, "RuntimeDepCode", { enumerable: true, get: function () { return RuntimeDepCode_1.RuntimeDepCode; } });
34
+ var CrossEnv_1 = require("./swpp/database/CrossEnv");
35
+ Object.defineProperty(exports, "CrossEnv", { enumerable: true, get: function () { return CrossEnv_1.CrossEnv; } });
36
+ var CrossDepCode_1 = require("./swpp/database/CrossDepCode");
37
+ Object.defineProperty(exports, "CrossDepCode", { enumerable: true, get: function () { return CrossDepCode_1.CrossDepCode; } });
38
+ var CompilationEnv_1 = require("./swpp/database/CompilationEnv");
39
+ Object.defineProperty(exports, "CompilationEnv", { enumerable: true, get: function () { return CompilationEnv_1.CompilationEnv; } });
40
+ Object.defineProperty(exports, "AllowNotFoundEnum", { enumerable: true, get: function () { return CompilationEnv_1.AllowNotFoundEnum; } });
41
+ var DomCode_1 = require("./swpp/database/DomCode");
42
+ Object.defineProperty(exports, "DomCode", { enumerable: true, get: function () { return DomCode_1.DomCode; } });
43
+ untils_1.utils.printInfo('INDEX', `欢迎使用 swpp@${exports.swppVersion}`);
44
+ var ConfigCluster_1 = require("./swpp/config/ConfigCluster");
45
+ Object.defineProperty(exports, "defineIndivisibleConfig", { enumerable: true, get: function () { return ConfigCluster_1.defineIndivisibleConfig; } });
46
+ Object.defineProperty(exports, "defineConfig", { enumerable: true, get: function () { return ConfigCluster_1.defineConfig; } });
47
+ Object.defineProperty(exports, "defineRuntimeEvent", { enumerable: true, get: function () { return ConfigCluster_1.defineRuntimeEvent; } });
48
+ Object.defineProperty(exports, "defineDomConfig", { enumerable: true, get: function () { return ConfigCluster_1.defineDomConfig; } });
49
+ Object.defineProperty(exports, "defineRuntimeCore", { enumerable: true, get: function () { return ConfigCluster_1.defineRuntimeCore; } });
50
+ Object.defineProperty(exports, "defineCrossDep", { enumerable: true, get: function () { return ConfigCluster_1.defineCrossDep; } });
51
+ Object.defineProperty(exports, "defineRuntimeDep", { enumerable: true, get: function () { return ConfigCluster_1.defineRuntimeDep; } });
52
+ Object.defineProperty(exports, "defineCrossEnv", { enumerable: true, get: function () { return ConfigCluster_1.defineCrossEnv; } });
53
+ Object.defineProperty(exports, "defineCompilationEnv", { enumerable: true, get: function () { return ConfigCluster_1.defineCompilationEnv; } });
@@ -1,17 +1,17 @@
1
- /// <reference types="node" />
2
1
  import * as crypto from 'node:crypto';
2
+ import { FileUpdateTracker } from './ResourcesScanner';
3
3
  import { CompilationData } from './SwCompiler';
4
4
  export declare class FileParserRegistry {
5
5
  private compilation;
6
+ private oldTracker?;
6
7
  private map;
7
- constructor(compilation: CompilationData, obj?: {
8
- [key: string]: FileParser<any>;
9
- });
8
+ constructor(compilation: CompilationData, oldTracker?: FileUpdateTracker | undefined);
9
+ /** 注册一种处理器 */
10
10
  registry(type: string, parser: FileParser<any>): void;
11
11
  /** 判断是否支持指定类型 */
12
12
  containsType(type: string): boolean;
13
13
  /** 解析本地文件 */
14
- parserLocalFile(path: string): Promise<Set<string>>;
14
+ parserLocalFile(path: string, cb?: (content: crypto.BinaryLike) => void, force?: boolean): Promise<Set<string>>;
15
15
  /** 解析网络文件 */
16
16
  parserNetworkFile(response: Response, callback?: (content: crypto.BinaryLike) => Promise<any> | any): Promise<Set<string>>;
17
17
  /**
@@ -59,8 +59,12 @@ export interface FileParser<T extends crypto.BinaryLike> {
59
59
  export interface FileMark {
60
60
  /** URL */
61
61
  file: string;
62
- /** 文件标识符 */
63
- mark: string;
62
+ /**
63
+ * 文件标识符或子文件列表
64
+ *
65
+ * 如果链接为稳定链接,则为子文件列表,否则为文件标识符
66
+ */
67
+ mark: string | Set<string>;
64
68
  /** URL 列表 */
65
69
  urls: Set<string>;
66
70
  }
@@ -3,17 +3,17 @@ 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.buildFileParser = exports.FileParserRegistry = void 0;
6
+ exports.FileParserRegistry = void 0;
7
+ exports.buildFileParser = buildFileParser;
7
8
  const path_1 = __importDefault(require("path"));
8
9
  const untils_1 = require("./untils");
9
10
  class FileParserRegistry {
10
- constructor(compilation, obj = {}) {
11
+ constructor(compilation, oldTracker) {
11
12
  this.compilation = compilation;
13
+ this.oldTracker = oldTracker;
12
14
  this.map = new Map();
13
- for (let key in obj) {
14
- this.map.set(key, obj[key]);
15
- }
16
15
  }
16
+ /** 注册一种处理器 */
17
17
  registry(type, parser) {
18
18
  this.map.set(type, parser);
19
19
  }
@@ -22,20 +22,33 @@ class FileParserRegistry {
22
22
  return this.map.has(type);
23
23
  }
24
24
  /** 解析本地文件 */
25
- async parserLocalFile(path) {
26
- const parser = this.map.get(path_1.default.extname(path));
27
- if (!parser)
25
+ async parserLocalFile(path, cb, force) {
26
+ const parser = this.map.get(path_1.default.extname(path).substring(1));
27
+ if (!parser) {
28
+ if (force && cb) {
29
+ const reader = this.compilation.compilationEnv.read('readLocalFile');
30
+ const content = await reader(path);
31
+ cb(content);
32
+ }
28
33
  return new Set();
34
+ }
29
35
  const content = await parser.readFromLocal(this.compilation, path);
36
+ cb?.(content);
30
37
  return await parser.extractUrls(this.compilation, content);
31
38
  }
32
39
  /** 解析网络文件 */
33
40
  async parserNetworkFile(response, callback) {
34
- const fileHandler = this.compilation.compilationEnv.read('FETCH_NETWORK_FILE');
41
+ const fileHandler = this.compilation.compilationEnv.read('NETWORK_FILE_FETCHER');
35
42
  const contentType = fileHandler.getUrlContentType(response.url, response);
36
43
  const parser = this.map.get(contentType);
37
- if (!parser)
44
+ if (!parser) {
45
+ if (callback) {
46
+ const blob = await response.blob();
47
+ const array = await blob.stream().getReader().read();
48
+ callback(array.value);
49
+ }
38
50
  return new Set();
51
+ }
39
52
  const content = await parser.readFromNetwork(this.compilation, response);
40
53
  if (callback)
41
54
  await callback(content);
@@ -47,11 +60,13 @@ class FileParserRegistry {
47
60
  * @param isCached 该链接指向的资源是否需要缓存
48
61
  */
49
62
  async parserUrlFile(url, isCached) {
50
- const fileHandler = this.compilation.compilationEnv.read('FETCH_NETWORK_FILE');
63
+ const fileHandler = this.compilation.compilationEnv.read('NETWORK_FILE_FETCHER');
51
64
  const contentType = fileHandler.getUrlContentType(url);
52
65
  if (!contentType && !isCached)
53
66
  return { file: url, mark: '', urls: new Set() };
54
67
  const parser = this.map.get(contentType);
68
+ if (!parser && !isCached)
69
+ return { file: url, mark: '', urls: new Set() };
55
70
  if (parser?.calcUrl) {
56
71
  const result = await parser.calcUrl(url);
57
72
  if (result)
@@ -60,13 +75,13 @@ class FileParserRegistry {
60
75
  ...result
61
76
  };
62
77
  }
63
- const fetcher = this.compilation.compilationEnv.read('FETCH_NETWORK_FILE');
78
+ const fetcher = this.compilation.compilationEnv.read('NETWORK_FILE_FETCHER');
64
79
  const urls = new Set();
65
80
  let mark = '';
66
81
  await fetcher.fetch(url)
67
- .then(response => this.parserNetworkFile(response, content => {
82
+ .then(response => this.parserNetworkFile(response, isCached ? content => {
68
83
  mark = untils_1.utils.calcHash(content);
69
- }))
84
+ } : undefined))
70
85
  .then(urls => urls.forEach(it => urls.add(it)));
71
86
  return { file: url, mark, urls };
72
87
  }
@@ -82,4 +97,3 @@ exports.FileParserRegistry = FileParserRegistry;
82
97
  function buildFileParser(parser) {
83
98
  return parser;
84
99
  }
85
- exports.buildFileParser = buildFileParser;
@@ -15,13 +15,14 @@ class JsonBuilder {
15
15
  putHeader(key, value) {
16
16
  this.headers.set(key, value);
17
17
  }
18
+ // noinspection JSUnusedGlobalSymbols
18
19
  async buildJson() {
19
- const json = await this.compilation.compilationEnv.read('VERSION_FILE')();
20
+ const json = await this.compilation.compilationEnv.read('SWPP_JSON_FILE').fetchVersionFile();
20
21
  if (json.info.length == 0) {
21
22
  json.info.push({ version: 1 });
22
23
  return json;
23
24
  }
24
- const newChange = createUpdateChangeExps(this.urls, this.map.values());
25
+ const newChange = createUpdateChangeExps(this.urls, this.map.keys());
25
26
  json.info.unshift({
26
27
  version: json.info[0].version + 1,
27
28
  change: [newChange]
@@ -11,7 +11,7 @@ class FiniteConcurrencyFetcher {
11
11
  this.fetchingCount = 0;
12
12
  this.waitList = [];
13
13
  this.limit = 100;
14
- this.referer = 'swpp-backends';
14
+ this.referer = 'https://swpp.example.com';
15
15
  this.userAgent = 'swpp-backends';
16
16
  this.headers = {};
17
17
  }
@@ -52,7 +52,7 @@ class FiniteConcurrencyFetcher {
52
52
  contentType = 'html';
53
53
  }
54
54
  else {
55
- contentType = path_1.default.extname(url);
55
+ contentType = path_1.default.extname(url).substring(1);
56
56
  }
57
57
  if (!contentType) {
58
58
  if (response)
@@ -60,7 +60,7 @@ class FiniteConcurrencyFetcher {
60
60
  if (contentType.startsWith('text/'))
61
61
  contentType = contentType.substring(5);
62
62
  if (contentType === 'javascript')
63
- contentType = 'script';
63
+ contentType = 'js';
64
64
  }
65
65
  return contentType;
66
66
  }
@@ -5,7 +5,8 @@ import { CompilationData } from './SwCompiler';
5
5
  */
6
6
  export declare class ResourcesScanner {
7
7
  private compilation;
8
- constructor(compilation: CompilationData);
8
+ private oldTracker?;
9
+ constructor(compilation: CompilationData, oldTracker?: FileUpdateTracker | undefined);
9
10
  /** 扫描指定目录下的所有文件 */
10
11
  scanLocalFile(path: string): Promise<FileUpdateTracker>;
11
12
  /** 扫描网络文件 */
@@ -24,9 +25,14 @@ export declare class FileUpdateTracker {
24
25
  protected allUrl: Set<string>;
25
26
  constructor(compilation: CompilationData);
26
27
  /** 更新一个文件的标识符 */
27
- update(uri: string, value: string): void;
28
+ update(uri: string, value: string | Set<string> | string[]): void;
29
+ /**
30
+ * 同步指定的稳定资源(同步时会连同同步其连接的稳定资源)
31
+ * @return 直接或间接连接的一些需要扫描的资源
32
+ */
33
+ syncStable(uri: URL, value: string[], oldTracker: FileUpdateTracker): string[];
28
34
  /** 读取一个文件的标识符 */
29
- get(uri: string): string | undefined;
35
+ get(uri: string): string | string[] | undefined;
30
36
  /** 设置一个 header */
31
37
  putHeader(key: string, value: any): void;
32
38
  /** 读取一个 header */
@@ -43,7 +49,7 @@ export declare class FileUpdateTracker {
43
49
  * + 在新旧 tracker 中都存在且唯一标识符发生变化
44
50
  * + 在新 tracker 中不存在且在旧 tracker 中存在
45
51
  */
46
- diff(oldTracker: FileUpdateTracker): JsonBuilder;
52
+ diff(): Promise<JsonBuilder>;
47
53
  /**
48
54
  * 将数据序列化为 JSON
49
55
  *
@@ -64,4 +70,6 @@ export declare class FileUpdateTracker {
64
70
  json(): string;
65
71
  /** 解序列化数据 */
66
72
  static unJson(compilation: CompilationData, jsonStr: string): FileUpdateTracker;
73
+ /** 从网络拉取并解析 tracker */
74
+ static parserJsonFromNetwork(compilation: CompilationData): Promise<FileUpdateTracker>;
67
75
  }
@@ -30,41 +30,46 @@ exports.FileUpdateTracker = exports.ResourcesScanner = void 0;
30
30
  const fs_1 = __importDefault(require("fs"));
31
31
  const crypto = __importStar(require("node:crypto"));
32
32
  const path_1 = __importDefault(require("path"));
33
+ const CompilationEnv_1 = require("./database/CompilationEnv");
33
34
  const JsonBuilder_1 = require("./JsonBuilder");
34
35
  const untils_1 = require("./untils");
35
36
  /**
36
37
  * 资源文件扫描器
37
38
  */
38
39
  class ResourcesScanner {
39
- constructor(compilation) {
40
+ constructor(compilation, oldTracker) {
40
41
  this.compilation = compilation;
42
+ this.oldTracker = oldTracker;
41
43
  }
44
+ // noinspection JSUnusedGlobalSymbols
42
45
  /** 扫描指定目录下的所有文件 */
43
46
  async scanLocalFile(path) {
44
47
  const matchCacheRule = this.compilation.crossDep.read('matchCacheRule');
45
48
  const register = this.compilation.compilationEnv.read('FILE_PARSER');
49
+ const jsonInfo = this.compilation.compilationEnv.read('SWPP_JSON_FILE');
50
+ const excludes = [
51
+ path_1.default.posix.join(path, jsonInfo.swppPath, jsonInfo.versionPath),
52
+ path_1.default.posix.join(path, jsonInfo.swppPath, jsonInfo.trackerPath),
53
+ path_1.default.posix.join(path, this.compilation.compilationEnv.read('SERVICE_WORKER') + '.js')
54
+ ];
46
55
  const urls = new Set();
47
56
  const tracker = new FileUpdateTracker(this.compilation);
48
57
  await traverseDirectory(path, async (file) => {
49
- const stream = fs_1.default.createReadStream(file);
50
- const hash = crypto.createHash('md5');
51
- stream.on('data', data => hash.update(data));
58
+ if (excludes.includes(file))
59
+ return;
52
60
  const localUrl = tracker.normalizeUri(file.substring(path.length));
53
- if (matchCacheRule.runOnNode(localUrl)) {
61
+ const isCached = !!matchCacheRule.runOnNode(localUrl);
62
+ if (isCached) {
54
63
  tracker.addUrl(localUrl.href);
55
64
  }
56
- const type = path_1.default.extname(file);
57
- if (register.containsType(type)) {
58
- const set = await register.parserLocalFile(file);
59
- set.forEach(it => urls.add(it));
60
- }
61
- await new Promise((resolve, reject) => {
62
- stream.on('end', () => {
63
- tracker.update(file, hash.digest('hex'));
64
- resolve();
65
- });
66
- stream.on('error', err => reject(err));
67
- });
65
+ const set = await register.parserLocalFile(file, content => {
66
+ if (isCached) {
67
+ const hash = crypto.createHash('md5');
68
+ hash.update(content);
69
+ tracker.update(localUrl.pathname, hash.digest('hex'));
70
+ }
71
+ }, isCached);
72
+ set.forEach(it => urls.add(it));
68
73
  });
69
74
  await this.scanNetworkFile(tracker, urls);
70
75
  return tracker;
@@ -73,6 +78,7 @@ class ResourcesScanner {
73
78
  async scanNetworkFile(tracker, urls, record = new Set()) {
74
79
  const matchCacheRule = this.compilation.crossDep.read('matchCacheRule');
75
80
  const registry = this.compilation.compilationEnv.read('FILE_PARSER');
81
+ const isStable = this.compilation.compilationEnv.read('isStable');
76
82
  const appendedUrls = new Set();
77
83
  const taskList = new Array(urls.size);
78
84
  let i = 0;
@@ -85,9 +91,19 @@ class ResourcesScanner {
85
91
  if (isCached) {
86
92
  tracker.addUrl(normalizeUri.href);
87
93
  }
94
+ if (isStable(normalizeUri)) {
95
+ const oldValue = this.oldTracker?.get?.(normalizeUri.href);
96
+ if (Array.isArray(oldValue)) {
97
+ const list = tracker.syncStable(normalizeUri, oldValue, this.oldTracker);
98
+ list.forEach(it => appendedUrls.add(it));
99
+ continue;
100
+ }
101
+ }
88
102
  taskList[i++] = registry.parserUrlFile(normalizeUri.href, !!isCached)
89
103
  .then(value => {
90
- tracker.update(value.file, value.mark);
104
+ if (isCached) {
105
+ tracker.update(value.file, value.mark);
106
+ }
91
107
  value.urls.forEach(it => appendedUrls.add(it));
92
108
  }).catch(err => untils_1.utils.printError('SCAN NETWORK FILE', err));
93
109
  }
@@ -110,7 +126,7 @@ async function traverseDirectory(dir, callback) {
110
126
  if (err)
111
127
  reject(err);
112
128
  else {
113
- Promise.all(files.map(it => traverseDirectory(path_1.default.join(dir, it), callback))).then(() => resolve());
129
+ Promise.all(files.map(it => traverseDirectory(path_1.default.posix.join(dir, it), callback))).then(() => resolve());
114
130
  }
115
131
  });
116
132
  });
@@ -134,11 +150,51 @@ class FileUpdateTracker {
134
150
  }
135
151
  /** 更新一个文件的标识符 */
136
152
  update(uri, value) {
137
- this.map.set(uri, value);
153
+ if (typeof value == 'string') {
154
+ if (value.startsWith('['))
155
+ throw {
156
+ code: untils_1.exceptionNames.invalidValue,
157
+ message: `插入数据("${value}")时,不应当以方括号开头`
158
+ };
159
+ this.map.set(uri, value);
160
+ }
161
+ else if (Array.isArray(value)) {
162
+ this.map.set(uri, JSON.stringify(value));
163
+ }
164
+ else {
165
+ this.map.set(uri, JSON.stringify(Array.from(value)));
166
+ }
167
+ }
168
+ /**
169
+ * 同步指定的稳定资源(同步时会连同同步其连接的稳定资源)
170
+ * @return 直接或间接连接的一些需要扫描的资源
171
+ */
172
+ syncStable(uri, value, oldTracker) {
173
+ const isStable = this.compilation.compilationEnv.read('isStable');
174
+ this.update(uri.href, value);
175
+ this.addUrl(uri.href);
176
+ const result = [];
177
+ for (let item of value) {
178
+ this.addUrl(item);
179
+ const itemUrl = new URL(item);
180
+ if (isStable(itemUrl)) {
181
+ const oldValue = oldTracker.get(item);
182
+ if (Array.isArray(oldValue)) {
183
+ const son = this.syncStable(itemUrl, oldValue, oldTracker);
184
+ result.push(...son);
185
+ continue;
186
+ }
187
+ }
188
+ result.push(item);
189
+ }
190
+ return result;
138
191
  }
139
192
  /** 读取一个文件的标识符 */
140
193
  get(uri) {
141
- return this.map.get(this.normalizeUri(uri).href);
194
+ const value = this.map.get(this.normalizeUri(uri).href);
195
+ if (!value)
196
+ return;
197
+ return value.startsWith('[') ? JSON.parse(value) : value;
142
198
  }
143
199
  /** 设置一个 header */
144
200
  putHeader(key, value) {
@@ -153,12 +209,15 @@ class FileUpdateTracker {
153
209
  if (uri.startsWith('http:'))
154
210
  uri = `https:${uri.substring(5)}`;
155
211
  const domain = this.compilation.compilationEnv.read('DOMAIN_HOST');
156
- return new URL(uri, `https://${domain}`);
212
+ const url = new URL(uri, `https://${domain}`);
213
+ const normalizer = this.compilation.crossDep.read('normalizeUrl');
214
+ return new URL(normalizer.runOnNode(url.href));
157
215
  }
158
216
  /** 添加一个 URL */
159
217
  addUrl(url) {
160
218
  this.allUrl.add(url);
161
219
  }
220
+ // noinspection JSUnusedGlobalSymbols
162
221
  /**
163
222
  * 判断两个 tracker 的差异
164
223
  *
@@ -167,15 +226,17 @@ class FileUpdateTracker {
167
226
  * + 在新旧 tracker 中都存在且唯一标识符发生变化
168
227
  * + 在新 tracker 中不存在且在旧 tracker 中存在
169
228
  */
170
- diff(oldTracker) {
229
+ async diff() {
230
+ const host = this.compilation.compilationEnv.read('DOMAIN_HOST');
171
231
  const diff = new JsonBuilder_1.JsonBuilder(this.compilation, this.allUrl);
232
+ const oldTracker = await this.compilation.compilationEnv.read('SWPP_JSON_FILE').fetchTrackerFile(this.compilation);
172
233
  oldTracker.map.forEach((value, key) => {
173
234
  if (this.map.has(key)) {
174
235
  if (this.get(key) !== value)
175
- diff.update(key, value);
236
+ diff.update(untils_1.utils.splicingUrl(host, key).href, value);
176
237
  }
177
238
  else {
178
- diff.update(key, value);
239
+ diff.update(untils_1.utils.splicingUrl(host, key).href, value);
179
240
  }
180
241
  });
181
242
  this.headers.forEach((value, key) => {
@@ -186,6 +247,7 @@ class FileUpdateTracker {
186
247
  });
187
248
  return diff;
188
249
  }
250
+ // noinspection JSUnusedGlobalSymbols
189
251
  /**
190
252
  * 将数据序列化为 JSON
191
253
  *
@@ -206,12 +268,16 @@ class FileUpdateTracker {
206
268
  json() {
207
269
  const result = {
208
270
  version: 4,
209
- tracker: {}
271
+ tracker: {},
272
+ headers: {}
210
273
  };
211
274
  this.map.forEach((value, key) => {
212
275
  result.tracker[key] = value;
213
276
  });
214
- return JSON.stringify(result.tracker);
277
+ this.headers.forEach((value, key) => {
278
+ result.headers[key] = value;
279
+ });
280
+ return JSON.stringify(result);
215
281
  }
216
282
  /** 解序列化数据 */
217
283
  static unJson(compilation, jsonStr) {
@@ -242,5 +308,48 @@ class FileUpdateTracker {
242
308
  }
243
309
  return tracker;
244
310
  }
311
+ // noinspection JSUnusedGlobalSymbols
312
+ /** 从网络拉取并解析 tracker */
313
+ static async parserJsonFromNetwork(compilation) {
314
+ const domain = compilation.compilationEnv.read('DOMAIN_HOST');
315
+ const jsonInfo = compilation.compilationEnv.read('SWPP_JSON_FILE');
316
+ const url = untils_1.utils.splicingUrl(domain, jsonInfo.swppPath, jsonInfo.trackerPath);
317
+ const fetcher = compilation.compilationEnv.read('NETWORK_FILE_FETCHER');
318
+ const isNotFound = compilation.compilationEnv.read('isNotFound');
319
+ const notFoundLevel = compilation.compilationEnv.read('ALLOW_NOT_FOUND');
320
+ let error;
321
+ const result = await (async () => {
322
+ try {
323
+ const response = await fetcher.fetch(url);
324
+ if (isNotFound.response(response)) {
325
+ if (notFoundLevel == CompilationEnv_1.AllowNotFoundEnum.REJECT_ALL) {
326
+ error = {
327
+ code: untils_1.exceptionNames.notFound,
328
+ message: `拉取 ${url} 时出现 404 错误`
329
+ };
330
+ return;
331
+ }
332
+ untils_1.utils.printWarning('SCANNER', '拉取 tracker 时服务器返回了 404,如果是第一次携带 swpp v3 构建网站请忽视这条信息');
333
+ return new FileUpdateTracker(compilation);
334
+ }
335
+ const text = await response.text();
336
+ return FileUpdateTracker.unJson(compilation, text);
337
+ }
338
+ catch (e) {
339
+ if (isNotFound.error(e) && notFoundLevel == CompilationEnv_1.AllowNotFoundEnum.ALLOW_ALL) {
340
+ untils_1.utils.printWarning('SCANNER', '拉取 tracker 时 DNS 解析失败,如果是第一次携带 swpp v3 构建网站且网站暂时无法解析请忽视这条信息');
341
+ return new FileUpdateTracker(compilation);
342
+ }
343
+ untils_1.utils.printError('SCANNER', e);
344
+ throw {
345
+ code: untils_1.exceptionNames.error,
346
+ message: `拉取或解析历史 Tracker 时出现错误`
347
+ };
348
+ }
349
+ })();
350
+ if (result)
351
+ return result;
352
+ throw error;
353
+ }
245
354
  }
246
355
  exports.FileUpdateTracker = FileUpdateTracker;
@@ -1,5 +1,6 @@
1
1
  import { CompilationEnv } from './database/CompilationEnv';
2
2
  import { CrossDepCode } from './database/CrossDepCode';
3
+ import { DomCode } from './database/DomCode';
3
4
  import { RuntimeCoreCode } from './database/RuntimeCoreCode';
4
5
  import { RuntimeDepCode } from './database/RuntimeDepCode';
5
6
  import { CrossEnv } from './database/CrossEnv';
@@ -15,24 +16,27 @@ export declare class SwCompiler {
15
16
  /** 运行时数据 */
16
17
  export declare class RuntimeData {
17
18
  /** 控制插入顺序 */
18
- readonly insertOrder: (Exclude<keyof RuntimeData, 'insertOrder'> | string)[];
19
+ readonly insertOrder: (Exclude<keyof RuntimeData, 'insertOrder' | 'domConfig'> | string)[];
19
20
  /** 运行时环境变量 */
20
- readonly crossEnv: CrossEnv;
21
+ crossEnv: CrossEnv;
21
22
  /** 运行时工具函数 */
22
- readonly runtimeDep: RuntimeDepCode;
23
+ runtimeDep: RuntimeDepCode;
23
24
  /** 运行时核心功能函数 */
24
- readonly runtimeCore: RuntimeCoreCode;
25
+ runtimeCore: RuntimeCoreCode;
25
26
  /** 运行时事件注册 */
26
- readonly runtimeEvent: RuntimeEventCode;
27
+ runtimeEvent: RuntimeEventCode;
27
28
  /** 运行时/编译时工具函数 */
28
- readonly crossDep: CrossDepCode;
29
+ crossDep: CrossDepCode;
30
+ /** DOM 相关设置 */
31
+ domConfig: DomCode;
32
+ constructor(compilationData: CompilationData);
29
33
  getDatabase(key: string): RuntimeKeyValueDatabase<any, {}>;
30
34
  }
31
35
  /** 编译时数据 */
32
- export interface CompilationData {
33
- compilationEnv: CompilationEnv;
36
+ export declare class CompilationData {
34
37
  crossEnv: CrossEnv;
35
38
  crossDep: CrossDepCode;
39
+ compilationEnv: CompilationEnv;
36
40
  }
37
41
  /** 版本号信息 */
38
42
  export interface BrowserVersion {