@vlian/framework 1.2.25 → 1.2.37

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 (213) hide show
  1. package/dist/analytics.umd.js +208 -2395
  2. package/dist/analytics.umd.js.map +1 -1
  3. package/dist/core/error/ErrorHandler.cjs.map +1 -1
  4. package/dist/core/error/ErrorHandler.d.ts +1 -1
  5. package/dist/core/error/ErrorHandler.js.map +1 -1
  6. package/dist/core/router/monitoring/RouterMonitoring.cjs +1 -1
  7. package/dist/core/router/monitoring/RouterMonitoring.cjs.map +1 -1
  8. package/dist/core/router/monitoring/RouterMonitoring.js +1 -1
  9. package/dist/core/router/monitoring/RouterMonitoring.js.map +1 -1
  10. package/dist/core/router/utils/adapters/react-router/transform.cjs +4 -0
  11. package/dist/core/router/utils/adapters/react-router/transform.cjs.map +1 -1
  12. package/dist/core/router/utils/adapters/react-router/transform.js +4 -0
  13. package/dist/core/router/utils/adapters/react-router/transform.js.map +1 -1
  14. package/dist/core/startup/initializeServices.cjs +1 -1
  15. package/dist/core/startup/initializeServices.cjs.map +1 -1
  16. package/dist/core/startup/initializeServices.d.ts +1 -1
  17. package/dist/core/startup/initializeServices.js +1 -1
  18. package/dist/core/startup/initializeServices.js.map +1 -1
  19. package/dist/core/startup/performanceTracker.cjs.map +1 -1
  20. package/dist/core/startup/performanceTracker.d.ts +1 -1
  21. package/dist/core/startup/performanceTracker.js.map +1 -1
  22. package/dist/core/startup/renderApp.cjs +1 -1
  23. package/dist/core/startup/renderApp.cjs.map +1 -1
  24. package/dist/core/startup/renderApp.d.ts +1 -1
  25. package/dist/core/startup/renderApp.js +1 -1
  26. package/dist/core/startup/renderApp.js.map +1 -1
  27. package/dist/core/startup/startApp.cjs +2 -2
  28. package/dist/core/startup/startApp.cjs.map +1 -1
  29. package/dist/core/startup/startApp.js +3 -3
  30. package/dist/core/startup/startApp.js.map +1 -1
  31. package/dist/core/types.d.ts +1 -1
  32. package/dist/core/types.js.map +1 -1
  33. package/dist/index.cjs +15 -2
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.ts +6 -4
  36. package/dist/index.js +5 -4
  37. package/dist/index.js.map +1 -1
  38. package/dist/index.umd.js +11648 -32616
  39. package/dist/index.umd.js.map +1 -1
  40. package/dist/kernel/constants.cjs +67 -0
  41. package/dist/kernel/constants.cjs.map +1 -0
  42. package/dist/kernel/constants.d.ts +5 -0
  43. package/dist/kernel/constants.js +43 -0
  44. package/dist/kernel/constants.js.map +1 -0
  45. package/dist/kernel/index.cjs +40 -0
  46. package/dist/kernel/index.cjs.map +1 -0
  47. package/dist/kernel/index.d.ts +3 -0
  48. package/dist/kernel/index.js +4 -0
  49. package/dist/kernel/index.js.map +1 -0
  50. package/dist/kernel/kernel.cjs +296 -0
  51. package/dist/kernel/kernel.cjs.map +1 -0
  52. package/dist/kernel/kernel.d.ts +40 -0
  53. package/dist/kernel/kernel.js +272 -0
  54. package/dist/kernel/kernel.js.map +1 -0
  55. package/dist/kernel/manager/cacheManager.cjs +46 -0
  56. package/dist/kernel/manager/cacheManager.cjs.map +1 -0
  57. package/dist/kernel/manager/cacheManager.d.ts +6 -0
  58. package/dist/kernel/manager/cacheManager.js +36 -0
  59. package/dist/kernel/manager/cacheManager.js.map +1 -0
  60. package/dist/kernel/manager/i18nManager.cjs +68 -0
  61. package/dist/kernel/manager/i18nManager.cjs.map +1 -0
  62. package/dist/kernel/manager/i18nManager.d.ts +8 -0
  63. package/dist/kernel/manager/i18nManager.js +58 -0
  64. package/dist/kernel/manager/i18nManager.js.map +1 -0
  65. package/dist/kernel/manager/index.cjs +30 -0
  66. package/dist/kernel/manager/index.cjs.map +1 -0
  67. package/dist/kernel/manager/index.d.ts +4 -0
  68. package/dist/kernel/manager/index.js +6 -0
  69. package/dist/kernel/manager/index.js.map +1 -0
  70. package/dist/kernel/manager/loggerManager.cjs +70 -0
  71. package/dist/kernel/manager/loggerManager.cjs.map +1 -0
  72. package/dist/kernel/manager/loggerManager.d.ts +14 -0
  73. package/dist/kernel/manager/loggerManager.js +60 -0
  74. package/dist/kernel/manager/loggerManager.js.map +1 -0
  75. package/dist/kernel/manager/persistence.cjs +93 -0
  76. package/dist/kernel/manager/persistence.cjs.map +1 -0
  77. package/dist/kernel/manager/persistence.d.ts +3 -0
  78. package/dist/kernel/manager/persistence.js +75 -0
  79. package/dist/kernel/manager/persistence.js.map +1 -0
  80. package/dist/kernel/manager/themeManager.cjs +85 -0
  81. package/dist/kernel/manager/themeManager.cjs.map +1 -0
  82. package/dist/kernel/manager/themeManager.d.ts +9 -0
  83. package/dist/kernel/manager/themeManager.js +75 -0
  84. package/dist/kernel/manager/themeManager.js.map +1 -0
  85. package/dist/kernel/types.cjs +6 -0
  86. package/dist/kernel/types.cjs.map +1 -0
  87. package/dist/kernel/types.d.ts +72 -0
  88. package/dist/kernel/types.js +3 -0
  89. package/dist/kernel/types.js.map +1 -0
  90. package/dist/request/adapter.d.ts +1 -0
  91. package/dist/request/core.d.ts +1 -0
  92. package/dist/request/index.d.ts +1 -42
  93. package/dist/request/plugin/csrfPlugin.d.ts +2 -2
  94. package/dist/request/plugin/queue.d.ts +2 -2
  95. package/dist/request/plugin.d.ts +1 -0
  96. package/dist/request/runtime.d.ts +1 -0
  97. package/dist/request/types.d.ts +1 -394
  98. package/dist/request/utils.d.ts +1 -0
  99. package/dist/state.umd.js +1 -1
  100. package/dist/utils/csrf.cjs +13 -152
  101. package/dist/utils/csrf.cjs.map +1 -1
  102. package/dist/utils/csrf.d.ts +1 -72
  103. package/dist/utils/csrf.js +1 -142
  104. package/dist/utils/csrf.js.map +1 -1
  105. package/dist/utils/errors/ErrorCodes.cjs +6 -76
  106. package/dist/utils/errors/ErrorCodes.cjs.map +1 -1
  107. package/dist/utils/errors/ErrorCodes.d.ts +1 -45
  108. package/dist/utils/errors/ErrorCodes.js +1 -84
  109. package/dist/utils/errors/ErrorCodes.js.map +1 -1
  110. package/dist/utils/errors.cjs +15 -344
  111. package/dist/utils/errors.cjs.map +1 -1
  112. package/dist/utils/errors.d.ts +1 -183
  113. package/dist/utils/errors.js +1 -352
  114. package/dist/utils/errors.js.map +1 -1
  115. package/dist/utils/logger.cjs +5 -374
  116. package/dist/utils/logger.cjs.map +1 -1
  117. package/dist/utils/logger.d.ts +2 -189
  118. package/dist/utils/logger.js +1 -379
  119. package/dist/utils/logger.js.map +1 -1
  120. package/dist/utils/logger.types.cjs +3 -12
  121. package/dist/utils/logger.types.cjs.map +1 -1
  122. package/dist/utils/logger.types.d.ts +2 -57
  123. package/dist/utils/logger.types.js +1 -10
  124. package/dist/utils/logger.types.js.map +1 -1
  125. package/dist/utils/monitoring.cjs +11 -302
  126. package/dist/utils/monitoring.cjs.map +1 -1
  127. package/dist/utils/monitoring.d.ts +1 -163
  128. package/dist/utils/monitoring.js +1 -294
  129. package/dist/utils/monitoring.js.map +1 -1
  130. package/dist/utils/performance.cjs +5 -352
  131. package/dist/utils/performance.cjs.map +1 -1
  132. package/dist/utils/performance.d.ts +2 -246
  133. package/dist/utils/performance.js +1 -354
  134. package/dist/utils/performance.js.map +1 -1
  135. package/dist/utils/resourceLoader.cjs +5 -303
  136. package/dist/utils/resourceLoader.cjs.map +1 -1
  137. package/dist/utils/resourceLoader.d.ts +2 -130
  138. package/dist/utils/resourceLoader.js +1 -305
  139. package/dist/utils/resourceLoader.js.map +1 -1
  140. package/dist/utils/runtimeSecurity.cjs +2 -140
  141. package/dist/utils/runtimeSecurity.cjs.map +1 -1
  142. package/dist/utils/runtimeSecurity.d.ts +2 -104
  143. package/dist/utils/runtimeSecurity.js +1 -141
  144. package/dist/utils/runtimeSecurity.js.map +1 -1
  145. package/dist/utils/security.cjs +3 -314
  146. package/dist/utils/security.cjs.map +1 -1
  147. package/dist/utils/security.d.ts +2 -80
  148. package/dist/utils/security.js +1 -311
  149. package/dist/utils/security.js.map +1 -1
  150. package/dist/utils/traceId.cjs +10 -111
  151. package/dist/utils/traceId.cjs.map +1 -1
  152. package/dist/utils/traceId.d.ts +1 -63
  153. package/dist/utils/traceId.js +1 -116
  154. package/dist/utils/traceId.js.map +1 -1
  155. package/dist/utils/validation.cjs +3 -173
  156. package/dist/utils/validation.cjs.map +1 -1
  157. package/dist/utils/validation.d.ts +2 -110
  158. package/dist/utils/validation.js +1 -175
  159. package/dist/utils/validation.js.map +1 -1
  160. package/package.json +15 -24
  161. package/dist/lazy/index.cjs +0 -104
  162. package/dist/lazy/index.cjs.map +0 -1
  163. package/dist/lazy/index.d.ts +0 -19
  164. package/dist/lazy/index.js +0 -24
  165. package/dist/lazy/index.js.map +0 -1
  166. package/dist/request/adapter/RequestAdapter.cjs +0 -78
  167. package/dist/request/adapter/RequestAdapter.cjs.map +0 -1
  168. package/dist/request/adapter/axiosAdapter.cjs +0 -164
  169. package/dist/request/adapter/axiosAdapter.cjs.map +0 -1
  170. package/dist/request/adapter/fetchAdapter.cjs +0 -134
  171. package/dist/request/adapter/fetchAdapter.cjs.map +0 -1
  172. package/dist/request/adapter/index.cjs +0 -80
  173. package/dist/request/adapter/index.cjs.map +0 -1
  174. package/dist/request/adapter/kyAdapter.cjs +0 -191
  175. package/dist/request/adapter/kyAdapter.cjs.map +0 -1
  176. package/dist/request/adapter/undiciAdapter.cjs +0 -213
  177. package/dist/request/adapter/undiciAdapter.cjs.map +0 -1
  178. package/dist/request/core/RequestClient.cjs +0 -558
  179. package/dist/request/core/RequestClient.cjs.map +0 -1
  180. package/dist/request/core/index.cjs +0 -15
  181. package/dist/request/core/index.cjs.map +0 -1
  182. package/dist/request/index.cjs +0 -149
  183. package/dist/request/index.cjs.map +0 -1
  184. package/dist/request/plugin/RequestPlugin.cjs +0 -218
  185. package/dist/request/plugin/RequestPlugin.cjs.map +0 -1
  186. package/dist/request/plugin/cache.cjs +0 -269
  187. package/dist/request/plugin/cache.cjs.map +0 -1
  188. package/dist/request/plugin/csrfPlugin.cjs +0 -40
  189. package/dist/request/plugin/csrfPlugin.cjs.map +0 -1
  190. package/dist/request/plugin/index.cjs +0 -53
  191. package/dist/request/plugin/index.cjs.map +0 -1
  192. package/dist/request/plugin/monitoring.cjs +0 -216
  193. package/dist/request/plugin/monitoring.cjs.map +0 -1
  194. package/dist/request/plugin/queue.cjs +0 -140
  195. package/dist/request/plugin/queue.cjs.map +0 -1
  196. package/dist/request/plugin/retry.cjs +0 -98
  197. package/dist/request/plugin/retry.cjs.map +0 -1
  198. package/dist/request/plugin/validation.cjs +0 -121
  199. package/dist/request/plugin/validation.cjs.map +0 -1
  200. package/dist/request/runtime/RequestContext.cjs +0 -77
  201. package/dist/request/runtime/RequestContext.cjs.map +0 -1
  202. package/dist/request/runtime/index.cjs +0 -32
  203. package/dist/request/runtime/index.cjs.map +0 -1
  204. package/dist/request/types.cjs +0 -112
  205. package/dist/request/types.cjs.map +0 -1
  206. package/dist/request/utils/RequestQueueManager.cjs +0 -168
  207. package/dist/request/utils/RequestQueueManager.cjs.map +0 -1
  208. package/dist/request/utils/dependencyCheck.cjs +0 -237
  209. package/dist/request/utils/dependencyCheck.cjs.map +0 -1
  210. package/dist/request/utils/index.cjs +0 -30
  211. package/dist/request/utils/index.cjs.map +0 -1
  212. package/dist/request.umd.js +0 -5392
  213. package/dist/request.umd.js.map +0 -1
