ngx-preboot
Version:
Record server view events and play back to Angular client view
76 lines • 11.7 kB
JavaScript
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { APP_BOOTSTRAP_LISTENER, ApplicationRef, Inject, InjectionToken, Optional, PLATFORM_ID } from '@angular/core';
import { DOCUMENT, isPlatformBrowser, isPlatformServer } from '@angular/common';
import { filter, take } from 'rxjs/operators';
import { EventReplayer } from './api/event.replayer';
import { PREBOOT_NONCE } from './common/tokens';
import { getInlineDefinition, getInlineInvocation } from './api/inline.preboot.code';
import { validateOptions } from './api';
const PREBOOT_SCRIPT_CLASS = 'preboot-inline-script';
export const PREBOOT_OPTIONS = new InjectionToken('PrebootOptions');
function createScriptFromCode(doc, nonce, inlineCode) {
const script = doc.createElement('script');
if (nonce) {
script.nonce = nonce;
}
script.className = PREBOOT_SCRIPT_CLASS;
script.textContent = inlineCode;
return script;
}
export function PREBOOT_FACTORY(doc, prebootOpts, nonce, platformId, appRef, eventReplayer) {
return () => {
validateOptions(prebootOpts);
if (isPlatformServer(platformId)) {
const inlineCodeDefinition = getInlineDefinition(prebootOpts);
const scriptWithDefinition = createScriptFromCode(doc, nonce, inlineCodeDefinition);
const inlineCodeInvocation = getInlineInvocation();
const existingScripts = doc.getElementsByClassName(PREBOOT_SCRIPT_CLASS);
// Check to see if preboot scripts are already inlined before adding them
// to the DOM. If they are, update the nonce to be current.
if (existingScripts.length === 0) {
const baseList = [];
const appRootSelectors = baseList.concat(prebootOpts.appRoot);
doc.head.appendChild(scriptWithDefinition);
appRootSelectors
.map((selector) => ({
selector,
appRootElem: doc.querySelector(selector),
}))
.forEach(({ selector, appRootElem }) => {
if (!appRootElem) {
console.log(`No server node found for selector: ${selector}`);
return;
}
const scriptWithInvocation = createScriptFromCode(doc, nonce, inlineCodeInvocation);
appRootElem.insertBefore(scriptWithInvocation, appRootElem.firstChild);
});
}
else if (existingScripts.length > 0 && nonce) {
existingScripts[0].nonce = nonce;
}
}
if (isPlatformBrowser(platformId)) {
const replay = prebootOpts.replay != null ? prebootOpts.replay : true;
if (replay) {
appRef.isStable
.pipe(filter((stable) => stable), take(1))
.subscribe(() => {
eventReplayer.replayAll();
});
}
}
};
}
export const PREBOOT_PROVIDER = {
provide: APP_BOOTSTRAP_LISTENER,
useFactory: PREBOOT_FACTORY,
deps: [DOCUMENT, PREBOOT_OPTIONS, [new Optional(), new Inject(PREBOOT_NONCE)], PLATFORM_ID, ApplicationRef, EventReplayer],
multi: true,
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiLi4vLi4vc3JjL2xpYi8iLCJzb3VyY2VzIjpbInByb3ZpZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUNILE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3RILE9BQU8sRUFBRSxRQUFRLEVBQUUsaUJBQWlCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRixPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTlDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLG1CQUFtQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFckYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUV4QyxNQUFNLG9CQUFvQixHQUFHLHVCQUF1QixDQUFDO0FBQ3JELE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxJQUFJLGNBQWMsQ0FBaUIsZ0JBQWdCLENBQUMsQ0FBQztBQUVwRixTQUFTLG9CQUFvQixDQUFDLEdBQWEsRUFBRSxLQUFvQixFQUFFLFVBQWtCO0lBQ25GLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDM0MsSUFBSSxLQUFLLEVBQUU7UUFDUixNQUFjLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztLQUMvQjtJQUNELE1BQU0sQ0FBQyxTQUFTLEdBQUcsb0JBQW9CLENBQUM7SUFDeEMsTUFBTSxDQUFDLFdBQVcsR0FBRyxVQUFVLENBQUM7SUFFaEMsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUVE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O0NBQ1osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuaW1wb3J0IHsgQVBQX0JPT1RTVFJBUF9MSVNURU5FUiwgQXBwbGljYXRpb25SZWYsIEluamVjdCwgSW5qZWN0aW9uVG9rZW4sIE9wdGlvbmFsLCBQTEFURk9STV9JRCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRE9DVU1FTlQsIGlzUGxhdGZvcm1Ccm93c2VyLCBpc1BsYXRmb3JtU2VydmVyIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IGZpbHRlciwgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgRXZlbnRSZXBsYXllciB9IGZyb20gJy4vYXBpL2V2ZW50LnJlcGxheWVyJztcbmltcG9ydCB7IFBSRUJPT1RfTk9OQ0UgfSBmcm9tICcuL2NvbW1vbi90b2tlbnMnO1xuaW1wb3J0IHsgZ2V0SW5saW5lRGVmaW5pdGlvbiwgZ2V0SW5saW5lSW52b2NhdGlvbiB9IGZyb20gJy4vYXBpL2lubGluZS5wcmVib290LmNvZGUnO1xuaW1wb3J0IHsgUHJlYm9vdE9wdGlvbnMgfSBmcm9tICcuL2NvbW1vbi9wcmVib290LmludGVyZmFjZXMnO1xuaW1wb3J0IHsgdmFsaWRhdGVPcHRpb25zIH0gZnJvbSAnLi9hcGknO1xuXG5jb25zdCBQUkVCT09UX1NDUklQVF9DTEFTUyA9ICdwcmVib290LWlubGluZS1zY3JpcHQnO1xuZXhwb3J0IGNvbnN0IFBSRUJPT1RfT1BUSU9OUyA9IG5ldyBJbmplY3Rpb25Ub2tlbjxQcmVib290T3B0aW9ucz4oJ1ByZWJvb3RPcHRpb25zJyk7XG5cbmZ1bmN0aW9uIGNyZWF0ZVNjcmlwdEZyb21Db2RlKGRvYzogRG9jdW1lbnQsIG5vbmNlOiBzdHJpbmcgfCBudWxsLCBpbmxpbmVDb2RlOiBzdHJpbmcpIHtcbiAgY29uc3Qgc2NyaXB0ID0gZG9jLmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICBpZiAobm9uY2UpIHtcbiAgICAoc2NyaXB0IGFzIGFueSkubm9uY2UgPSBub25jZTtcbiAgfVxuICBzY3JpcHQuY2xhc3NOYW1lID0gUFJFQk9PVF9TQ1JJUFRfQ0xBU1M7XG4gIHNjcmlwdC50ZXh0Q29udGVudCA9IGlubGluZUNvZGU7XG5cbiAgcmV0dXJuIHNjcmlwdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFBSRUJPT1RfRkFDVE9SWShcbiAgZG9jOiBEb2N1bWVudCxcbiAgcHJlYm9vdE9wdHM6IFByZWJvb3RPcHRpb25zLFxuICBub25jZTogc3RyaW5nIHwgbnVsbCxcbiAgcGxhdGZvcm1JZDogT2JqZWN0LFxuICBhcHBSZWY6IEFwcGxpY2F0aW9uUmVmLFxuICBldmVudFJlcGxheWVyOiBFdmVudFJlcGxheWVyXG4pIHtcbiAgcmV0dXJuICgpID0+IHtcbiAgICB2YWxpZGF0ZU9wdGlvbnMocHJlYm9vdE9wdHMpO1xuXG4gICAgaWYgKGlzUGxhdGZvcm1TZXJ2ZXIocGxhdGZvcm1JZCkpIHtcbiAgICAgIGNvbnN0IGlubGluZUNvZGVEZWZpbml0aW9uID0gZ2V0SW5saW5lRGVmaW5pdGlvbihwcmVib290T3B0cyk7XG4gICAgICBjb25zdCBzY3JpcHRXaXRoRGVmaW5pdGlvbiA9IGNyZWF0ZVNjcmlwdEZyb21Db2RlKGRvYywgbm9uY2UsIGlubGluZUNvZGVEZWZpbml0aW9uKTtcbiAgICAgIGNvbnN0IGlubGluZUNvZGVJbnZvY2F0aW9uID0gZ2V0SW5saW5lSW52b2NhdGlvbigpO1xuXG4gICAgICBjb25zdCBleGlzdGluZ1NjcmlwdHMgPSBkb2MuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShQUkVCT09UX1NDUklQVF9DTEFTUyk7XG5cbiAgICAgIC8vIENoZWNrIHRvIHNlZSBpZiBwcmVib290IHNjcmlwdHMgYXJlIGFscmVhZHkgaW5saW5lZCBiZWZvcmUgYWRkaW5nIHRoZW1cbiAgICAgIC8vIHRvIHRoZSBET00uIElmIHRoZXkgYXJlLCB1cGRhdGUgdGhlIG5vbmNlIHRvIGJlIGN1cnJlbnQuXG4gICAgICBpZiAoZXhpc3RpbmdTY3JpcHRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBjb25zdCBiYXNlTGlzdDogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgY29uc3QgYXBwUm9vdFNlbGVjdG9ycyA9IGJhc2VMaXN0LmNvbmNhdChwcmVib290T3B0cy5hcHBSb290KTtcbiAgICAgICAgZG9jLmhlYWQuYXBwZW5kQ2hpbGQoc2NyaXB0V2l0aERlZmluaXRpb24pO1xuICAgICAgICBhcHBSb290U2VsZWN0b3JzXG4gICAgICAgICAgLm1hcCgoc2VsZWN0b3IpID0+ICh7XG4gICAgICAgICAgICBzZWxlY3RvcixcbiAgICAgICAgICAgIGFwcFJvb3RFbGVtOiBkb2MucXVlcnlTZWxlY3RvcihzZWxlY3RvciksXG4gICAgICAgICAgfSkpXG4gICAgICAgICAgLmZvckVhY2goKHsgc2VsZWN0b3IsIGFwcFJvb3RFbGVtIH0pID0+IHtcbiAgICAgICAgICAgIGlmICghYXBwUm9vdEVsZW0pIHtcbiAgICAgICAgICAgICAgY29uc29sZS5sb2coYE5vIHNlcnZlciBub2RlIGZvdW5kIGZvciBzZWxlY3RvcjogJHtzZWxlY3Rvcn1gKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc2NyaXB0V2l0aEludm9jYXRpb24gPSBjcmVhdGVTY3JpcHRGcm9tQ29kZShkb2MsIG5vbmNlLCBpbmxpbmVDb2RlSW52b2NhdGlvbik7XG4gICAgICAgICAgICBhcHBSb290RWxlbS5pbnNlcnRCZWZvcmUoc2NyaXB0V2l0aEludm9jYXRpb24sIGFwcFJvb3RFbGVtLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChleGlzdGluZ1NjcmlwdHMubGVuZ3RoID4gMCAmJiBub25jZSkge1xuICAgICAgICAoZXhpc3RpbmdTY3JpcHRzWzBdIGFzIGFueSkubm9uY2UgPSBub25jZTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGlzUGxhdGZvcm1Ccm93c2VyKHBsYXRmb3JtSWQpKSB7XG4gICAgICBjb25zdCByZXBsYXkgPSBwcmVib290T3B0cy5yZXBsYXkgIT0gbnVsbCA/IHByZWJvb3RPcHRzLnJlcGxheSA6IHRydWU7XG4gICAgICBpZiAocmVwbGF5KSB7XG4gICAgICAgIGFwcFJlZi5pc1N0YWJsZVxuICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgZmlsdGVyKChzdGFibGUpID0+IHN0YWJsZSksXG4gICAgICAgICAgICB0YWtlKDEpXG4gICAgICAgICAgKVxuICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgZXZlbnRSZXBsYXllci5yZXBsYXlBbGwoKTtcbiAgICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbmV4cG9ydCBjb25zdCBQUkVCT09UX1BST1ZJREVSID0ge1xuICBwcm92aWRlOiA8SW5qZWN0aW9uVG9rZW48KCkgPT4gdm9pZD4+QVBQX0JPT1RTVFJBUF9MSVNURU5FUixcbiAgdXNlRmFjdG9yeTogUFJFQk9PVF9GQUNUT1JZLFxuICBkZXBzOiBbRE9DVU1FTlQsIFBSRUJPT1RfT1BUSU9OUywgW25ldyBPcHRpb25hbCgpLCBuZXcgSW5qZWN0KFBSRUJPT1RfTk9OQ0UpXSwgUExBVEZPUk1fSUQsIEFwcGxpY2F0aW9uUmVmLCBFdmVudFJlcGxheWVyXSxcbiAgbXVsdGk6IHRydWUsXG59O1xuIl19