@ng-web-apis/universal
Version:
A set of fallback for @ng-web-apis/common for Angular Universal
529 lines (502 loc) • 14.7 kB
JavaScript
import { WA_ANIMATION_FRAME, CACHES, CRYPTO, HISTORY, WA_LOCAL_STORAGE, WA_LOCATION, WA_NAVIGATOR, MEDIA_DEVICES, WA_PERFORMANCE, WA_SESSION_STORAGE, SPEECH_SYNTHESIS, WA_USER_AGENT, WA_WINDOW } from '@ng-web-apis/common';
import { NEVER } from 'rxjs';
import { InjectionToken, Optional } from '@angular/core';
import { DOCUMENT } from '@angular/common';
const UNIVERSAL_ANIMATION_FRAME = {
provide: WA_ANIMATION_FRAME,
useValue: NEVER,
};
function identity(v) {
return v;
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
function emptyFunction() { }
function emptyArray() {
return [];
}
function emptyObject() {
return {};
}
function alwaysFalse() {
return false;
}
function alwaysNull() {
return null;
}
function alwaysZero() {
return 0;
}
async function alwaysRejected() {
return Promise.reject().catch(emptyFunction);
}
const CACHES_MOCK = {
delete: async () => Promise.resolve(false),
has: async () => Promise.resolve(false),
keys: async () => Promise.resolve([]),
match: alwaysRejected,
open: alwaysRejected,
};
const UNIVERSAL_CACHES = {
provide: CACHES,
useValue: CACHES_MOCK,
};
const CRYPTO_MOCK = {
subtle: new Proxy({}, {
get: () => () => alwaysRejected,
}),
getRandomValues: identity,
};
const UNIVERSAL_CRYPTO = {
provide: CRYPTO,
useValue: CRYPTO_MOCK,
};
const HISTORY_MOCK = {
length: 0,
scrollRestoration: 'auto',
state: {},
back: emptyFunction,
forward: emptyFunction,
go: emptyFunction,
pushState: emptyFunction,
replaceState: emptyFunction,
};
const UNIVERSAL_HISTORY = {
provide: HISTORY,
useValue: HISTORY_MOCK,
};
class StorageMock {
storage = new Map();
get length() {
return this.storage.size;
}
getItem(key) {
return this.storage.has(key) ? this.storage.get(key) : null;
}
setItem(key, value) {
this.storage.set(key, value);
}
clear() {
this.storage.clear();
}
key(index) {
return index < this.storage.size
? ([...this.storage.keys()]?.[index] ?? null)
: null;
}
removeItem(key) {
this.storage.delete(key);
}
}
const UNIVERSAL_LOCAL_STORAGE = {
provide: WA_LOCAL_STORAGE,
useClass: StorageMock,
};
class DOMStringListMock extends Array {
contains() {
return false;
}
item() {
return null;
}
}
class LocationMock {
ancestorOrigins = new DOMStringListMock();
hash = '';
host = '';
hostname = '';
href = '';
origin = '';
pathname = '';
port = '';
protocol = '';
search = '';
assign = emptyFunction;
reload = emptyFunction;
replace = emptyFunction;
}
const WA_SSR_LOCATION = new InjectionToken('[WA_SSR_LOCATION]');
/**
* @deprecated: drop in v5.0, use {@link WA_SSR_LOCATION}
*/
const SSR_LOCATION = WA_SSR_LOCATION;
const UNIVERSAL_LOCATION = {
provide: WA_LOCATION,
deps: [[new Optional(), SSR_LOCATION]],
useFactory: (location) => location || new LocationMock(),
};
const WA_SSR_USER_AGENT = new InjectionToken('[WA_SSR_USER_AGENT]');
/**
* @deprecated: drop in v5.0, use {@link WA_SSR_USER_AGENT}
*/
const SSR_USER_AGENT = WA_SSR_USER_AGENT;
const EVENT_TARGET = {
addEventListener: emptyFunction,
dispatchEvent: alwaysFalse,
removeEventListener: emptyFunction,
};
function getArray() {
return new (class extends Array {
item = () => null;
namedItem = () => null;
refresh() { }
})();
}
const NAVIGATOR_MOCK = {
appCodeName: '',
appName: '',
appVersion: '',
platform: '',
product: '',
productSub: '',
userAgent: '',
vendor: '',
vendorSub: '',
onLine: false,
confirmSiteSpecificTrackingException: alwaysFalse,
confirmWebWideTrackingException: alwaysFalse,
share: alwaysRejected,
registerProtocolHandler: emptyFunction,
unregisterProtocolHandler: emptyFunction,
removeSiteSpecificTrackingException: emptyFunction,
removeWebWideTrackingException: emptyFunction,
storeSiteSpecificTrackingException: emptyFunction,
storeWebWideTrackingException: emptyFunction,
credentials: {
create: alwaysRejected,
get: alwaysRejected,
preventSilentAccess: alwaysRejected,
store: alwaysRejected,
},
msSaveBlob: alwaysFalse,
msSaveOrOpenBlob: alwaysFalse,
sendBeacon: alwaysFalse,
hardwareConcurrency: 0,
getDisplayMedia: alwaysRejected,
language: '',
languages: [],
storage: {
estimate: alwaysRejected,
persist: alwaysRejected,
persisted: alwaysRejected,
},
activeVRDisplays: [],
authentication: {
getAssertion: alwaysRejected,
makeCredential: alwaysRejected,
},
clipboard: {
...EVENT_TARGET,
readText: alwaysRejected,
writeText: alwaysRejected,
},
cookieEnabled: false,
doNotTrack: null,
gamepadInputEmulation: 'keyboard',
geolocation: {
clearWatch: emptyFunction,
getCurrentPosition: emptyFunction,
watchPosition: alwaysZero,
},
maxTouchPoints: 0,
mediaDevices: {
...EVENT_TARGET,
ondevicechange: null,
enumerateDevices: alwaysRejected,
getSupportedConstraints: emptyObject,
getUserMedia: alwaysRejected,
},
mimeTypes: getArray(),
msManipulationViewsEnabled: false,
msMaxTouchPoints: 0,
msPointerEnabled: false,
permissions: {
query: alwaysRejected,
},
plugins: getArray(),
pointerEnabled: false,
serviceWorker: {
...EVENT_TARGET,
controller: null,
oncontrollerchange: null,
onmessage: null,
onmessageerror: null,
ready: alwaysRejected(),
getRegistration: alwaysRejected,
getRegistrations: alwaysRejected,
register: alwaysRejected,
startMessages: emptyFunction,
},
webdriver: false,
getGamepads: emptyArray,
getUserMedia: emptyFunction,
getVRDisplays: alwaysRejected,
javaEnabled: alwaysFalse,
msLaunchUri: emptyFunction,
requestMediaKeySystemAccess: alwaysRejected,
vibrate: alwaysFalse,
};
const UNIVERSAL_NAVIGATOR = {
provide: WA_NAVIGATOR,
deps: [[new Optional(), SSR_USER_AGENT]],
useFactory: (userAgent) => ({
...NAVIGATOR_MOCK,
userAgent: userAgent ?? '',
}),
};
const UNIVERSAL_MEDIA_DEVICES = {
provide: MEDIA_DEVICES,
useValue: NAVIGATOR_MOCK.mediaDevices,
};
function performanceFactory() {
return (safeRequire('node:perf_hooks')?.performance ||
safeRequire('perf_hooks')?.performance ||
globalThis.performance);
}
const UNIVERSAL_PERFORMANCE = {
provide: WA_PERFORMANCE,
deps: [],
useFactory: performanceFactory,
};
function safeRequire(modulePath) {
try {
return require(modulePath);
}
catch {
return undefined;
}
}
const UNIVERSAL_SESSION_STORAGE = {
provide: WA_SESSION_STORAGE,
useClass: StorageMock,
};
const SPEECH_SYNTHESIS_MOCK = {
paused: false,
pending: false,
speaking: false,
onvoiceschanged: emptyFunction,
addEventListener: emptyFunction,
removeEventListener: emptyFunction,
dispatchEvent: alwaysFalse,
cancel: emptyFunction,
pause: emptyFunction,
resume: emptyFunction,
speak: emptyFunction,
getVoices: emptyArray,
};
const UNIVERSAL_SPEECH_SYNTHESIS = {
provide: SPEECH_SYNTHESIS,
useValue: SPEECH_SYNTHESIS_MOCK,
};
const UNIVERSAL_USER_AGENT = {
provide: WA_USER_AGENT,
deps: [[new Optional(), SSR_USER_AGENT]],
useFactory: (userAgent) => userAgent ?? '',
};
class BlobMock {
size = 0;
type = '';
arrayBuffer = async () => alwaysRejected();
stream = () => new ReadableStream();
text = async () => alwaysRejected();
slice = () => this;
}
const COMPUTED_STYLES = {
getPropertyPriority: () => '',
getPropertyValue: () => '',
item: () => '',
removeProperty: () => '',
setProperty: emptyFunction,
};
const COMPUTED_STYLES_HANDLER = {
get: (obj, key) => (key in obj ? obj[key] : null),
};
const COMPUTED_STYLES_PROXY = new Proxy(COMPUTED_STYLES, COMPUTED_STYLES_HANDLER);
const CSS_RULES = new (class extends Array {
item = () => null;
})();
const BAR_PROP = {
visible: false,
};
const DB_REQUEST = {
...EVENT_TARGET,
onblocked: null,
onerror: null,
onsuccess: null,
onupgradeneeded: null,
error: null,
readyState: 'pending',
result: null,
source: null,
transaction: null,
};
const SELF = ['frames', 'parent', 'self', 'top', 'window'];
const WINDOW_HANDLER = {
get: (windowRef, key) => {
if (SELF.includes(key)) {
return windowRef;
}
return key.startsWith('on') ? null : windowRef[key];
},
};
const UNIVERSAL_WINDOW = {
provide: WA_WINDOW,
deps: [DOCUMENT, [new Optional(), SSR_LOCATION], [new Optional(), SSR_USER_AGENT]],
useFactory: (document, location, userAgent) => {
const windowMock = {
...EVENT_TARGET,
document,
localStorage: new StorageMock(),
location: location ?? new LocationMock(),
navigator: { ...NAVIGATOR_MOCK, userAgent: userAgent ?? '' },
performance: performanceFactory(),
sessionStorage: new StorageMock(),
speechSynthesis: SPEECH_SYNTHESIS_MOCK,
caches: CACHES_MOCK,
crypto: CRYPTO_MOCK,
URL,
URLSearchParams,
setTimeout,
setInterval,
clearTimeout,
clearInterval,
console,
Blob: BlobMock,
alert: emptyFunction,
clientInformation: { ...NAVIGATOR_MOCK, userAgent: userAgent ?? '' },
// TODO: Candidate for token
matchMedia: () => ({
...EVENT_TARGET,
matches: false,
media: '',
onchange: null,
addListener: emptyFunction,
removeListener: emptyFunction,
}),
// TODO: Candidate for token
indexedDB: {
cmp: alwaysZero,
open: () => DB_REQUEST,
deleteDatabase: () => DB_REQUEST,
},
customElements: {
define: emptyFunction,
get: emptyFunction,
upgrade: emptyFunction,
whenDefined: alwaysRejected,
},
styleMedia: {
type: '',
matchMedium: alwaysFalse,
},
history: {
length: 0,
scrollRestoration: 'auto',
state: {},
back: emptyFunction,
forward: emptyFunction,
go: emptyFunction,
pushState: emptyFunction,
replaceState: emptyFunction,
},
closed: false,
defaultStatus: '',
devicePixelRatio: 1,
doNotTrack: '',
frameElement: null,
innerHeight: 0,
innerWidth: 0,
isSecureContext: false,
length: 0,
name: '',
offscreenBuffering: false,
opener: {},
origin: '',
orientation: '',
outerHeight: 0,
outerWidth: 0,
pageXOffset: 0,
pageYOffset: 0,
screenLeft: 0,
screenTop: 0,
screenX: 0,
screenY: 0,
scrollX: 0,
scrollY: 0,
status: '',
blur: emptyFunction,
cancelAnimationFrame: emptyFunction,
captureEvents: emptyFunction,
close: emptyFunction,
confirm: alwaysFalse,
departFocus: emptyFunction,
focus: emptyFunction,
moveBy: emptyFunction,
moveTo: emptyFunction,
open: alwaysNull,
postMessage: emptyFunction,
print: emptyFunction,
prompt: alwaysNull,
releaseEvents: emptyFunction,
requestAnimationFrame: alwaysZero,
resizeBy: emptyFunction,
resizeTo: emptyFunction,
scroll: emptyFunction,
scrollBy: emptyFunction,
scrollTo: emptyFunction,
stop: emptyFunction,
atob: identity,
btoa: identity,
fetch: alwaysRejected,
createImageBitmap: alwaysRejected,
queueMicrotask: emptyFunction,
locationbar: BAR_PROP,
menubar: BAR_PROP,
personalbar: BAR_PROP,
scrollbars: BAR_PROP,
statusbar: BAR_PROP,
toolbar: BAR_PROP,
getComputedStyle: () => COMPUTED_STYLES_PROXY,
getMatchedCSSRules: () => CSS_RULES,
getSelection: () => null,
};
return new Proxy(windowMock, WINDOW_HANDLER);
},
};
const UNIVERSAL_PROVIDERS = [
UNIVERSAL_ANIMATION_FRAME,
UNIVERSAL_CACHES,
UNIVERSAL_CRYPTO,
UNIVERSAL_HISTORY,
UNIVERSAL_LOCAL_STORAGE,
UNIVERSAL_SESSION_STORAGE,
UNIVERSAL_LOCATION,
UNIVERSAL_MEDIA_DEVICES,
UNIVERSAL_NAVIGATOR,
UNIVERSAL_PERFORMANCE,
UNIVERSAL_SPEECH_SYNTHESIS,
UNIVERSAL_USER_AGENT,
UNIVERSAL_WINDOW,
];
function provideLocation(req) {
const protocol = 'encrypted' in req.socket ? 'https' : 'http';
const url = new URL(`${protocol}://${req.headers.host}${req.url}`);
url.assign = emptyFunction;
url.reload = emptyFunction;
url.replace = emptyFunction;
url.ancestorOrigins = new DOMStringListMock();
return {
provide: SSR_LOCATION,
useValue: url,
};
}
function provideUserAgent(req) {
return {
provide: SSR_USER_AGENT,
useValue: req.headers['user-agent'],
};
}
/**
* Generated bundle index. Do not edit.
*/
export { CACHES_MOCK, CRYPTO_MOCK, EVENT_TARGET, HISTORY_MOCK, NAVIGATOR_MOCK, SPEECH_SYNTHESIS_MOCK, SSR_LOCATION, SSR_USER_AGENT, UNIVERSAL_ANIMATION_FRAME, UNIVERSAL_CACHES, UNIVERSAL_CRYPTO, UNIVERSAL_HISTORY, UNIVERSAL_LOCAL_STORAGE, UNIVERSAL_LOCATION, UNIVERSAL_MEDIA_DEVICES, UNIVERSAL_NAVIGATOR, UNIVERSAL_PERFORMANCE, UNIVERSAL_PROVIDERS, UNIVERSAL_SESSION_STORAGE, UNIVERSAL_SPEECH_SYNTHESIS, UNIVERSAL_USER_AGENT, UNIVERSAL_WINDOW, WA_SSR_LOCATION, WA_SSR_USER_AGENT, alwaysFalse, alwaysNull, alwaysRejected, alwaysZero, emptyArray, emptyFunction, emptyObject, identity, performanceFactory, provideLocation, provideUserAgent };
//# sourceMappingURL=ng-web-apis-universal.mjs.map