@@ -1,307 +1,3 @@
1
- /**
2
- * 资源类型
3
- */ function _define_property(obj, key, value) {
4
- if (key in obj) {
5
- Object.defineProperty(obj, key, {
6
- value: value,
7
- enumerable: true,
8
- configurable: true,
9
- writable: true
10
- });
11
- } else {
12
- obj[key] = value;
13
- }
14
- return obj;
15
- }
16
- /**
17
- * 资源优先级
18
- */ export var ResourcePriority = /*#__PURE__*/ function(ResourcePriority) {
19
- /**
20
- * 高优先级 - 关键资源
21
- */ ResourcePriority["HIGH"] = "high";
22
- /**
23
- * 中优先级 - 重要资源
24
- */ ResourcePriority["MEDIUM"] = "medium";
25
- /**
26
- * 低优先级 - 非关键资源
27
- */ ResourcePriority["LOW"] = "low";
28
- /**
29
- * 自动 - 由浏览器决定
30
- */ ResourcePriority["AUTO"] = "auto";
31
- return ResourcePriority;
32
- }({});
33
- /**
34
- * 资源加载器类
35
- */ export class ResourceLoader {
36
- /**
37
- * 获取动态并发数(基于网络状况)
38
- */ getDynamicConcurrency() {
39
- if (typeof navigator === 'undefined' || !('connection' in navigator)) {
40
- return this.maxConcurrentLoads;
41
- }
42
- const connection = navigator.connection;
43
- if (!connection) {
44
- return this.maxConcurrentLoads;
45
- }
46
- // 根据网络类型调整并发数
47
- const effectiveType = connection.effectiveType;
48
- switch(effectiveType){
49
- case 'slow-2g':
50
- case '2g':
51
- return 2;
52
- case '3g':
53
- return 4;
54
- case '4g':
55
- default:
56
- return this.maxConcurrentLoads;
57
- }
58
- }
59
- /**
60
- * 加载脚本
61
- */ async loadScript(options) {
62
- const { url, ...rest } = options;
63
- return this.loadResource({
64
- ...rest,
65
- type: 'script',
66
- url
67
- });
68
- }
69
- /**
70
- * 加载样式
71
- */ async loadStyle(options) {
72
- const { url, ...rest } = options;
73
- return this.loadResource({
74
- ...rest,
75
- type: 'style',
76
- url
77
- });
78
- }
79
- /**
80
- * 预加载资源
81
- */ preload(options) {
82
- if (typeof document === 'undefined') {
83
- return;
84
- }
85
- const link = document.createElement('link');
86
- link.rel = 'preload';
87
- link.href = options.url;
88
- link.as = this.getResourceAs(options.type);
89
- if (options.priority) {
90
- link.setAttribute('fetchpriority', options.priority);
91
- }
92
- if (options.crossOrigin) {
93
- link.crossOrigin = options.crossOrigin;
94
- }
95
- if (options.integrity) {
96
- link.integrity = options.integrity;
97
- }
98
- document.head.appendChild(link);
99
- }
100
- /**
101
- * 预取资源
102
- */ prefetch(options) {
103
- if (typeof document === 'undefined') {
104
- return;
105
- }
106
- const link = document.createElement('link');
107
- link.rel = 'prefetch';
108
- link.href = options.url;
109
- if (options.priority) {
110
- link.setAttribute('fetchpriority', options.priority);
111
- }
112
- document.head.appendChild(link);
113
- }
114
- /**
115
- * 加载资源
116
- */ async loadResource(options) {
117
- const { url, type, onLoad, onError } = options;
118
- // 如果已经加载过,直接返回
119
- if (this.loadedResources.has(url)) {
120
- onLoad?.();
121
- return;
122
- }
123
- // 如果正在加载,等待加载完成
124
- if (this.loadingResources.has(url)) {
125
- await this.loadingResources.get(url);
126
- onLoad?.();
127
- return;
128
- }
129
- // 创建加载 Promise
130
- const loadPromise = this.doLoadResource({
131
- ...options,
132
- type,
133
- url
134
- });
135
- // 保存加载 Promise
136
- this.loadingResources.set(url, loadPromise);
137
- try {
138
- await loadPromise;
139
- this.loadedResources.add(url);
140
- onLoad?.();
141
- } catch (error) {
142
- const err = error instanceof Error ? error : new Error(String(error));
143
- onError?.(err);
144
- throw err;
145
- } finally{
146
- this.loadingResources.delete(url);
147
- }
148
- }
149
- /**
150
- * 执行资源加载
151
- */ doLoadResource(options) {
152
- return new Promise((resolve, reject)=>{
153
- if (typeof document === 'undefined') {
154
- reject(new Error('资源加载需要在浏览器环境中执行'));
155
- return;
156
- }
157
- const { url, type, async = true, defer, crossOrigin, integrity } = options;
158
- if (type === 'script') {
159
- const script = document.createElement('script');
160
- script.src = url;
161
- script.async = async;
162
- if (defer !== undefined) {
163
- script.defer = defer;
164
- }
165
- if (crossOrigin) {
166
- script.crossOrigin = crossOrigin;
167
- }
168
- if (integrity) {
169
- script.integrity = integrity;
170
- }
171
- script.onload = ()=>resolve();
172
- script.onerror = ()=>reject(new Error(`Failed to load script: ${url}`));
173
- document.head.appendChild(script);
174
- } else if (type === 'style') {
175
- const link = document.createElement('link');
176
- link.rel = 'stylesheet';
177
- link.href = url;
178
- if (crossOrigin) {
179
- link.crossOrigin = crossOrigin;
180
- }
181
- if (integrity) {
182
- link.integrity = integrity;
183
- }
184
- link.onload = ()=>resolve();
185
- link.onerror = ()=>reject(new Error(`Failed to load stylesheet: ${url}`));
186
- document.head.appendChild(link);
187
- } else {
188
- reject(new Error(`Unsupported resource type: ${type}`));
189
- }
190
- });
191
- }
192
- /**
193
- * 获取资源 as 属性值
194
- */ getResourceAs(type) {
195
- const asMap = {
196
- script: 'script',
197
- style: 'style',
198
- image: 'image',
199
- font: 'font',
200
- prefetch: 'fetch',
201
- preload: 'fetch'
202
- };
203
- return asMap[type] || 'fetch';
204
- }
205
- /**
206
- * 使用 requestIdleCallback 加载低优先级资源
207
- */ loadWhenIdle(options, timeout) {
208
- if (typeof requestIdleCallback !== 'undefined') {
209
- requestIdleCallback(()=>{
210
- this.loadResource(options).catch((error)=>{
211
- console.warn('Idle resource load failed:', error);
212
- });
213
- }, {
214
- timeout
215
- });
216
- } else {
217
- // 降级方案:延迟加载
218
- setTimeout(()=>{
219
- this.loadResource(options).catch((error)=>{
220
- console.warn('Delayed resource load failed:', error);
221
- });
222
- }, 1000);
223
- }
224
- }
225
- /**
226
- * 批量加载资源(按优先级)
227
- */ async loadResources(resources) {
228
- // 按优先级排序
229
- const sortedResources = this.sortByPriority(resources);
230
- // 按优先级分组
231
- const highPriority = sortedResources.filter((r)=>r.priority === "high" || !r.priority);
232
- const mediumPriority = sortedResources.filter((r)=>r.priority === "medium");
233
- const lowPriority = sortedResources.filter((r)=>r.priority === "low");
234
- const results = [];
235
- // 先加载高优先级资源(并行,但限制并发数)
236
- if (highPriority.length > 0) {
237
- const highResults = await this.loadResourcesWithConcurrencyLimit(highPriority);
238
- results.push(...highResults);
239
- }
240
- // 然后加载中优先级资源
241
- if (mediumPriority.length > 0) {
242
- const mediumResults = await this.loadResourcesWithConcurrencyLimit(mediumPriority);
243
- results.push(...mediumResults);
244
- }
245
- // 最后加载低优先级资源(使用空闲时间)
246
- if (lowPriority.length > 0) {
247
- // 低优先级资源在空闲时加载
248
- for (const resource of lowPriority){
249
- this.loadWhenIdle(resource);
250
- }
251
- }
252
- return results;
253
- }
254
- /**
255
- * 按优先级排序资源
256
- */ sortByPriority(resources) {
257
- const priorityOrder = {
258
- ["high"]: 0,
259
- ["medium"]: 1,
260
- ["low"]: 2,
261
- ["auto"]: 3
262
- };
263
- return [
264
- ...resources
265
- ].sort((a, b)=>{
266
- const aPriority = priorityOrder[a.priority || "auto"] ?? 3;
267
- const bPriority = priorityOrder[b.priority || "auto"] ?? 3;
268
- return aPriority - bPriority;
269
- });
270
- }
271
- /**
272
- * 限制并发数的资源加载(优化版本)
273
- */ async loadResourcesWithConcurrencyLimit(resources, concurrency) {
274
- const maxConcurrency = concurrency ?? this.getDynamicConcurrency();
275
- const results = [];
276
- const executing = new Set();
277
- for (const resource of resources){
278
- // 如果达到并发限制,等待一个任务完成
279
- if (executing.size >= maxConcurrency) {
280
- await Promise.race(executing);
281
- }
282
- const promise = this.loadResource(resource).finally(()=>{
283
- executing.delete(promise);
284
- });
285
- executing.add(promise);
286
- results.push(promise);
287
- }
288
- // 等待所有任务完成
289
- await Promise.all(results);
290
- return [];
291
- }
292
- /**
293
- * 检查资源是否已加载
294
- */ isLoaded(url) {
295
- return this.loadedResources.has(url);
296
- }
297
- constructor(){
298
- _define_property(this, "loadedResources", new Set());
299
- _define_property(this, "loadingResources", new Map());
300
- _define_property(this, "maxConcurrentLoads", 6); // 最大并发加载数(默认值)
301
- }
302
- }
303
- /**
304
- * 默认资源加载器实例
305
- */ export const resourceLoader = new ResourceLoader();
1
+ export { ResourceLoader, ResourcePriority, resourceLoader } from "@vlian/utils";
306
2
 
