baseguard 1.0.0
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/.eslintrc.json +25 -0
- package/.prettierrc +8 -0
- package/README.md +94 -0
- package/bin/base.js +494 -0
- package/dist/ai/fix-manager.d.ts +67 -0
- package/dist/ai/fix-manager.d.ts.map +1 -0
- package/dist/ai/fix-manager.js +326 -0
- package/dist/ai/fix-manager.js.map +1 -0
- package/dist/ai/gemini-analyzer.d.ts +116 -0
- package/dist/ai/gemini-analyzer.d.ts.map +1 -0
- package/dist/ai/gemini-analyzer.js +572 -0
- package/dist/ai/gemini-analyzer.js.map +1 -0
- package/dist/ai/index.d.ts +4 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +5 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/jules-implementer.d.ts +115 -0
- package/dist/ai/jules-implementer.d.ts.map +1 -0
- package/dist/ai/jules-implementer.js +387 -0
- package/dist/ai/jules-implementer.js.map +1 -0
- package/dist/commands/automation.d.ts +5 -0
- package/dist/commands/automation.d.ts.map +1 -0
- package/dist/commands/automation.js +305 -0
- package/dist/commands/automation.js.map +1 -0
- package/dist/commands/check.d.ts +9 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +113 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/config.d.ts +11 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +324 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/fix.d.ts +9 -0
- package/dist/commands/fix.d.ts.map +1 -0
- package/dist/commands/fix.js +207 -0
- package/dist/commands/fix.js.map +1 -0
- package/dist/commands/index.d.ts +6 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +7 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +125 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/core/api-key-manager.d.ts +83 -0
- package/dist/core/api-key-manager.d.ts.map +1 -0
- package/dist/core/api-key-manager.js +244 -0
- package/dist/core/api-key-manager.js.map +1 -0
- package/dist/core/baseguard.d.ts +46 -0
- package/dist/core/baseguard.d.ts.map +1 -0
- package/dist/core/baseguard.js +132 -0
- package/dist/core/baseguard.js.map +1 -0
- package/dist/core/baseline-checker.d.ts +63 -0
- package/dist/core/baseline-checker.d.ts.map +1 -0
- package/dist/core/baseline-checker.js +502 -0
- package/dist/core/baseline-checker.js.map +1 -0
- package/dist/core/cache-manager.d.ts +88 -0
- package/dist/core/cache-manager.d.ts.map +1 -0
- package/dist/core/cache-manager.js +213 -0
- package/dist/core/cache-manager.js.map +1 -0
- package/dist/core/configuration.d.ts +140 -0
- package/dist/core/configuration.d.ts.map +1 -0
- package/dist/core/configuration.js +474 -0
- package/dist/core/configuration.js.map +1 -0
- package/dist/core/directory-filter.d.ts +90 -0
- package/dist/core/directory-filter.d.ts.map +1 -0
- package/dist/core/directory-filter.js +319 -0
- package/dist/core/directory-filter.js.map +1 -0
- package/dist/core/error-handler.d.ts +110 -0
- package/dist/core/error-handler.d.ts.map +1 -0
- package/dist/core/error-handler.js +392 -0
- package/dist/core/error-handler.js.map +1 -0
- package/dist/core/file-processor.d.ts +80 -0
- package/dist/core/file-processor.d.ts.map +1 -0
- package/dist/core/file-processor.js +259 -0
- package/dist/core/file-processor.js.map +1 -0
- package/dist/core/gitignore-manager.d.ts +44 -0
- package/dist/core/gitignore-manager.d.ts.map +1 -0
- package/dist/core/gitignore-manager.js +147 -0
- package/dist/core/gitignore-manager.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +13 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/lazy-loader.d.ts +68 -0
- package/dist/core/lazy-loader.d.ts.map +1 -0
- package/dist/core/lazy-loader.js +260 -0
- package/dist/core/lazy-loader.js.map +1 -0
- package/dist/core/memory-manager.d.ts +1 -0
- package/dist/core/memory-manager.d.ts.map +1 -0
- package/dist/core/memory-manager.js +2 -0
- package/dist/core/memory-manager.js.map +1 -0
- package/dist/core/startup-optimizer.d.ts +45 -0
- package/dist/core/startup-optimizer.d.ts.map +1 -0
- package/dist/core/startup-optimizer.js +140 -0
- package/dist/core/startup-optimizer.js.map +1 -0
- package/dist/git/automation-engine.d.ts +58 -0
- package/dist/git/automation-engine.d.ts.map +1 -0
- package/dist/git/automation-engine.js +318 -0
- package/dist/git/automation-engine.js.map +1 -0
- package/dist/git/github-manager.d.ts +71 -0
- package/dist/git/github-manager.d.ts.map +1 -0
- package/dist/git/github-manager.js +226 -0
- package/dist/git/github-manager.js.map +1 -0
- package/dist/git/hook-manager.d.ts +43 -0
- package/dist/git/hook-manager.d.ts.map +1 -0
- package/dist/git/hook-manager.js +191 -0
- package/dist/git/hook-manager.js.map +1 -0
- package/dist/git/index.d.ts +4 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/index.js +5 -0
- package/dist/git/index.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/feature-validator.d.ts +60 -0
- package/dist/parsers/feature-validator.d.ts.map +1 -0
- package/dist/parsers/feature-validator.js +483 -0
- package/dist/parsers/feature-validator.js.map +1 -0
- package/dist/parsers/index.d.ts +8 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +9 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/parser-manager.d.ts +103 -0
- package/dist/parsers/parser-manager.d.ts.map +1 -0
- package/dist/parsers/parser-manager.js +321 -0
- package/dist/parsers/parser-manager.js.map +1 -0
- package/dist/parsers/parser.d.ts +23 -0
- package/dist/parsers/parser.d.ts.map +1 -0
- package/dist/parsers/parser.js +6 -0
- package/dist/parsers/parser.js.map +1 -0
- package/dist/parsers/react-parser.d.ts +22 -0
- package/dist/parsers/react-parser.d.ts.map +1 -0
- package/dist/parsers/react-parser.js +307 -0
- package/dist/parsers/react-parser.js.map +1 -0
- package/dist/parsers/svelte-parser.d.ts +33 -0
- package/dist/parsers/svelte-parser.d.ts.map +1 -0
- package/dist/parsers/svelte-parser.js +408 -0
- package/dist/parsers/svelte-parser.js.map +1 -0
- package/dist/parsers/vanilla-parser.d.ts +31 -0
- package/dist/parsers/vanilla-parser.d.ts.map +1 -0
- package/dist/parsers/vanilla-parser.js +590 -0
- package/dist/parsers/vanilla-parser.js.map +1 -0
- package/dist/parsers/vue-parser.d.ts +9 -0
- package/dist/parsers/vue-parser.d.ts.map +1 -0
- package/dist/parsers/vue-parser.js +16 -0
- package/dist/parsers/vue-parser.js.map +1 -0
- package/dist/terminal-header.d.ts +12 -0
- package/dist/terminal-header.js +45 -0
- package/dist/types/index.d.ts +83 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/components.d.ts +133 -0
- package/dist/ui/components.d.ts.map +1 -0
- package/dist/ui/components.js +482 -0
- package/dist/ui/components.js.map +1 -0
- package/dist/ui/help.d.ts +11 -0
- package/dist/ui/help.d.ts.map +1 -0
- package/dist/ui/help.js +161 -0
- package/dist/ui/help.js.map +1 -0
- package/dist/ui/index.d.ts +5 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +5 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/prompts.d.ts +63 -0
- package/dist/ui/prompts.d.ts.map +1 -0
- package/dist/ui/prompts.js +611 -0
- package/dist/ui/prompts.js.map +1 -0
- package/dist/ui/terminal-header.d.ts +13 -0
- package/dist/ui/terminal-header.d.ts.map +1 -0
- package/dist/ui/terminal-header.js +46 -0
- package/dist/ui/terminal-header.js.map +1 -0
- package/package.json +80 -0
- package/src/ai/__tests__/gemini-analyzer.test.ts +181 -0
- package/src/ai/fix-manager.ts +362 -0
- package/src/ai/gemini-analyzer.ts +671 -0
- package/src/ai/index.ts +4 -0
- package/src/ai/jules-implementer.ts +459 -0
- package/src/commands/automation.ts +344 -0
- package/src/commands/check.ts +299 -0
- package/src/commands/config.ts +365 -0
- package/src/commands/fix.ts +234 -0
- package/src/commands/index.ts +6 -0
- package/src/commands/init.ts +142 -0
- package/src/commands/status.ts +0 -0
- package/src/core/api-key-manager.ts +298 -0
- package/src/core/baseguard.ts +742 -0
- package/src/core/baseline-checker.ts +563 -0
- package/src/core/cache-manager.ts +270 -0
- package/src/core/configuration-recovery.ts +676 -0
- package/src/core/configuration.ts +559 -0
- package/src/core/debug-logger.ts +590 -0
- package/src/core/directory-filter.ts +421 -0
- package/src/core/error-handler.ts +517 -0
- package/src/core/file-processor.ts +331 -0
- package/src/core/gitignore-manager.ts +169 -0
- package/src/core/graceful-degradation-manager.ts +596 -0
- package/src/core/index.ts +13 -0
- package/src/core/lazy-loader.ts +307 -0
- package/src/core/logger.ts +0 -0
- package/src/core/memory-manager.ts +294 -0
- package/src/core/startup-optimizer.ts +173 -0
- package/src/core/system-error-handler.ts +746 -0
- package/src/git/automation-engine.ts +361 -0
- package/src/git/github-manager.ts +260 -0
- package/src/git/hook-manager.ts +210 -0
- package/src/git/index.ts +4 -0
- package/src/index.ts +8 -0
- package/src/parsers/feature-validator.ts +559 -0
- package/src/parsers/index.ts +8 -0
- package/src/parsers/parser-manager.ts +419 -0
- package/src/parsers/parser.ts +26 -0
- package/src/parsers/react-parser-optimized.ts +161 -0
- package/src/parsers/react-parser.ts +359 -0
- package/src/parsers/svelte-parser.ts +506 -0
- package/src/parsers/vanilla-parser.ts +682 -0
- package/src/parsers/vue-parser.ts +472 -0
- package/src/types/index.ts +92 -0
- package/src/ui/components.ts +567 -0
- package/src/ui/help.ts +193 -0
- package/src/ui/index.ts +4 -0
- package/src/ui/prompts.ts +688 -0
- package/src/ui/terminal-header.ts +59 -0
- package/test-config-commands.js +56 -0
- package/test-header-simple.js +33 -0
- package/test-terminal-header.js +12 -0
- package/test-ui.js +29 -0
- package/tests/e2e/baseguard.e2e.test.ts +516 -0
- package/tests/e2e/cross-platform.e2e.test.ts +420 -0
- package/tests/e2e/git-integration.e2e.test.ts +487 -0
- package/tests/fixtures/react-project/package.json +14 -0
- package/tests/fixtures/react-project/src/App.css +76 -0
- package/tests/fixtures/react-project/src/App.tsx +77 -0
- package/tests/fixtures/svelte-project/package.json +11 -0
- package/tests/fixtures/svelte-project/src/App.svelte +369 -0
- package/tests/fixtures/vanilla-project/index.html +76 -0
- package/tests/fixtures/vanilla-project/script.js +331 -0
- package/tests/fixtures/vanilla-project/styles.css +359 -0
- package/tests/fixtures/vue-project/package.json +12 -0
- package/tests/fixtures/vue-project/src/App.vue +216 -0
- package/tsconfig.json +36 -0
- package/vitest.config.ts +10 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
import type { BrowserTarget, Violation, DetectedFeature, CompatibilityResult } from '../types/index.js';
|
|
2
|
+
import { LazyLoader } from './lazy-loader.js';
|
|
3
|
+
import { MemoryManager } from './memory-manager.js';
|
|
4
|
+
|
|
5
|
+
// Comprehensive feature mapping dictionary for ALL web platform features
|
|
6
|
+
const FEATURE_ID_MAP: Record<string, string> = {
|
|
7
|
+
// CSS Properties
|
|
8
|
+
'container-type': 'container-queries',
|
|
9
|
+
'container-name': 'container-queries',
|
|
10
|
+
'container': 'container-queries',
|
|
11
|
+
'aspect-ratio': 'aspect-ratio',
|
|
12
|
+
'gap': 'grid-gap',
|
|
13
|
+
'row-gap': 'grid-gap',
|
|
14
|
+
'column-gap': 'grid-gap',
|
|
15
|
+
'scroll-behavior': 'scroll-behavior',
|
|
16
|
+
'backdrop-filter': 'backdrop-filter',
|
|
17
|
+
'color-scheme': 'color-scheme',
|
|
18
|
+
'accent-color': 'accent-color',
|
|
19
|
+
'overscroll-behavior': 'overscroll-behavior',
|
|
20
|
+
'scroll-snap-type': 'scroll-snap-type',
|
|
21
|
+
'scroll-snap-align': 'scroll-snap-align',
|
|
22
|
+
'object-fit': 'object-fit',
|
|
23
|
+
'object-position': 'object-position',
|
|
24
|
+
'place-items': 'place-items',
|
|
25
|
+
'place-content': 'place-content',
|
|
26
|
+
'place-self': 'place-self',
|
|
27
|
+
'inset': 'inset',
|
|
28
|
+
'inset-block': 'inset',
|
|
29
|
+
'inset-inline': 'inset',
|
|
30
|
+
'block-size': 'logical-properties',
|
|
31
|
+
'inline-size': 'logical-properties',
|
|
32
|
+
'margin-block': 'logical-properties',
|
|
33
|
+
'margin-inline': 'logical-properties',
|
|
34
|
+
'padding-block': 'logical-properties',
|
|
35
|
+
'padding-inline': 'logical-properties',
|
|
36
|
+
'border-block': 'logical-properties',
|
|
37
|
+
'border-inline': 'logical-properties',
|
|
38
|
+
|
|
39
|
+
// CSS Selectors
|
|
40
|
+
':has()': 'has',
|
|
41
|
+
':is()': 'is',
|
|
42
|
+
':where()': 'where',
|
|
43
|
+
':focus-visible': 'focus-visible',
|
|
44
|
+
':focus-within': 'focus-within',
|
|
45
|
+
':target-within': 'target-within',
|
|
46
|
+
'::backdrop': 'backdrop',
|
|
47
|
+
'::marker': 'marker',
|
|
48
|
+
'::part()': 'part',
|
|
49
|
+
'::slotted()': 'slotted',
|
|
50
|
+
|
|
51
|
+
// CSS At-rules
|
|
52
|
+
'@supports': 'supports',
|
|
53
|
+
'@container': 'container-queries',
|
|
54
|
+
'@layer': 'cascade-layers',
|
|
55
|
+
'@scope': 'scope',
|
|
56
|
+
|
|
57
|
+
// JavaScript Web APIs
|
|
58
|
+
'HTMLDialogElement.showModal': 'dialog',
|
|
59
|
+
'HTMLDialogElement.show': 'dialog',
|
|
60
|
+
'HTMLDialogElement.close': 'dialog',
|
|
61
|
+
'structuredClone': 'structured-clone',
|
|
62
|
+
'Array.prototype.at': 'array-at',
|
|
63
|
+
'Array.prototype.findLast': 'array-find-last',
|
|
64
|
+
'Array.prototype.findLastIndex': 'array-find-last',
|
|
65
|
+
'String.prototype.at': 'string-at',
|
|
66
|
+
'String.prototype.replaceAll': 'string-replace-all',
|
|
67
|
+
'Object.hasOwn': 'object-has-own',
|
|
68
|
+
'ResizeObserver': 'resize-observer',
|
|
69
|
+
'IntersectionObserver': 'intersection-observer',
|
|
70
|
+
'MutationObserver': 'mutation-observer',
|
|
71
|
+
'PerformanceObserver': 'performance-observer',
|
|
72
|
+
'BroadcastChannel': 'broadcast-channel',
|
|
73
|
+
'MessageChannel': 'message-channel',
|
|
74
|
+
'SharedArrayBuffer': 'shared-array-buffer',
|
|
75
|
+
'Atomics': 'atomics',
|
|
76
|
+
'BigInt': 'bigint',
|
|
77
|
+
'WeakRef': 'weak-ref',
|
|
78
|
+
'FinalizationRegistry': 'finalization-registry',
|
|
79
|
+
|
|
80
|
+
// Canvas and WebGL APIs
|
|
81
|
+
'CanvasRenderingContext2D.filter': 'canvas-filter',
|
|
82
|
+
'CanvasRenderingContext2D.reset': 'canvas-reset',
|
|
83
|
+
'WebGL2RenderingContext': 'webgl2',
|
|
84
|
+
'OffscreenCanvas': 'offscreen-canvas',
|
|
85
|
+
'OffscreenCanvasRenderingContext2D': 'offscreen-canvas',
|
|
86
|
+
'ImageBitmap': 'image-bitmap',
|
|
87
|
+
'createImageBitmap': 'image-bitmap',
|
|
88
|
+
'Path2D': 'path2d',
|
|
89
|
+
|
|
90
|
+
// WebRTC APIs
|
|
91
|
+
'RTCPeerConnection': 'webrtc',
|
|
92
|
+
'getUserMedia': 'getusermedia',
|
|
93
|
+
'RTCDataChannel': 'rtc-data-channel',
|
|
94
|
+
'RTCRtpTransceiver': 'rtc-rtp-transceiver',
|
|
95
|
+
'RTCStatsReport': 'rtc-stats',
|
|
96
|
+
'RTCIceCandidate': 'rtc-ice-candidate',
|
|
97
|
+
'RTCSessionDescription': 'rtc-session-description',
|
|
98
|
+
|
|
99
|
+
// Service Workers and PWA
|
|
100
|
+
'ServiceWorker': 'service-workers',
|
|
101
|
+
'navigator.serviceWorker': 'service-workers',
|
|
102
|
+
'ServiceWorkerRegistration': 'service-workers',
|
|
103
|
+
'Cache': 'cache-api',
|
|
104
|
+
'CacheStorage': 'cache-api',
|
|
105
|
+
'PushManager': 'push-api',
|
|
106
|
+
'PushSubscription': 'push-api',
|
|
107
|
+
'NotificationEvent': 'notification-api',
|
|
108
|
+
'BackgroundSync': 'background-sync',
|
|
109
|
+
'PaymentRequest': 'payment-request',
|
|
110
|
+
'PaymentResponse': 'payment-request',
|
|
111
|
+
|
|
112
|
+
// WebAssembly
|
|
113
|
+
'WebAssembly': 'webassembly',
|
|
114
|
+
'WebAssembly.instantiate': 'webassembly',
|
|
115
|
+
'WebAssembly.compile': 'webassembly',
|
|
116
|
+
'WebAssembly.Module': 'webassembly',
|
|
117
|
+
'WebAssembly.Instance': 'webassembly',
|
|
118
|
+
'WebAssembly.Memory': 'webassembly',
|
|
119
|
+
'WebAssembly.Table': 'webassembly',
|
|
120
|
+
|
|
121
|
+
// JavaScript Syntax (ECMAScript features)
|
|
122
|
+
'optional-chaining': 'optional-chaining',
|
|
123
|
+
'nullish-coalescing': 'nullish-coalescing',
|
|
124
|
+
'private-fields': 'private-fields',
|
|
125
|
+
'private-methods': 'private-methods',
|
|
126
|
+
'static-class-fields': 'static-class-fields',
|
|
127
|
+
'top-level-await': 'top-level-await',
|
|
128
|
+
'import-assertions': 'import-assertions',
|
|
129
|
+
'import-meta': 'import-meta',
|
|
130
|
+
'dynamic-import': 'dynamic-import',
|
|
131
|
+
'async-iteration': 'async-iteration',
|
|
132
|
+
'for-await-of': 'async-iteration',
|
|
133
|
+
'destructuring': 'destructuring',
|
|
134
|
+
'rest-spread': 'rest-spread',
|
|
135
|
+
'template-literals': 'template-literals',
|
|
136
|
+
'arrow-functions': 'arrow-functions',
|
|
137
|
+
'const-let': 'const-let',
|
|
138
|
+
'default-parameters': 'default-parameters',
|
|
139
|
+
|
|
140
|
+
// HTML Elements and Attributes
|
|
141
|
+
'dialog': 'dialog',
|
|
142
|
+
'details': 'details-summary',
|
|
143
|
+
'summary': 'details-summary',
|
|
144
|
+
'loading="lazy"': 'loading-lazy',
|
|
145
|
+
'decoding="async"': 'image-decoding',
|
|
146
|
+
'input[type="date"]': 'input-date',
|
|
147
|
+
'input[type="time"]': 'input-time',
|
|
148
|
+
'input[type="datetime-local"]': 'input-datetime-local',
|
|
149
|
+
'input[type="month"]': 'input-month',
|
|
150
|
+
'input[type="week"]': 'input-week',
|
|
151
|
+
'input[type="color"]': 'input-color',
|
|
152
|
+
'input[type="range"]': 'input-range',
|
|
153
|
+
'input[type="search"]': 'input-search',
|
|
154
|
+
'input[type="tel"]': 'input-tel',
|
|
155
|
+
'input[type="url"]': 'input-url',
|
|
156
|
+
'input[type="email"]': 'input-email',
|
|
157
|
+
'input[type="number"]': 'input-number',
|
|
158
|
+
'datalist': 'datalist',
|
|
159
|
+
'output': 'output',
|
|
160
|
+
'progress': 'progress',
|
|
161
|
+
'meter': 'meter',
|
|
162
|
+
'picture': 'picture',
|
|
163
|
+
'source': 'picture',
|
|
164
|
+
'track': 'track',
|
|
165
|
+
'slot': 'slot',
|
|
166
|
+
'template': 'template',
|
|
167
|
+
|
|
168
|
+
// DOM APIs
|
|
169
|
+
'DOMMatrix': 'geometry-interfaces',
|
|
170
|
+
'DOMPoint': 'geometry-interfaces',
|
|
171
|
+
'DOMRect': 'geometry-interfaces',
|
|
172
|
+
'DOMQuad': 'geometry-interfaces',
|
|
173
|
+
'AbortController': 'abort-controller',
|
|
174
|
+
'AbortSignal': 'abort-controller',
|
|
175
|
+
'FormData': 'form-data',
|
|
176
|
+
'URLSearchParams': 'url-search-params',
|
|
177
|
+
'URL': 'url',
|
|
178
|
+
'URLPattern': 'url-pattern',
|
|
179
|
+
'Blob': 'blob',
|
|
180
|
+
'File': 'file',
|
|
181
|
+
'FileReader': 'file-reader',
|
|
182
|
+
'FileList': 'file-list',
|
|
183
|
+
'DataTransfer': 'data-transfer',
|
|
184
|
+
'ClipboardAPI': 'clipboard-api',
|
|
185
|
+
'navigator.clipboard': 'clipboard-api',
|
|
186
|
+
'Permissions': 'permissions-api',
|
|
187
|
+
'navigator.permissions': 'permissions-api',
|
|
188
|
+
'Geolocation': 'geolocation',
|
|
189
|
+
'navigator.geolocation': 'geolocation',
|
|
190
|
+
'DeviceOrientationEvent': 'device-orientation',
|
|
191
|
+
'DeviceMotionEvent': 'device-motion',
|
|
192
|
+
'Vibration': 'vibration',
|
|
193
|
+
'navigator.vibrate': 'vibration',
|
|
194
|
+
'Battery': 'battery-status',
|
|
195
|
+
'navigator.getBattery': 'battery-status',
|
|
196
|
+
'NetworkInformation': 'network-information',
|
|
197
|
+
'navigator.connection': 'network-information',
|
|
198
|
+
'MediaDevices': 'media-devices',
|
|
199
|
+
'navigator.mediaDevices': 'media-devices',
|
|
200
|
+
'MediaStream': 'media-stream',
|
|
201
|
+
'MediaRecorder': 'media-recorder',
|
|
202
|
+
'SpeechSynthesis': 'speech-synthesis',
|
|
203
|
+
'SpeechRecognition': 'speech-recognition',
|
|
204
|
+
'Gamepad': 'gamepad',
|
|
205
|
+
'navigator.getGamepads': 'gamepad',
|
|
206
|
+
'PointerEvent': 'pointer-events',
|
|
207
|
+
'TouchEvent': 'touch-events',
|
|
208
|
+
'WheelEvent': 'wheel-events',
|
|
209
|
+
'KeyboardEvent': 'keyboard-events',
|
|
210
|
+
'MouseEvent': 'mouse-events',
|
|
211
|
+
'FocusEvent': 'focus-events',
|
|
212
|
+
'InputEvent': 'input-events',
|
|
213
|
+
'CompositionEvent': 'composition-events',
|
|
214
|
+
'CustomEvent': 'custom-events',
|
|
215
|
+
'EventTarget': 'event-target',
|
|
216
|
+
'addEventListener': 'event-listeners',
|
|
217
|
+
'removeEventListener': 'event-listeners',
|
|
218
|
+
'dispatchEvent': 'event-dispatch',
|
|
219
|
+
'requestAnimationFrame': 'request-animation-frame',
|
|
220
|
+
'cancelAnimationFrame': 'request-animation-frame',
|
|
221
|
+
'requestIdleCallback': 'request-idle-callback',
|
|
222
|
+
'cancelIdleCallback': 'request-idle-callback',
|
|
223
|
+
'setTimeout': 'timers',
|
|
224
|
+
'setInterval': 'timers',
|
|
225
|
+
'clearTimeout': 'timers',
|
|
226
|
+
'clearInterval': 'timers',
|
|
227
|
+
'queueMicrotask': 'queue-microtask',
|
|
228
|
+
'fetch': 'fetch',
|
|
229
|
+
'Request': 'fetch',
|
|
230
|
+
'Response': 'fetch',
|
|
231
|
+
'Headers': 'fetch',
|
|
232
|
+
'XMLHttpRequest': 'xhr',
|
|
233
|
+
'EventSource': 'server-sent-events',
|
|
234
|
+
'WebSocket': 'websockets',
|
|
235
|
+
'History': 'history-api',
|
|
236
|
+
'history.pushState': 'history-api',
|
|
237
|
+
'history.replaceState': 'history-api',
|
|
238
|
+
'Location': 'location',
|
|
239
|
+
'Navigator': 'navigator',
|
|
240
|
+
'Screen': 'screen',
|
|
241
|
+
'Window': 'window',
|
|
242
|
+
'Document': 'document',
|
|
243
|
+
'Element': 'element',
|
|
244
|
+
'Node': 'node',
|
|
245
|
+
'DocumentFragment': 'document-fragment',
|
|
246
|
+
'ShadowRoot': 'shadow-dom',
|
|
247
|
+
'customElements': 'custom-elements',
|
|
248
|
+
'HTMLElement': 'html-element',
|
|
249
|
+
'SVGElement': 'svg-element'
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
export class BaselineChecker {
|
|
253
|
+
private webFeatures: any = null;
|
|
254
|
+
private featureCache = new Map<string, any>();
|
|
255
|
+
private initialized = false;
|
|
256
|
+
|
|
257
|
+
constructor() {
|
|
258
|
+
// Don't load web-features immediately - use lazy loading
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Initialize web-features data lazily
|
|
263
|
+
*/
|
|
264
|
+
private async ensureInitialized(): Promise<void> {
|
|
265
|
+
if (this.initialized) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
this.webFeatures = await LazyLoader.getWebFeatures();
|
|
271
|
+
this.initialized = true;
|
|
272
|
+
} catch (error) {
|
|
273
|
+
console.warn('Failed to load web-features data:', error);
|
|
274
|
+
this.webFeatures = { features: {}, browsers: {}, groups: {} };
|
|
275
|
+
this.initialized = true;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Get feature status from web-features package with caching
|
|
281
|
+
*/
|
|
282
|
+
private async getFeatureStatus(featureId: string): Promise<any> {
|
|
283
|
+
await this.ensureInitialized();
|
|
284
|
+
|
|
285
|
+
// Check cache first
|
|
286
|
+
if (this.featureCache.has(featureId)) {
|
|
287
|
+
return this.featureCache.get(featureId);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const feature = this.webFeatures?.features?.[featureId] || this.webFeatures?.[featureId];
|
|
291
|
+
|
|
292
|
+
// Cache the result to avoid repeated lookups
|
|
293
|
+
if (feature) {
|
|
294
|
+
// Optimize the feature data to reduce memory usage
|
|
295
|
+
const optimized = MemoryManager.optimizeObject({
|
|
296
|
+
name: feature.name,
|
|
297
|
+
status: feature.status,
|
|
298
|
+
support: feature.support,
|
|
299
|
+
baseline: feature.baseline
|
|
300
|
+
});
|
|
301
|
+
this.featureCache.set(featureId, optimized);
|
|
302
|
+
return optimized;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Cache null results too to avoid repeated failed lookups
|
|
306
|
+
this.featureCache.set(featureId, null);
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Map detected feature to web-features ID
|
|
312
|
+
*/
|
|
313
|
+
private mapFeatureToId(feature: string): string | null {
|
|
314
|
+
// Direct mapping
|
|
315
|
+
if (FEATURE_ID_MAP[feature]) {
|
|
316
|
+
return FEATURE_ID_MAP[feature];
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Try to find partial matches for complex features
|
|
320
|
+
for (const [key, value] of Object.entries(FEATURE_ID_MAP)) {
|
|
321
|
+
if (feature.includes(key) || key.includes(feature)) {
|
|
322
|
+
return value;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Check if the feature exists directly in web-features
|
|
327
|
+
if (this.webFeatures[feature]) {
|
|
328
|
+
return feature;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Check if a version is supported based on browser support data
|
|
336
|
+
*/
|
|
337
|
+
private isVersionSupported(browserSupport: any, minVersion: string): boolean {
|
|
338
|
+
if (!browserSupport) return false;
|
|
339
|
+
|
|
340
|
+
// If browser support is true, it's supported
|
|
341
|
+
if (browserSupport === true) return true;
|
|
342
|
+
|
|
343
|
+
// If browser support is false or null, it's not supported
|
|
344
|
+
if (!browserSupport) return false;
|
|
345
|
+
|
|
346
|
+
// If it's a version string, compare versions
|
|
347
|
+
if (typeof browserSupport === 'string') {
|
|
348
|
+
return this.compareVersions(browserSupport, minVersion) >= 0;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// If it's an object with version info, extract the version
|
|
352
|
+
if (typeof browserSupport === 'object' && browserSupport.version) {
|
|
353
|
+
return this.compareVersions(browserSupport.version, minVersion) >= 0;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Compare two version strings
|
|
361
|
+
*/
|
|
362
|
+
private compareVersions(version1: string, version2: string): number {
|
|
363
|
+
const v1Parts = version1.split('.').map(Number);
|
|
364
|
+
const v2Parts = version2.split('.').map(Number);
|
|
365
|
+
|
|
366
|
+
const maxLength = Math.max(v1Parts.length, v2Parts.length);
|
|
367
|
+
|
|
368
|
+
for (let i = 0; i < maxLength; i++) {
|
|
369
|
+
const v1Part = v1Parts[i] || 0;
|
|
370
|
+
const v2Part = v2Parts[i] || 0;
|
|
371
|
+
|
|
372
|
+
if (v1Part > v2Part) return 1;
|
|
373
|
+
if (v1Part < v2Part) return -1;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return 0;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Map browser name to web-features format
|
|
381
|
+
*/
|
|
382
|
+
private mapBrowserName(browser: string): string {
|
|
383
|
+
const browserMap: Record<string, string> = {
|
|
384
|
+
'chrome': 'chrome',
|
|
385
|
+
'firefox': 'firefox',
|
|
386
|
+
'safari': 'safari',
|
|
387
|
+
'edge': 'edge',
|
|
388
|
+
'opera': 'opera',
|
|
389
|
+
'samsung': 'samsung_android'
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
return browserMap[browser] || browser;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Create a violation object
|
|
397
|
+
*/
|
|
398
|
+
private createViolation(
|
|
399
|
+
detectedFeature: DetectedFeature,
|
|
400
|
+
target: BrowserTarget,
|
|
401
|
+
featureData: any,
|
|
402
|
+
featureId: string
|
|
403
|
+
): Violation {
|
|
404
|
+
const browserKey = this.mapBrowserName(target.browser);
|
|
405
|
+
const support = featureData?.status?.support;
|
|
406
|
+
const browserSupport = support ? (support as any)[browserKey] : undefined;
|
|
407
|
+
const baselineStatus = featureData?.status?.baseline;
|
|
408
|
+
|
|
409
|
+
let actual: string | false = false;
|
|
410
|
+
if (browserSupport === true) {
|
|
411
|
+
actual = 'supported';
|
|
412
|
+
} else if (typeof browserSupport === 'string') {
|
|
413
|
+
actual = browserSupport;
|
|
414
|
+
} else if (typeof browserSupport === 'object' && browserSupport?.version) {
|
|
415
|
+
actual = browserSupport.version;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
let reason = '';
|
|
419
|
+
if (target.minVersion === 'baseline' || target.minVersion === 'baseline-newly') {
|
|
420
|
+
if (baselineStatus === false) {
|
|
421
|
+
reason = 'Feature is not part of Baseline (not supported across all major browsers)';
|
|
422
|
+
} else if (baselineStatus === 'limited') {
|
|
423
|
+
reason = 'Feature has limited Baseline support';
|
|
424
|
+
}
|
|
425
|
+
} else {
|
|
426
|
+
reason = `Feature requires ${target.browser} ${actual || 'unknown'} but target is ${target.minVersion}`;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return {
|
|
430
|
+
feature: detectedFeature.feature,
|
|
431
|
+
featureId,
|
|
432
|
+
file: detectedFeature.file || 'unknown',
|
|
433
|
+
line: detectedFeature.line,
|
|
434
|
+
column: detectedFeature.column,
|
|
435
|
+
context: detectedFeature.context,
|
|
436
|
+
browser: target.browser,
|
|
437
|
+
required: target.minVersion,
|
|
438
|
+
actual,
|
|
439
|
+
baselineStatus: baselineStatus === false ? 'false' : baselineStatus === true ? 'widely' : String(baselineStatus || 'unknown'),
|
|
440
|
+
reason
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Check compatibility of a detected feature against browser targets
|
|
446
|
+
*/
|
|
447
|
+
async checkCompatibility(detectedFeature: DetectedFeature, targets: BrowserTarget[]): Promise<CompatibilityResult> {
|
|
448
|
+
const featureId = this.mapFeatureToId(detectedFeature.feature);
|
|
449
|
+
|
|
450
|
+
if (!featureId) {
|
|
451
|
+
// Feature not found in mapping, assume it's compatible
|
|
452
|
+
return {
|
|
453
|
+
violations: [],
|
|
454
|
+
featureData: null
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const featureData = await this.getFeatureStatus(featureId);
|
|
459
|
+
|
|
460
|
+
if (!featureData) {
|
|
461
|
+
// Feature not found in web-features, assume it's compatible
|
|
462
|
+
return {
|
|
463
|
+
violations: [],
|
|
464
|
+
featureData: null
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const violations: Violation[] = [];
|
|
469
|
+
|
|
470
|
+
for (const target of targets) {
|
|
471
|
+
if (target.minVersion === 'baseline' || target.minVersion === 'baseline-newly') {
|
|
472
|
+
// Check baseline status
|
|
473
|
+
const baselineStatus = featureData.status?.baseline;
|
|
474
|
+
|
|
475
|
+
if (baselineStatus === false) {
|
|
476
|
+
violations.push(this.createViolation(detectedFeature, target, featureData, featureId));
|
|
477
|
+
} else if (target.minVersion === 'baseline-newly' && baselineStatus === 'low') {
|
|
478
|
+
violations.push(this.createViolation(detectedFeature, target, featureData, featureId));
|
|
479
|
+
}
|
|
480
|
+
} else {
|
|
481
|
+
// Check specific version - map browser names to web-features format
|
|
482
|
+
const browserKey = this.mapBrowserName(target.browser);
|
|
483
|
+
const support = featureData.status?.support;
|
|
484
|
+
const browserSupport = support ? (support as any)[browserKey] : undefined;
|
|
485
|
+
|
|
486
|
+
if (!this.isVersionSupported(browserSupport, target.minVersion)) {
|
|
487
|
+
violations.push(this.createViolation(detectedFeature, target, featureData, featureId));
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return {
|
|
493
|
+
violations,
|
|
494
|
+
featureData
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Check multiple features against browser targets with memory optimization
|
|
500
|
+
*/
|
|
501
|
+
async checkMultipleFeatures(detectedFeatures: DetectedFeature[], targets: BrowserTarget[]): Promise<Violation[]> {
|
|
502
|
+
const violationTracker = MemoryManager.createViolationTracker();
|
|
503
|
+
|
|
504
|
+
// Process in batches to manage memory usage
|
|
505
|
+
await MemoryManager.processBatches(
|
|
506
|
+
detectedFeatures,
|
|
507
|
+
async (batch) => {
|
|
508
|
+
const batchResults = await Promise.all(
|
|
509
|
+
batch.map(feature => this.checkCompatibility(feature, targets))
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
for (const result of batchResults) {
|
|
513
|
+
for (const violation of result.violations) {
|
|
514
|
+
violationTracker.addViolation(violation);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return [];
|
|
519
|
+
},
|
|
520
|
+
50 // Process 50 features at a time
|
|
521
|
+
);
|
|
522
|
+
|
|
523
|
+
return violationTracker.getViolations();
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Get available feature IDs for debugging/testing
|
|
528
|
+
*/
|
|
529
|
+
async getAvailableFeatureIds(): Promise<string[]> {
|
|
530
|
+
await this.ensureInitialized();
|
|
531
|
+
return Object.keys(this.webFeatures?.features || this.webFeatures || {});
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Clear caches to free memory
|
|
536
|
+
*/
|
|
537
|
+
clearCache(): void {
|
|
538
|
+
this.featureCache.clear();
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Get cache statistics
|
|
543
|
+
*/
|
|
544
|
+
getCacheStats(): {
|
|
545
|
+
cacheSize: number;
|
|
546
|
+
memoryEstimate: string;
|
|
547
|
+
} {
|
|
548
|
+
const cacheSize = this.featureCache.size;
|
|
549
|
+
const memoryEstimate = `${Math.round(cacheSize * 500 / 1024)}KB`; // Rough estimate
|
|
550
|
+
|
|
551
|
+
return {
|
|
552
|
+
cacheSize,
|
|
553
|
+
memoryEstimate
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Get feature mapping for debugging/testing
|
|
559
|
+
*/
|
|
560
|
+
getFeatureMapping(): Record<string, string> {
|
|
561
|
+
return { ...FEATURE_ID_MAP };
|
|
562
|
+
}
|
|
563
|
+
}
|