307
3
  //# sourceMappingURL=resourceLoader.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/resourceLoader.ts"],"sourcesContent":["/**\n * 资源类型\n */\nexport type ResourceType = 'script' | 'style' | 'image' | 'font' | 'prefetch' | 'preload';\n\n/**\n * 资源优先级\n */\nexport enum ResourcePriority {\n /**\n * 高优先级 - 关键资源\n */\n HIGH = 'high',\n /**\n * 中优先级 - 重要资源\n */\n MEDIUM = 'medium',\n /**\n * 低优先级 - 非关键资源\n */\n LOW = 'low',\n /**\n * 自动 - 由浏览器决定\n */\n AUTO = 'auto',\n}\n\n/**\n * 资源加载选项\n */\nexport interface ResourceLoadOptions {\n /**\n * 资源类型\n */\n type: ResourceType;\n /**\n * 资源 URL\n */\n url: string;\n /**\n * 优先级\n */\n priority?: ResourcePriority;\n /**\n * 是否异步加载\n */\n async?: boolean;\n /**\n * 是否延迟加载\n */\n defer?: boolean;\n /**\n * 跨域设置\n */\n crossOrigin?: 'anonymous' | 'use-credentials';\n /**\n * 完整性校验(SRI)\n */\n integrity?: string;\n /**\n * 加载完成回调\n */\n onLoad?: () => void;\n /**\n * 加载失败回调\n */\n onError?: (error: Error) => void;\n}\n\n/**\n * 资源加载器类\n */\nexport class ResourceLoader {\n private loadedResources: Set<string> = new Set();\n private loadingResources: Map<string, Promise<void>> = new Map();\n private maxConcurrentLoads: number = 6; // 最大并发加载数(默认值)\n\n /**\n * 获取动态并发数(基于网络状况)\n */\n private getDynamicConcurrency(): number {\n if (typeof navigator === 'undefined' || !('connection' in navigator)) {\n return this.maxConcurrentLoads;\n }\n\n const connection = (navigator as any).connection;\n if (!connection) {\n return this.maxConcurrentLoads;\n }\n\n // 根据网络类型调整并发数\n const effectiveType = connection.effectiveType;\n switch (effectiveType) {\n case 'slow-2g':\n case '2g':\n return 2;\n case '3g':\n return 4;\n case '4g':\n default:\n return this.maxConcurrentLoads;\n }\n }\n\n /**\n * 加载脚本\n */\n async loadScript(options: Omit<ResourceLoadOptions, 'type'>): Promise<void> {\n const { url, ...rest } = options;\n return this.loadResource({ ...rest, type: 'script', url });\n }\n\n /**\n * 加载样式\n */\n async loadStyle(options: Omit<ResourceLoadOptions, 'type'>): Promise<void> {\n const { url, ...rest } = options;\n return this.loadResource({ ...rest, type: 'style', url });\n }\n\n /**\n * 预加载资源\n */\n preload(options: ResourceLoadOptions): void {\n if (typeof document === 'undefined') {\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'preload';\n link.href = options.url;\n link.as = this.getResourceAs(options.type);\n\n if (options.priority) {\n link.setAttribute('fetchpriority', options.priority);\n }\n\n if (options.crossOrigin) {\n link.crossOrigin = options.crossOrigin;\n }\n\n if (options.integrity) {\n link.integrity = options.integrity;\n }\n\n document.head.appendChild(link);\n }\n\n /**\n * 预取资源\n */\n prefetch(options: Omit<ResourceLoadOptions, 'type'>): void {\n if (typeof document === 'undefined') {\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'prefetch';\n link.href = options.url;\n\n if (options.priority) {\n link.setAttribute('fetchpriority', options.priority);\n }\n\n document.head.appendChild(link);\n }\n\n /**\n * 加载资源\n */\n async loadResource(options: ResourceLoadOptions): Promise<void> {\n const { url, type, onLoad, onError } = options;\n\n // 如果已经加载过,直接返回\n if (this.loadedResources.has(url)) {\n onLoad?.();\n return;\n }\n\n // 如果正在加载,等待加载完成\n if (this.loadingResources.has(url)) {\n await this.loadingResources.get(url);\n onLoad?.();\n return;\n }\n\n // 创建加载 Promise\n const loadPromise = this.doLoadResource({ ...options, type, url });\n\n // 保存加载 Promise\n this.loadingResources.set(url, loadPromise);\n\n try {\n await loadPromise;\n this.loadedResources.add(url);\n onLoad?.();\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n onError?.(err);\n throw err;\n } finally {\n this.loadingResources.delete(url);\n }\n }\n\n /**\n * 执行资源加载\n */\n private doLoadResource(options: ResourceLoadOptions): Promise<void> {\n return new Promise((resolve, reject) => {\n if (typeof document === 'undefined') {\n reject(new Error('资源加载需要在浏览器环境中执行'));\n return;\n }\n\n const { url, type, async = true, defer, crossOrigin, integrity } = options;\n\n if (type === 'script') {\n const script = document.createElement('script');\n script.src = url;\n script.async = async;\n if (defer !== undefined) {\n script.defer = defer;\n }\n if (crossOrigin) {\n script.crossOrigin = crossOrigin;\n }\n if (integrity) {\n script.integrity = integrity;\n }\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(`Failed to load script: ${url}`));\n document.head.appendChild(script);\n } else if (type === 'style') {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n if (crossOrigin) {\n link.crossOrigin = crossOrigin;\n }\n if (integrity) {\n link.integrity = integrity;\n }\n link.onload = () => resolve();\n link.onerror = () => reject(new Error(`Failed to load stylesheet: ${url}`));\n document.head.appendChild(link);\n } else {\n reject(new Error(`Unsupported resource type: ${type}`));\n }\n });\n }\n\n /**\n * 获取资源 as 属性值\n */\n private getResourceAs(type: ResourceType): string {\n const asMap: Record<ResourceType, string> = {\n script: 'script',\n style: 'style',\n image: 'image',\n font: 'font',\n prefetch: 'fetch',\n preload: 'fetch',\n };\n return asMap[type] || 'fetch';\n }\n\n /**\n * 使用 requestIdleCallback 加载低优先级资源\n */\n loadWhenIdle(options: ResourceLoadOptions, timeout?: number): void {\n if (typeof requestIdleCallback !== 'undefined') {\n requestIdleCallback(\n () => {\n this.loadResource(options).catch((error) => {\n console.warn('Idle resource load failed:', error);\n });\n },\n { timeout }\n );\n } else {\n // 降级方案:延迟加载\n setTimeout(() => {\n this.loadResource(options).catch((error) => {\n console.warn('Delayed resource load failed:', error);\n });\n }, 1000);\n }\n }\n\n /**\n * 批量加载资源(按优先级)\n */\n async loadResources(resources: ResourceLoadOptions[]): Promise<void[]> {\n // 按优先级排序\n const sortedResources = this.sortByPriority(resources);\n \n // 按优先级分组\n const highPriority = sortedResources.filter(r => r.priority === ResourcePriority.HIGH || !r.priority);\n const mediumPriority = sortedResources.filter(r => r.priority === ResourcePriority.MEDIUM);\n const lowPriority = sortedResources.filter(r => r.priority === ResourcePriority.LOW);\n\n const results: void[] = [];\n\n // 先加载高优先级资源(并行,但限制并发数)\n if (highPriority.length > 0) {\n const highResults = await this.loadResourcesWithConcurrencyLimit(highPriority);\n results.push(...highResults);\n }\n\n // 然后加载中优先级资源\n if (mediumPriority.length > 0) {\n const mediumResults = await this.loadResourcesWithConcurrencyLimit(mediumPriority);\n results.push(...mediumResults);\n }\n\n // 最后加载低优先级资源(使用空闲时间)\n if (lowPriority.length > 0) {\n // 低优先级资源在空闲时加载\n for (const resource of lowPriority) {\n this.loadWhenIdle(resource);\n }\n }\n\n return results;\n }\n\n /**\n * 按优先级排序资源\n */\n private sortByPriority(resources: ResourceLoadOptions[]): ResourceLoadOptions[] {\n const priorityOrder = {\n [ResourcePriority.HIGH]: 0,\n [ResourcePriority.MEDIUM]: 1,\n [ResourcePriority.LOW]: 2,\n [ResourcePriority.AUTO]: 3,\n };\n\n return [...resources].sort((a, b) => {\n const aPriority = priorityOrder[a.priority || ResourcePriority.AUTO] ?? 3;\n const bPriority = priorityOrder[b.priority || ResourcePriority.AUTO] ?? 3;\n return aPriority - bPriority;\n });\n }\n\n /**\n * 限制并发数的资源加载(优化版本)\n */\n private async loadResourcesWithConcurrencyLimit(\n resources: ResourceLoadOptions[],\n concurrency?: number\n ): Promise<void[]> {\n const maxConcurrency = concurrency ?? this.getDynamicConcurrency();\n const results: Promise<void>[] = [];\n const executing = new Set<Promise<void>>();\n\n for (const resource of resources) {\n // 如果达到并发限制,等待一个任务完成\n if (executing.size >= maxConcurrency) {\n await Promise.race(executing);\n }\n\n const promise = this.loadResource(resource).finally(() => {\n executing.delete(promise);\n });\n\n executing.add(promise);\n results.push(promise);\n }\n\n // 等待所有任务完成\n await Promise.all(results);\n return [];\n }\n\n /**\n * 检查资源是否已加载\n */\n isLoaded(url: string): boolean {\n return this.loadedResources.has(url);\n }\n}\n\n/**\n * 默认资源加载器实例\n */\nexport const resourceLoader = new ResourceLoader();\n"],"names":["ResourcePriority","ResourceLoader","getDynamicConcurrency","navigator","maxConcurrentLoads","connection","effectiveType","loadScript","options","url","rest","loadResource","type","loadStyle","preload","document","link","createElement","rel","href","as","getResourceAs","priority","setAttribute","crossOrigin","integrity","head","appendChild","prefetch","onLoad","onError","loadedResources","has","loadingResources","get","loadPromise","doLoadResource","set","add","error","err","Error","String","delete","Promise","resolve","reject","async","defer","script","src","undefined","onload","onerror","asMap","style","image","font","loadWhenIdle","timeout","requestIdleCallback","catch","console","warn","setTimeout","loadResources","resources","sortedResources","sortByPriority","highPriority","filter","r","mediumPriority","lowPriority","results","length","highResults","loadResourcesWithConcurrencyLimit","push","mediumResults","resource","priorityOrder","sort","a","b","aPriority","bPriority","concurrency","maxConcurrency","executing","Set","size","race","promise","finally","all","isLoaded","Map","resourceLoader"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utils/resourceLoader.ts"],"sourcesContent":["export { ResourceLoader, ResourcePriority, resourceLoader } from '@vlian/utils';\nexport type { ResourceLoadOptions, ResourceType } from '@vlian/utils';\n"],"names":["ResourceLoader","ResourcePriority","resourceLoader"],"mappings":"AAAA,SAASA,cAAc,EAAEC,gBAAgB,EAAEC,cAAc,QAAQ,eAAe"}
@@ -5,147 +5,9 @@ Object.defineProperty(exports, "__esModule", {
5
5
  Object.defineProperty(exports, "RuntimeSecurity", {
6
6
  enumerable: true,
7
7
  get: function() {
8
- return RuntimeSecurity;
8
+ return _utils.RuntimeSecurity;
9
9
  }
10
10
  });
11
- const _security = require("./security");
12
- let RuntimeSecurity = class RuntimeSecurity {
13
- /**
14
- * 应用 CSP
15
- *
16
- * 注意:通过 meta 标签设置 CSP 不如 HTTP 头安全,建议在服务器端设置 CSP 头。
17
- * 此方法仅作为补充措施。
18
- */ static applyCSP(config) {
19
- if (typeof document === 'undefined') {
20
- return;
21
- }
22
- try {
23
- const cspHeader = _security.SecurityUtils.generateCSP(config);
24
- // 创建或更新 meta 标签
25
- let metaCSP = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
26
- if (!metaCSP) {
27
- metaCSP = document.createElement('meta');
28
- metaCSP.setAttribute('http-equiv', 'Content-Security-Policy');
29
- // 插入到 head 的开头,确保优先级
30
- document.head.insertBefore(metaCSP, document.head.firstChild);
31
- }
32
- metaCSP.setAttribute('content', cspHeader);
33
- // 添加 CSP 违规报告(如果支持)
34
- if (typeof window !== 'undefined' && 'reporting' in window) {
35
- // 可以添加 CSP 违规监听器
36
- window.addEventListener('securitypolicyviolation', (event)=>{
37
- console.warn('CSP 违规:', {
38
- violatedDirective: event.violatedDirective,
39
- blockedURI: event.blockedURI
40
- });
41
- });
42
- }
43
- } catch (error) {
44
- console.error('应用 CSP 失败:', error);
45
- }
46
- }
47
- /**
48
- * 应用安全头(通过 meta 标签,实际应该由服务器设置)
49
- */ static applySecurityHeaders(config) {
50
- if (typeof document === 'undefined') {
51
- return;
52
- }
53
- // X-Frame-Options
54
- if (config.xFrameOptions) {
55
- let meta = document.querySelector('meta[http-equiv="X-Frame-Options"]');
56
- if (!meta) {
57
- meta = document.createElement('meta');
58
- meta.setAttribute('http-equiv', 'X-Frame-Options');
59
- document.head.appendChild(meta);
60
- }
61
- meta.setAttribute('content', config.xFrameOptions);
62
- }
63
- // X-Content-Type-Options
64
- if (config.xContentTypeOptions !== false) {
65
- let meta = document.querySelector('meta[http-equiv="X-Content-Type-Options"]');
66
- if (!meta) {
67
- meta = document.createElement('meta');
68
- meta.setAttribute('http-equiv', 'X-Content-Type-Options');
69
- document.head.appendChild(meta);
70
- }
71
- meta.setAttribute('content', 'nosniff');
72
- }
73
- // X-XSS-Protection
74
- if (config.xXSSProtection !== false) {
75
- let meta = document.querySelector('meta[http-equiv="X-XSS-Protection"]');
76
- if (!meta) {
77
- meta = document.createElement('meta');
78
- meta.setAttribute('http-equiv', 'X-XSS-Protection');
79
- document.head.appendChild(meta);
80
- }
81
- meta.setAttribute('content', '1; mode=block');
82
- }
83
- // Referrer-Policy
84
- if (config.referrerPolicy) {
85
- let meta = document.querySelector('meta[name="referrer"]');
86
- if (!meta) {
87
- meta = document.createElement('meta');
88
- meta.setAttribute('name', 'referrer');
89
- document.head.appendChild(meta);
90
- }
91
- meta.setAttribute('content', config.referrerPolicy);
92
- }
93
- }
94
- /**
95
- * 检查运行时安全
96
- */ static checkRuntimeSecurity() {
97
- const issues = [];
98
- if (typeof window === 'undefined') {
99
- return {
100
- safe: true,
101
- issues: []
102
- };
103
- }
104
- // 检查是否在 HTTPS 环境下
105
- if (window.location.protocol !== 'https:' && window.location.hostname !== 'localhost') {
106
- issues.push('应用未在 HTTPS 环境下运行');
107
- }
108
- // 检查是否有危险的全局对象
109
- if (window.eval) {
110
- issues.push('检测到危险的 eval 函数');
111
- }
112
- // 检查是否有危险的 innerHTML 使用
113
- // 这个检查需要在代码层面进行,这里只是示例
114
- return {
115
- safe: issues.length === 0,
116
- issues
117
- };
118
- }
119
- /**
120
- * 初始化运行时安全
121
- */ static initialize(options = {}) {
122
- const { enableCSP = false, enableSecurityHeaders = false, enableRuntimeChecks = false, csp, securityHeaders } = options;
123
- // 应用 CSP
124
- if (enableCSP && csp) {
125
- this.applyCSP(csp);
126
- }
127
- // 应用安全头
128
- if (enableSecurityHeaders && securityHeaders) {
129
- this.applySecurityHeaders(securityHeaders);
130
- }
131
- // 运行时检查
132
- if (enableRuntimeChecks) {
133
- const checkResult = this.checkRuntimeSecurity();
134
- if (!checkResult.safe) {
135
- console.warn('运行时安全检查发现问题:', checkResult.issues);
136
- }
137
- }
138
- }
139
- /**
140
- * 验证 URL 安全性
141
- */ static validateUrl(url) {
142
- return _security.SecurityUtils.isSafeUrl(url);
143
- }
144
- /**
145
- * 验证并清理用户输入
146
- */ static sanitizeUserInput(input) {
147
- return _security.SecurityUtils.validateInput(input);
148
- }
149
- };
11
+ const _utils = require("@vlian/utils");
150
12
 
151
13
  //# sourceMappingURL=runtimeSecurity.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/runtimeSecurity.ts"],"sourcesContent":["import { SecurityUtils } from './security';\n\n/**\n * CSP 配置\n */\nexport interface CSPConfig {\n defaultSrc?: string[];\n scriptSrc?: string[];\n styleSrc?: string[];\n imgSrc?: string[];\n connectSrc?: string[];\n fontSrc?: string[];\n frameSrc?: string[];\n}\n\n/**\n * 安全头配置\n */\nexport interface SecurityHeadersConfig {\n /**\n * Content Security Policy\n */\n csp?: CSPConfig | string;\n /**\n * X-Frame-Options\n */\n xFrameOptions?: 'DENY' | 'SAMEORIGIN' | 'ALLOW-FROM';\n /**\n * X-Content-Type-Options\n */\n xContentTypeOptions?: boolean;\n /**\n * X-XSS-Protection\n */\n xXSSProtection?: boolean;\n /**\n * Referrer-Policy\n */\n referrerPolicy?: 'no-referrer' | 'no-referrer-when-downgrade' | 'origin' | 'origin-when-cross-origin' | 'same-origin' | 'strict-origin' | 'strict-origin-when-cross-origin' | 'unsafe-url';\n /**\n * Permissions-Policy\n */\n permissionsPolicy?: Record<string, string[]>;\n}\n\n/**\n * 运行时安全检查选项\n */\nexport interface RuntimeSecurityOptions {\n /**\n * 是否启用 CSP\n */\n enableCSP?: boolean;\n /**\n * 是否启用安全头\n */\n enableSecurityHeaders?: boolean;\n /**\n * 是否启用运行时检查\n */\n enableRuntimeChecks?: boolean;\n /**\n * CSP 配置\n */\n csp?: CSPConfig;\n /**\n * 安全头配置\n */\n securityHeaders?: SecurityHeadersConfig;\n}\n\n/**\n * 运行时安全工具类\n */\nexport class RuntimeSecurity {\n /**\n * 应用 CSP\n * \n * 注意:通过 meta 标签设置 CSP 不如 HTTP 头安全,建议在服务器端设置 CSP 头。\n * 此方法仅作为补充措施。\n */\n static applyCSP(config: CSPConfig): void {\n if (typeof document === 'undefined') {\n return;\n }\n\n try {\n const cspHeader = SecurityUtils.generateCSP(config);\n\n // 创建或更新 meta 标签\n let metaCSP = document.querySelector('meta[http-equiv=\"Content-Security-Policy\"]');\n if (!metaCSP) {\n metaCSP = document.createElement('meta');\n metaCSP.setAttribute('http-equiv', 'Content-Security-Policy');\n // 插入到 head 的开头,确保优先级\n document.head.insertBefore(metaCSP, document.head.firstChild);\n }\n metaCSP.setAttribute('content', cspHeader);\n\n // 添加 CSP 违规报告(如果支持)\n if (typeof window !== 'undefined' && 'reporting' in window) {\n // 可以添加 CSP 违规监听器\n window.addEventListener('securitypolicyviolation', (event) => {\n console.warn('CSP 违规:', {\n violatedDirective: (event as any).violatedDirective,\n blockedURI: (event as any).blockedURI,\n });\n });\n }\n } catch (error) {\n console.error('应用 CSP 失败:', error);\n }\n }\n\n /**\n * 应用安全头(通过 meta 标签,实际应该由服务器设置)\n */\n static applySecurityHeaders(config: SecurityHeadersConfig): void {\n if (typeof document === 'undefined') {\n return;\n }\n\n // X-Frame-Options\n if (config.xFrameOptions) {\n let meta = document.querySelector('meta[http-equiv=\"X-Frame-Options\"]');\n if (!meta) {\n meta = document.createElement('meta');\n meta.setAttribute('http-equiv', 'X-Frame-Options');\n document.head.appendChild(meta);\n }\n meta.setAttribute('content', config.xFrameOptions);\n }\n\n // X-Content-Type-Options\n if (config.xContentTypeOptions !== false) {\n let meta = document.querySelector('meta[http-equiv=\"X-Content-Type-Options\"]');\n if (!meta) {\n meta = document.createElement('meta');\n meta.setAttribute('http-equiv', 'X-Content-Type-Options');\n document.head.appendChild(meta);\n }\n meta.setAttribute('content', 'nosniff');\n }\n\n // X-XSS-Protection\n if (config.xXSSProtection !== false) {\n let meta = document.querySelector('meta[http-equiv=\"X-XSS-Protection\"]');\n if (!meta) {\n meta = document.createElement('meta');\n meta.setAttribute('http-equiv', 'X-XSS-Protection');\n document.head.appendChild(meta);\n }\n meta.setAttribute('content', '1; mode=block');\n }\n\n // Referrer-Policy\n if (config.referrerPolicy) {\n let meta = document.querySelector('meta[name=\"referrer\"]');\n if (!meta) {\n meta = document.createElement('meta');\n meta.setAttribute('name', 'referrer');\n document.head.appendChild(meta);\n }\n meta.setAttribute('content', config.referrerPolicy);\n }\n }\n\n /**\n * 检查运行时安全\n */\n static checkRuntimeSecurity(): {\n safe: boolean;\n issues: string[];\n } {\n const issues: string[] = [];\n\n if (typeof window === 'undefined') {\n return { safe: true, issues: [] };\n }\n\n // 检查是否在 HTTPS 环境下\n if (window.location.protocol !== 'https:' && window.location.hostname !== 'localhost') {\n issues.push('应用未在 HTTPS 环境下运行');\n }\n\n // 检查是否有危险的全局对象\n if ((window as any).eval) {\n issues.push('检测到危险的 eval 函数');\n }\n\n // 检查是否有危险的 innerHTML 使用\n // 这个检查需要在代码层面进行,这里只是示例\n\n return {\n safe: issues.length === 0,\n issues,\n };\n }\n\n /**\n * 初始化运行时安全\n */\n static initialize(options: RuntimeSecurityOptions = {}): void {\n const {\n enableCSP = false,\n enableSecurityHeaders = false,\n enableRuntimeChecks = false,\n csp,\n securityHeaders,\n } = options;\n\n // 应用 CSP\n if (enableCSP && csp) {\n this.applyCSP(csp);\n }\n\n // 应用安全头\n if (enableSecurityHeaders && securityHeaders) {\n this.applySecurityHeaders(securityHeaders);\n }\n\n // 运行时检查\n if (enableRuntimeChecks) {\n const checkResult = this.checkRuntimeSecurity();\n if (!checkResult.safe) {\n console.warn('运行时安全检查发现问题:', checkResult.issues);\n }\n }\n }\n\n /**\n * 验证 URL 安全性\n */\n static validateUrl(url: string): boolean {\n return SecurityUtils.isSafeUrl(url);\n }\n\n /**\n * 验证并清理用户输入\n */\n static sanitizeUserInput(input: unknown): {\n safe: boolean;\n sanitized?: string;\n } {\n return SecurityUtils.validateInput(input);\n }\n}\n"],"names":["RuntimeSecurity","applyCSP","config","document","cspHeader","SecurityUtils","generateCSP","metaCSP","querySelector","createElement","setAttribute","head","insertBefore","firstChild","window","addEventListener","event","console","warn","violatedDirective","blockedURI","error","applySecurityHeaders","xFrameOptions","meta","appendChild","xContentTypeOptions","xXSSProtection","referrerPolicy","checkRuntimeSecurity","issues","safe","location","protocol","hostname","push","eval","length","initialize","options","enableCSP","enableSecurityHeaders","enableRuntimeChecks","csp","securityHeaders","checkResult","validateUrl","url","isSafeUrl","sanitizeUserInput","input","validateInput"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utils/runtimeSecurity.ts"],"sourcesContent":["export { RuntimeSecurity } from '@vlian/utils';\nexport type { RuntimeSecurityOptions, CSPConfig, SecurityHeadersConfig } from '@vlian/utils';\n"],"names":["RuntimeSecurity"],"mappings":";;;;+BAASA;;;eAAAA,sBAAe;;;uBAAQ"}
@@ -1,104 +1,2 @@
1
- /**
2
- * CSP 配置
3
- */
4
- export interface CSPConfig {
5
- defaultSrc?: string[];
6
- scriptSrc?: string[];
7
- styleSrc?: string[];
8
- imgSrc?: string[];
9
- connectSrc?: string[];
10
- fontSrc?: string[];
11
- frameSrc?: string[];
12
- }
13
- /**
14
- * 安全头配置
15
- */
16
- export interface SecurityHeadersConfig {
17
- /**
18
- * Content Security Policy
19
- */
20
- csp?: CSPConfig | string;
21
- /**
22
- * X-Frame-Options
23
- */
24
- xFrameOptions?: 'DENY' | 'SAMEORIGIN' | 'ALLOW-FROM';
25
- /**
26
- * X-Content-Type-Options
27
- */
28
- xContentTypeOptions?: boolean;
29
- /**
30
- * X-XSS-Protection
31
- */
32
- xXSSProtection?: boolean;
33
- /**
34
- * Referrer-Policy
35
- */
36
- referrerPolicy?: 'no-referrer' | 'no-referrer-when-downgrade' | 'origin' | 'origin-when-cross-origin' | 'same-origin' | 'strict-origin' | 'strict-origin-when-cross-origin' | 'unsafe-url';
37
- /**
38
- * Permissions-Policy
39
- */
40
- permissionsPolicy?: Record<string, string[]>;
41
- }
42
- /**
43
- * 运行时安全检查选项
44
- */
45
- export interface RuntimeSecurityOptions {
46
- /**
47
- * 是否启用 CSP
48
- */
49
- enableCSP?: boolean;
50
- /**
51
- * 是否启用安全头
52
- */
53
- enableSecurityHeaders?: boolean;
54
- /**
55
- * 是否启用运行时检查
56
- */
57
- enableRuntimeChecks?: boolean;
58
- /**
59
- * CSP 配置
60
- */
61
- csp?: CSPConfig;
62
- /**
63
- * 安全头配置
64
- */
65
- securityHeaders?: SecurityHeadersConfig;
66
- }
67
- /**
68
- * 运行时安全工具类
69
- */
70
- export declare class RuntimeSecurity {
71
- /**
72
- * 应用 CSP
73
- *
74
- * 注意:通过 meta 标签设置 CSP 不如 HTTP 头安全,建议在服务器端设置 CSP 头。
75
- * 此方法仅作为补充措施。
76
- */
77
- static applyCSP(config: CSPConfig): void;
78
- /**
79
- * 应用安全头(通过 meta 标签,实际应该由服务器设置)
80
- */
81
- static applySecurityHeaders(config: SecurityHeadersConfig): void;
82
- /**
83
- * 检查运行时安全
84
- */
85
- static checkRuntimeSecurity(): {
86
- safe: boolean;
87
- issues: string[];
88
- };
89
- /**
90
- * 初始化运行时安全
91
- */
92
- static initialize(options?: RuntimeSecurityOptions): void;
93
- /**
94
- * 验证 URL 安全性
95
- */
96
- static validateUrl(url: string): boolean;
97
- /**
98
- * 验证并清理用户输入
99
- */
100
- static sanitizeUserInput(input: unknown): {
101
- safe: boolean;
102
- sanitized?: string;
103
- };
104
- }
1
+ export { RuntimeSecurity } from '@vlian/utils';
2
+ export type { RuntimeSecurityOptions, CSPConfig, SecurityHeadersConfig } from '@vlian/utils';