@ms-cloudpack/app-server 0.17.56 → 0.17.58
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/lib/inlineScripts/bootstrap.inline.d.ts +0 -1
- package/lib/inlineScripts/bootstrap.inline.js +1 -1
- package/lib/inlineScripts/bootstrap.inline.js.map +1 -1
- package/lib/inlineScripts/defineProcess.inline.d.ts +0 -1
- package/lib/inlineScripts/defineProcess.inline.js +1 -1
- package/lib/inlineScripts/defineProcess.inline.js.map +1 -1
- package/lib/inlineScripts/errorHandler.inline.d.ts +7 -1
- package/lib/inlineScripts/errorHandler.inline.d.ts.map +1 -1
- package/lib/inlineScripts/errorHandler.inline.js +1 -1
- package/lib/inlineScripts/errorHandler.inline.js.map +1 -1
- package/lib/inlineScripts/getBrowserCacheRatio.inline.d.ts +10 -1
- package/lib/inlineScripts/getBrowserCacheRatio.inline.d.ts.map +1 -1
- package/lib/inlineScripts/getBrowserCacheRatio.inline.js +1 -1
- package/lib/inlineScripts/getBrowserCacheRatio.inline.js.map +1 -1
- package/lib/inlineScripts/getPageLoadTime.inline.js +1 -1
- package/lib/inlineScripts/getPageLoadTime.inline.js.map +1 -1
- package/lib/renderRoute/renderRoute.d.ts.map +1 -1
- package/lib/renderRoute/renderRoute.js +12 -9
- package/lib/renderRoute/renderRoute.js.map +1 -1
- package/package.json +7 -8
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
window.__cloudpack ??= {};
|
|
2
3
|
window.__cloudpack.bootstrap = ({ inlineScripts, overlayScript, importMap, entryScripts }) => {
|
|
3
4
|
window.__cloudpack ??= {};
|
|
@@ -35,5 +36,4 @@ window.__cloudpack.bootstrap = ({ inlineScripts, overlayScript, importMap, entry
|
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
};
|
|
38
|
-
export {};
|
|
39
39
|
//# sourceMappingURL=bootstrap.inline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.inline.js","sourceRoot":"","sources":["../../src/inlineScripts/bootstrap.inline.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,WAAW,KAAK,EAAE,CAAC;AAC1B,MAAM,CAAC,WAAW,CAAC,SAAS,GAAG,CAAC,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,EAAE;IAC3F,MAAM,CAAC,WAAW,KAAK,EAAE,CAAC;IAC1B,IAAI,MAAM,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IACD,MAAM,CAAC,WAAW,CAAC,eAAe,GAAG,IAAI,CAAC;IAC1C,wBAAwB;IACxB,MAAM,kBAAkB,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC5D,kBAAkB,CAAC,IAAI,GAAG,WAAW,CAAC;IACtC,kBAAkB,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3D,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAE9C,4BAA4B;IAC5B,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnD,SAAS,CAAC,IAAI,GAAG,QAAQ,CAAC;QAC1B,SAAS,CAAC,WAAW,GAAG,YAAY,CAAC;QACrC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,4BAA4B;IAC5B,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,gBAAgB,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC1D,gBAAgB,CAAC,IAAI,GAAG,QAAQ,CAAC;QACjC,gBAAgB,CAAC,GAAG,GAAG,aAAa,CAAC;QACrC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;IAC9C,CAAC;IAED,yBAAyB;IACzB,IAAI,YAAY,EAAE,CAAC;QACjB,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,MAAM,cAAc,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YACxD,cAAc,CAAC,IAAI,GAAG,QAAQ,CAAC;YAC/B,cAAc,CAAC,GAAG,GAAG,WAAW,CAAC;YACjC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;AACH,CAAC,CAAC","sourcesContent":["window.__cloudpack ??= {};\nwindow.__cloudpack.bootstrap = ({ inlineScripts, overlayScript, importMap, entryScripts }) => {\n window.__cloudpack ??= {};\n if (window.__cloudpack.hasBootstrapRun) {\n console.warn('Cloudpack bootstrap has already run, skipping.');\n return;\n }\n window.__cloudpack.hasBootstrapRun = true;\n // Inject the import map\n const importMapScriptTag = document.createElement('script');\n importMapScriptTag.type = 'importmap';\n importMapScriptTag.textContent = JSON.stringify(importMap);\n document.head.appendChild(importMapScriptTag);\n\n // Inject the inline scripts\n for (const inlineScript of inlineScripts) {\n const inlineTag = document.createElement('script');\n inlineTag.type = 'module';\n inlineTag.textContent = inlineScript;\n document.head.appendChild(inlineTag);\n }\n\n // Inject the overlay script\n if (overlayScript) {\n const overlayScriptTag = document.createElement('script');\n overlayScriptTag.type = 'module';\n overlayScriptTag.src = overlayScript;\n document.head.appendChild(overlayScriptTag);\n }\n\n // Inject the main script\n if (entryScripts) {\n for (const entryScript of entryScripts) {\n const entryScriptTag = document.createElement('script');\n entryScriptTag.type = 'module';\n entryScriptTag.src = entryScript;\n document.head.appendChild(entryScriptTag);\n }\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"bootstrap.inline.js","sourceRoot":"","sources":["../../src/inlineScripts/bootstrap.inline.ts"],"names":[],"mappings":";AAAA,MAAM,CAAC,WAAW,KAAK,EAAE,CAAC;AAC1B,MAAM,CAAC,WAAW,CAAC,SAAS,GAAG,CAAC,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,EAAE;IAC3F,MAAM,CAAC,WAAW,KAAK,EAAE,CAAC;IAC1B,IAAI,MAAM,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IACD,MAAM,CAAC,WAAW,CAAC,eAAe,GAAG,IAAI,CAAC;IAC1C,wBAAwB;IACxB,MAAM,kBAAkB,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC5D,kBAAkB,CAAC,IAAI,GAAG,WAAW,CAAC;IACtC,kBAAkB,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3D,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAE9C,4BAA4B;IAC5B,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnD,SAAS,CAAC,IAAI,GAAG,QAAQ,CAAC;QAC1B,SAAS,CAAC,WAAW,GAAG,YAAY,CAAC;QACrC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,4BAA4B;IAC5B,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,gBAAgB,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC1D,gBAAgB,CAAC,IAAI,GAAG,QAAQ,CAAC;QACjC,gBAAgB,CAAC,GAAG,GAAG,aAAa,CAAC;QACrC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;IAC9C,CAAC;IAED,yBAAyB;IACzB,IAAI,YAAY,EAAE,CAAC;QACjB,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,MAAM,cAAc,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YACxD,cAAc,CAAC,IAAI,GAAG,QAAQ,CAAC;YAC/B,cAAc,CAAC,GAAG,GAAG,WAAW,CAAC;YACjC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;AACH,CAAC,CAAC","sourcesContent":["window.__cloudpack ??= {};\nwindow.__cloudpack.bootstrap = ({ inlineScripts, overlayScript, importMap, entryScripts }) => {\n window.__cloudpack ??= {};\n if (window.__cloudpack.hasBootstrapRun) {\n console.warn('Cloudpack bootstrap has already run, skipping.');\n return;\n }\n window.__cloudpack.hasBootstrapRun = true;\n // Inject the import map\n const importMapScriptTag = document.createElement('script');\n importMapScriptTag.type = 'importmap';\n importMapScriptTag.textContent = JSON.stringify(importMap);\n document.head.appendChild(importMapScriptTag);\n\n // Inject the inline scripts\n for (const inlineScript of inlineScripts) {\n const inlineTag = document.createElement('script');\n inlineTag.type = 'module';\n inlineTag.textContent = inlineScript;\n document.head.appendChild(inlineTag);\n }\n\n // Inject the overlay script\n if (overlayScript) {\n const overlayScriptTag = document.createElement('script');\n overlayScriptTag.type = 'module';\n overlayScriptTag.src = overlayScript;\n document.head.appendChild(overlayScriptTag);\n }\n\n // Inject the main script\n if (entryScripts) {\n for (const entryScript of entryScripts) {\n const entryScriptTag = document.createElement('script');\n entryScriptTag.type = 'module';\n entryScriptTag.src = entryScript;\n document.head.appendChild(entryScriptTag);\n }\n }\n};\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// This file must NOT import other files, because they won't be resolved at runtime.
|
|
2
3
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3
4
|
window.process ??= {};
|
|
4
5
|
window.process.env ??= {};
|
|
5
6
|
// Assign true to process.browser for packages like readable-stream
|
|
6
7
|
process.browser = true;
|
|
7
|
-
export {};
|
|
8
8
|
//# sourceMappingURL=defineProcess.inline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defineProcess.inline.js","sourceRoot":"","sources":["../../src/inlineScripts/defineProcess.inline.ts"],"names":[],"mappings":"AAAA,oFAAoF;AAEpF,8DAA8D;AAC9D,MAAM,CAAC,OAAO,KAAK,EAAS,CAAC;AAC7B,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,EAAE,CAAC;AAE1B,mEAAmE;AAClE,OAA2C,CAAC,OAAO,GAAG,IAAI,CAAC","sourcesContent":["// This file must NOT import other files, because they won't be resolved at runtime.\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nwindow.process ??= {} as any;\nwindow.process.env ??= {};\n\n// Assign true to process.browser for packages like readable-stream\n(process as unknown as { browser: boolean }).browser = true;\n"]}
|
|
1
|
+
{"version":3,"file":"defineProcess.inline.js","sourceRoot":"","sources":["../../src/inlineScripts/defineProcess.inline.ts"],"names":[],"mappings":";AAAA,oFAAoF;AAEpF,8DAA8D;AAC9D,MAAM,CAAC,OAAO,KAAK,EAAS,CAAC;AAC7B,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,EAAE,CAAC;AAE1B,mEAAmE;AAClE,OAA2C,CAAC,OAAO,GAAG,IAAI,CAAC","sourcesContent":["// This file must NOT import other files, because they won't be resolved at runtime.\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nwindow.process ??= {} as any;\nwindow.process.env ??= {};\n\n// Assign true to process.browser for packages like readable-stream\n(process as unknown as { browser: boolean }).browser = true;\n"]}
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
declare const pageErrors: {
|
|
2
|
+
uncaughtErrors: ErrorEvent[];
|
|
3
|
+
uncaughtRejections: PromiseRejectionEvent[];
|
|
4
|
+
unregister: () => void;
|
|
5
|
+
};
|
|
6
|
+
declare function handleError(event: ErrorEvent): void;
|
|
7
|
+
declare function handleRejection(event: PromiseRejectionEvent): void;
|
|
2
8
|
//# sourceMappingURL=errorHandler.inline.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorHandler.inline.d.ts","sourceRoot":"","sources":["../../src/inlineScripts/errorHandler.inline.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"errorHandler.inline.d.ts","sourceRoot":"","sources":["../../src/inlineScripts/errorHandler.inline.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,UAAU;oBACQ,UAAU,EAAE;wBACR,qBAAqB,EAAE;;CAKjD,CAAC;AAEH,iBAAS,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAE5C;AAED,iBAAS,eAAe,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,CAE3D"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// This file must NOT import other files, because they won't be resolved at runtime.
|
|
2
3
|
const pageErrors = (window.__pageErrors = {
|
|
3
4
|
uncaughtErrors: [],
|
|
@@ -15,5 +16,4 @@ function handleRejection(event) {
|
|
|
15
16
|
}
|
|
16
17
|
window.addEventListener('error', handleError);
|
|
17
18
|
window.addEventListener('unhandledrejection', handleRejection);
|
|
18
|
-
export {};
|
|
19
19
|
//# sourceMappingURL=errorHandler.inline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorHandler.inline.js","sourceRoot":"","sources":["../../src/inlineScripts/errorHandler.inline.ts"],"names":[],"mappings":"AAAA,oFAAoF;AAEpF,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG;IACxC,cAAc,EAAE,EAAkB;IAClC,kBAAkB,EAAE,EAA6B;IACjD,UAAU,EAAE,GAAG,EAAE;QACf,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QACjD,MAAM,CAAC,mBAAmB,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC;IACpE,CAAC;CACF,CAAC,CAAC;AAEH,SAAS,WAAW,CAAC,KAAiB;IACpC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,eAAe,CAAC,KAA4B;IACnD,UAAU,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAC9C,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC","sourcesContent":["// This file must NOT import other files, because they won't be resolved at runtime.\n\nconst pageErrors = (window.__pageErrors = {\n uncaughtErrors: [] as ErrorEvent[],\n uncaughtRejections: [] as PromiseRejectionEvent[],\n unregister: () => {\n window.removeEventListener('error', handleError);\n window.removeEventListener('unhandledrejection', handleRejection);\n },\n});\n\nfunction handleError(event: ErrorEvent): void {\n pageErrors.uncaughtErrors.push(event);\n}\n\nfunction handleRejection(event: PromiseRejectionEvent): void {\n pageErrors.uncaughtRejections.push(event);\n}\n\nwindow.addEventListener('error', handleError);\nwindow.addEventListener('unhandledrejection', handleRejection);\n"]}
|
|
1
|
+
{"version":3,"file":"errorHandler.inline.js","sourceRoot":"","sources":["../../src/inlineScripts/errorHandler.inline.ts"],"names":[],"mappings":";AAAA,oFAAoF;AAEpF,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG;IACxC,cAAc,EAAE,EAAkB;IAClC,kBAAkB,EAAE,EAA6B;IACjD,UAAU,EAAE,GAAG,EAAE;QACf,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QACjD,MAAM,CAAC,mBAAmB,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC;IACpE,CAAC;CACF,CAAC,CAAC;AAEH,SAAS,WAAW,CAAC,KAAiB;IACpC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,eAAe,CAAC,KAA4B;IACnD,UAAU,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAC9C,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC","sourcesContent":["// This file must NOT import other files, because they won't be resolved at runtime.\n\nconst pageErrors = (window.__pageErrors = {\n uncaughtErrors: [] as ErrorEvent[],\n uncaughtRejections: [] as PromiseRejectionEvent[],\n unregister: () => {\n window.removeEventListener('error', handleError);\n window.removeEventListener('unhandledrejection', handleRejection);\n },\n});\n\nfunction handleError(event: ErrorEvent): void {\n pageErrors.uncaughtErrors.push(event);\n}\n\nfunction handleRejection(event: PromiseRejectionEvent): void {\n pageErrors.uncaughtRejections.push(event);\n}\n\nwindow.addEventListener('error', handleError);\nwindow.addEventListener('unhandledrejection', handleRejection);\n"]}
|
|
@@ -1,2 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
declare const scriptLoadResults: Record<string, 'cache' | 'network'>;
|
|
2
|
+
declare const bundleServerUrl: string;
|
|
3
|
+
declare function isPerformanceResourceTiming(entry: PerformanceEntry): entry is PerformanceResourceTiming;
|
|
4
|
+
declare function handlePerformanceEntry(item: PerformanceEntry): void;
|
|
5
|
+
declare const perfObserver: PerformanceObserver;
|
|
6
|
+
declare function getBrowserCacheRatio(): {
|
|
7
|
+
ratio: number;
|
|
8
|
+
hit: number;
|
|
9
|
+
total: number;
|
|
10
|
+
};
|
|
2
11
|
//# sourceMappingURL=getBrowserCacheRatio.inline.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getBrowserCacheRatio.inline.d.ts","sourceRoot":"","sources":["../../src/inlineScripts/getBrowserCacheRatio.inline.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"getBrowserCacheRatio.inline.d.ts","sourceRoot":"","sources":["../../src/inlineScripts/getBrowserCacheRatio.inline.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAM,CAAC;AAMlE,QAAA,MAAM,eAAe,QAAwD,CAAC;AAE9E,iBAAS,2BAA2B,CAAC,KAAK,EAAE,gBAAgB,GAAG,KAAK,IAAI,yBAAyB,CAEhG;AAED,iBAAS,sBAAsB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAI5D;AAED,QAAA,MAAM,YAAY,qBAIhB,CAAC;AAUH,iBAAS,oBAAoB,IAAI;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAM7E"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
// This file must NOT import other files (except types), because they won't be resolved at runtime.
|
|
2
3
|
const scriptLoadResults = {};
|
|
3
4
|
if (!window.__cloudpack?.pageSessionContext) {
|
|
@@ -31,5 +32,4 @@ function getBrowserCacheRatio() {
|
|
|
31
32
|
}
|
|
32
33
|
window.__cloudpack ??= {};
|
|
33
34
|
window.__cloudpack.getBrowserCacheRatio = getBrowserCacheRatio;
|
|
34
|
-
export {};
|
|
35
35
|
//# sourceMappingURL=getBrowserCacheRatio.inline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getBrowserCacheRatio.inline.js","sourceRoot":"","sources":["../../src/inlineScripts/getBrowserCacheRatio.inline.ts"],"names":[],"mappings":"AAAA,mGAAmG;AAEnG,MAAM,iBAAiB,GAAwC,EAAE,CAAC;AAElE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAC5C,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,eAAe,GAAG,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,eAAe,CAAC;AAE9E,SAAS,2BAA2B,CAAC,KAAuB;IAC1D,OAAO,KAAK,CAAC,SAAS,KAAK,UAAU,CAAC;AACxC,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAsB;IACpD,IAAI,2BAA2B,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/E,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,CAAC;AACH,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,mBAAmB,CAAC,CAAC,IAAI,EAAE,EAAE;IACpD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;QACrC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,4DAA4D;AAC5D,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,CAAC;IAC7D,sBAAsB,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,0DAA0D;AAC1D,YAAY,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAE3D,SAAS,oBAAoB;IAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC;IACjG,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC;IACzD,MAAM,KAAK,GAAG,UAAU,GAAG,UAAU,CAAC;IAEtC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAW,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,WAAW,KAAK,EAAE,CAAC;AAC1B,MAAM,CAAC,WAAW,CAAC,oBAAoB,GAAG,oBAAoB,CAAC","sourcesContent":["// This file must NOT import other files (except types), because they won't be resolved at runtime.\n\nconst scriptLoadResults: Record<string, 'cache' | 'network'> = {};\n\nif (!window.__cloudpack?.pageSessionContext) {\n throw new Error('window.__cloudpack.pageSessionContext is not defined');\n}\n\nconst bundleServerUrl = window.__cloudpack.pageSessionContext.bundleServerUrl;\n\nfunction isPerformanceResourceTiming(entry: PerformanceEntry): entry is PerformanceResourceTiming {\n return entry.entryType === 'resource';\n}\n\nfunction handlePerformanceEntry(item: PerformanceEntry): void {\n if (isPerformanceResourceTiming(item) && item.name.startsWith(bundleServerUrl)) {\n scriptLoadResults[item.name] = item.transferSize === 0 ? 'cache' : 'network';\n }\n}\n\nconst perfObserver = new PerformanceObserver((list) => {\n for (const item of list.getEntries()) {\n handlePerformanceEntry(item);\n }\n});\n\n// Get all the resources that were loaded before this script\nfor (const entry of performance.getEntriesByType('resource')) {\n handlePerformanceEntry(entry);\n}\n\n// Observe all resources that are loaded after this script\nperfObserver.observe({ type: 'resource', buffered: true });\n\nfunction getBrowserCacheRatio(): { ratio: number; hit: number; total: number } {\n const cacheCount = Object.values(scriptLoadResults).filter((source) => source == 'cache').length;\n const totalCount = Object.keys(scriptLoadResults).length;\n const ratio = cacheCount / totalCount;\n\n return { ratio, hit: cacheCount, total: totalCount } as const;\n}\n\nwindow.__cloudpack ??= {};\nwindow.__cloudpack.getBrowserCacheRatio = getBrowserCacheRatio;\n"]}
|
|
1
|
+
{"version":3,"file":"getBrowserCacheRatio.inline.js","sourceRoot":"","sources":["../../src/inlineScripts/getBrowserCacheRatio.inline.ts"],"names":[],"mappings":";AAAA,mGAAmG;AAEnG,MAAM,iBAAiB,GAAwC,EAAE,CAAC;AAElE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAC5C,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,eAAe,GAAG,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,eAAe,CAAC;AAE9E,SAAS,2BAA2B,CAAC,KAAuB;IAC1D,OAAO,KAAK,CAAC,SAAS,KAAK,UAAU,CAAC;AACxC,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAsB;IACpD,IAAI,2BAA2B,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/E,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,CAAC;AACH,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,mBAAmB,CAAC,CAAC,IAAI,EAAE,EAAE;IACpD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;QACrC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,4DAA4D;AAC5D,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,CAAC;IAC7D,sBAAsB,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,0DAA0D;AAC1D,YAAY,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAE3D,SAAS,oBAAoB;IAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC;IACjG,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC;IACzD,MAAM,KAAK,GAAG,UAAU,GAAG,UAAU,CAAC;IAEtC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAW,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,WAAW,KAAK,EAAE,CAAC;AAC1B,MAAM,CAAC,WAAW,CAAC,oBAAoB,GAAG,oBAAoB,CAAC","sourcesContent":["// This file must NOT import other files (except types), because they won't be resolved at runtime.\n\nconst scriptLoadResults: Record<string, 'cache' | 'network'> = {};\n\nif (!window.__cloudpack?.pageSessionContext) {\n throw new Error('window.__cloudpack.pageSessionContext is not defined');\n}\n\nconst bundleServerUrl = window.__cloudpack.pageSessionContext.bundleServerUrl;\n\nfunction isPerformanceResourceTiming(entry: PerformanceEntry): entry is PerformanceResourceTiming {\n return entry.entryType === 'resource';\n}\n\nfunction handlePerformanceEntry(item: PerformanceEntry): void {\n if (isPerformanceResourceTiming(item) && item.name.startsWith(bundleServerUrl)) {\n scriptLoadResults[item.name] = item.transferSize === 0 ? 'cache' : 'network';\n }\n}\n\nconst perfObserver = new PerformanceObserver((list) => {\n for (const item of list.getEntries()) {\n handlePerformanceEntry(item);\n }\n});\n\n// Get all the resources that were loaded before this script\nfor (const entry of performance.getEntriesByType('resource')) {\n handlePerformanceEntry(entry);\n}\n\n// Observe all resources that are loaded after this script\nperfObserver.observe({ type: 'resource', buffered: true });\n\nfunction getBrowserCacheRatio(): { ratio: number; hit: number; total: number } {\n const cacheCount = Object.values(scriptLoadResults).filter((source) => source == 'cache').length;\n const totalCount = Object.keys(scriptLoadResults).length;\n const ratio = cacheCount / totalCount;\n\n return { ratio, hit: cacheCount, total: totalCount } as const;\n}\n\nwindow.__cloudpack ??= {};\nwindow.__cloudpack.getBrowserCacheRatio = getBrowserCacheRatio;\n"]}
|
|
@@ -23,7 +23,7 @@ function debounce(func, wait) {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
function hasMutationNonExcludedNodes(mutation) {
|
|
26
|
-
return
|
|
26
|
+
return Array.from(mutation.addedNodes).some((node) => {
|
|
27
27
|
const id = node.id;
|
|
28
28
|
if (id) {
|
|
29
29
|
return !excludedIds.includes(id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPageLoadTime.inline.js","sourceRoot":"","sources":["../../src/inlineScripts/getPageLoadTime.inline.ts"],"names":[],"mappings":"AAAA,mGAAmG;AAKnG,kGAAkG;AAClG,MAAM,gBAAgB,GAAgC,wBAAwB,CAAC;AAE/E;;;GAGG;AACH,MAAM,cAAc,GAAG,0BAA0B,CAAC;AAElD,8DAA8D;AAC9D,MAAM,WAAW,GAAa,CAAC,gBAAgB,CAAC,CAAC;AAIjD,MAAM,mBAAmB,GAAG,MAAM,CAAC;AACnC,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;AAE1D,SAAS,QAAQ,CAAsB,IAAqB,EAAE,IAAY;IACxE,IAAI,OAA6C,CAAC;IAElD,OAAO,UAAU,GAAG,IAAO;QACzB,IAAI,OAAO,EAAE,CAAC;YACZ,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YACxB,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAChB,CAAC,EAAE,IAAI,CAAC,CAAC;IACX,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAAC,QAAwB;IAC3D,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"getPageLoadTime.inline.js","sourceRoot":"","sources":["../../src/inlineScripts/getPageLoadTime.inline.ts"],"names":[],"mappings":"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","sourcesContent":["// This file must NOT import other files (except types), because they won't be resolved at runtime.\n\nimport type { PageLoadTimePerformanceEntry } from '@ms-cloudpack/common-types-browser';\nimport type { elementIds } from '@ms-cloudpack/overlay/constants';\n\n// Typing hack to ensure this ID is correct while working around the limitation on runtime imports\nconst overlayRootDivId: (typeof elementIds)['root'] = 'cloudpack-overlay-root';\n\n/**\n * Performance mark name for page load time.\n * This makes it easier to see the page load time in the performance tab in dev tools\n */\nconst pageLoadMarker = 'CLOUDPACK_PAGE_LOAD_TIME';\n\n// The below dom elements will be ignored by mutation observer\nconst excludedIds: string[] = [overlayRootDivId];\n\ntype DebounceFunc<T extends unknown[]> = (...args: T) => void;\n\nconst defaultPltEntryType = 'mark';\nconst defaultPltEntryTimeout = 5 * 60 * 1000; // 5 minutes\n\nfunction debounce<T extends unknown[]>(func: DebounceFunc<T>, wait: number): DebounceFunc<T> {\n let timeout: ReturnType<typeof setTimeout> | null;\n\n return function (...args: T) {\n if (timeout) {\n clearTimeout(timeout);\n }\n timeout = setTimeout(() => {\n timeout = null;\n func(...args);\n }, wait);\n };\n}\n\nfunction hasMutationNonExcludedNodes(mutation: MutationRecord): boolean {\n return Array.from(mutation.addedNodes).some((node) => {\n const id = (node as { id?: string }).id;\n\n if (id) {\n return !excludedIds.includes(id);\n }\n\n return true;\n });\n}\n\nconst waitForPerformancEntry = (pltPerfEntry: PageLoadTimePerformanceEntry): Promise<PerformanceEntry> => {\n return new Promise((resolve, reject) => {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n const observer = new PerformanceObserver((list) => {\n const entries = list.getEntriesByName(pltPerfEntry.name, pltPerfEntry.type);\n if (entries.length > 0) {\n observer.disconnect();\n if (timeout) {\n clearTimeout(timeout);\n timeout = null;\n }\n\n resolve(entries[entries.length - 1]);\n }\n });\n\n observer.observe({ entryTypes: [pltPerfEntry.type ?? defaultPltEntryType] });\n\n // Add a timeout to reject the promise if the entry is not found within a reasonable time\n timeout = setTimeout(() => {\n observer.disconnect();\n reject(new Error('Performance entry not found within the timeout period'));\n }, pltPerfEntry.timeout ?? defaultPltEntryTimeout);\n });\n};\n\nconst pageLoadTimePromise = new Promise<number>((resolve, reject) => {\n const pltPerfEntry = window.__cloudpack?.pageSessionContext?.pageLoadTimePerformanceEntry;\n if (pltPerfEntry) {\n // If the pageLoadTimePerformanceMark is set, wait for it and resolve the promise.\n // No need to observe the DOM changes.\n void waitForPerformancEntry(pltPerfEntry)\n .then((entry) => {\n resolve(entry.entryType == 'mark' ? entry.startTime : entry.duration);\n })\n .catch(reject);\n return;\n }\n\n const observer = new MutationObserver(domChanged);\n\n function reportLastAnimationTime(time: number) {\n // Stop observing the DOM\n observer.disconnect();\n\n // Resolve the promise with the page load time\n resolve(time);\n }\n\n const debouncedReportLastAnimationTime = debounce(reportLastAnimationTime, 2000 /* wait ms */);\n\n function domChanged(mutations: MutationRecord[]) {\n const shouldProcess = mutations.filter(hasMutationNonExcludedNodes).length > 0;\n\n if (shouldProcess) {\n requestAnimationFrame(() => {\n // Get the current time in ms since the time when navigation has started in window\n const time = performance.now();\n\n // Clear previous marks\n performance.clearMarks(pageLoadMarker);\n\n // Mark the page load time\n performance.mark(pageLoadMarker);\n\n // Report the page load time\n debouncedReportLastAnimationTime(time);\n });\n }\n }\n\n observer.observe(document.body, {\n childList: true,\n });\n});\n\nwindow.__cloudpack ??= {};\nwindow.__cloudpack.getPageLoadTime = () => pageLoadTimePromise;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderRoute.d.ts","sourceRoot":"","sources":["../../src/renderRoute/renderRoute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,qBAAqB,EAErB,4BAA4B,EAI7B,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"renderRoute.d.ts","sourceRoot":"","sources":["../../src/renderRoute/renderRoute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,qBAAqB,EAErB,4BAA4B,EAI7B,MAAM,4BAA4B,CAAC;AAUpC;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,4BAA4B,GAAG,IAAI,CAAC,CA6D9G"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { makeUrl } from '@ms-cloudpack/path-string-parsing';
|
|
2
2
|
import fsPromises from 'fs/promises';
|
|
3
|
-
import {
|
|
3
|
+
import { Window } from 'happy-dom';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { pathToFileURL } from 'url';
|
|
6
6
|
import { getDefaultHtmlResponse } from './getDefaultHtmlResponse.js';
|
|
7
7
|
import { getHtmlErrorResponse } from './getHtmlErrorResponse.js';
|
|
8
|
+
import HTMLSerializer from 'happy-dom/lib/html-serializer/HTMLSerializer.js';
|
|
8
9
|
/**
|
|
9
10
|
* Get the response for the given route. If the route has a custom render script, use that.
|
|
10
11
|
* Returns an error response if the file referenced by the script doesn't exist or throws an error.
|
|
@@ -50,7 +51,7 @@ export async function renderRoute(options) {
|
|
|
50
51
|
if (result.statusCode === 200 && isHtmlType(result.contentType)) {
|
|
51
52
|
if (isHtmlAcceptable(options)) {
|
|
52
53
|
// Inject the import map and scripts.
|
|
53
|
-
injectScripts(options, result);
|
|
54
|
+
await injectScripts(options, result);
|
|
54
55
|
}
|
|
55
56
|
else {
|
|
56
57
|
// It appears we're accidentally returning HTML when a different file type was requested.
|
|
@@ -150,15 +151,15 @@ async function renderCustomScript(params) {
|
|
|
150
151
|
*
|
|
151
152
|
* Note that this just logs an error rather than returning an error response if something fails, for now.
|
|
152
153
|
*/
|
|
153
|
-
function injectScripts(options, result) {
|
|
154
|
-
const { route, overlayScript, entryScripts, inlineScripts, importMap } = options;
|
|
155
|
-
|
|
154
|
+
async function injectScripts(options, result) {
|
|
155
|
+
const { route, overlayScript, entryScripts, inlineScripts, importMap, baseUrl } = options;
|
|
156
|
+
const window = new Window({ url: baseUrl });
|
|
156
157
|
try {
|
|
157
|
-
// TODO:
|
|
158
|
+
// TODO: happy-dom is overkill for what we're doing here--a full browser-like environment isn't
|
|
158
159
|
// needed to just parse and modify the HTML. If it becomes a perf concern (less likely since
|
|
159
160
|
// HTML page rendering is probably just done once per page load), we could switch to
|
|
160
161
|
// a pure parser like parse5 or htmlparser2.
|
|
161
|
-
|
|
162
|
+
window.document.write(result.content);
|
|
162
163
|
}
|
|
163
164
|
catch (e) {
|
|
164
165
|
// Trying to write a test for the above, it seemed very permissive, but catch just in case
|
|
@@ -166,7 +167,7 @@ function injectScripts(options, result) {
|
|
|
166
167
|
return;
|
|
167
168
|
}
|
|
168
169
|
try {
|
|
169
|
-
const
|
|
170
|
+
const document = window.document;
|
|
170
171
|
if (entryScripts || overlayScript) {
|
|
171
172
|
// Inject the import map at the top of the head, in case other scripts use it
|
|
172
173
|
addScript({ document, type: 'importmap', prepend: true, content: JSON.stringify(importMap, null, 2) });
|
|
@@ -183,7 +184,9 @@ function injectScripts(options, result) {
|
|
|
183
184
|
addScript({ document, url: entryScript });
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
|
-
|
|
187
|
+
const serializer = new HTMLSerializer();
|
|
188
|
+
result.content = serializer.serializeToString(document);
|
|
189
|
+
await window.happyDOM.close();
|
|
187
190
|
}
|
|
188
191
|
catch (e) {
|
|
189
192
|
console.error(`Error injecting scripts for route "${JSON.stringify(route.match)}":\n${e.stack || e}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderRoute.js","sourceRoot":"","sources":["../../src/renderRoute/renderRoute.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n RenderFunction,\n RenderFunctionOptions,\n RenderFunctionResult,\n ExpandedRenderFunctionResult,\n RenderedRoute,\n Request,\n RenderFunctionScript,\n} from '@ms-cloudpack/common-types';\nimport { makeUrl } from '@ms-cloudpack/path-string-parsing';\nimport fsPromises from 'fs/promises';\nimport { JSDOM } from 'jsdom';\nimport path from 'path';\nimport { pathToFileURL } from 'url';\nimport { getDefaultHtmlResponse } from './getDefaultHtmlResponse.js';\nimport { getHtmlErrorResponse } from './getHtmlErrorResponse.js';\n\n/**\n * Get the response for the given route. If the route has a custom render script, use that.\n * Returns an error response if the file referenced by the script doesn't exist or throws an error.\n */\nexport async function renderRoute(options: RenderFunctionOptions): Promise<ExpandedRenderFunctionResult | null> {\n const { route, session } = options;\n const { config } = session;\n const { appPath } = config;\n\n // Get an initial result from either the render script or default handler.\n let rawResult: RenderFunctionResult;\n const renderScriptPath = route.renderScript && path.resolve(appPath, route.renderScript);\n if (renderScriptPath) {\n const scriptExt = path.extname(renderScriptPath).toLowerCase();\n if (scriptExt === '.html' || scriptExt === '.htm') {\n rawResult = await readStaticHtml(renderScriptPath);\n } else {\n rawResult = await renderCustomScript({ ...options, renderScriptPath });\n }\n } else {\n rawResult = await getDefaultHtmlResponse(options);\n }\n\n if (rawResult === null) {\n // This means the custom renderScript fully handled the request.\n return null;\n }\n\n if (rawResult === undefined) {\n return makeErrorResponse({\n message:\n `returned undefined. If the renderScript fully handled the request (sent a response), ` +\n `return null instead. Otherwise ensure that the function returns the content to be rendered.`,\n route,\n req: options.req,\n renderScriptPath,\n });\n }\n\n const result: ExpandedRenderFunctionResult = {\n contentType: 'text/html',\n statusCode: 200,\n ...(typeof rawResult === 'string' ? { content: rawResult } : rawResult),\n };\n\n // If it's HTML and a success statusCode, inject the import map and appropriate scripts.\n if (result.statusCode === 200 && isHtmlType(result.contentType)) {\n if (isHtmlAcceptable(options)) {\n // Inject the import map and scripts.\n injectScripts(options, result);\n } else {\n // It appears we're accidentally returning HTML when a different file type was requested.\n // This could happen for overly broad route matches such as '*', or if no routes are configured.\n return makeErrorResponse({\n message:\n 'returned HTML, but this appears to be a non-HTML request. This is likely due to an ' +\n 'overly broad match or other misconfiguration of server.routes in the cloudpack config.',\n route,\n renderScriptPath,\n req: options.req,\n });\n }\n }\n\n return result;\n}\n\n/**\n * Fill in details of the message, log to console.error, and return an error response.\n * `Route ${route.match} with renderScript \"${renderScriptPath}\" ${message}`\n */\nfunction makeErrorResponse(params: {\n message: string;\n route: RenderedRoute;\n renderScriptPath: string | undefined;\n req: Request;\n}): ExpandedRenderFunctionResult {\n const { message, route, renderScriptPath, req } = params;\n const renderer = renderScriptPath ? `renderScript \"${renderScriptPath}\"` : 'the default renderer';\n const content = `Route ${JSON.stringify(route.match)} with ${renderer} ${message}`;\n console.error(`App server: request ${req.url} - ${content}`);\n\n return { statusCode: 500, contentType: 'text/plain', content };\n}\n\nfunction isHtmlAcceptable(options: Pick<RenderFunctionOptions, 'req' | 'baseUrl'>): boolean {\n const { req, baseUrl } = options;\n // Get the request path and extension (the URL.pathname conversion gets rid of any query or hash)\n const requestPath = makeUrl(req.url, baseUrl).pathname;\n const requestExt = path.extname(requestPath);\n // Determine whether HTML is (probably) an acceptable response type (can be refined later if needed).\n // In theory we should be able to use req.accepts() but not all requests set the accept header.\n return (!requestExt || requestExt.startsWith('.htm')) && !req.xhr && isHtmlType(req.headers.accept || '*/*');\n}\n\nfunction isHtmlType(acceptOrContentType: string): boolean {\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types\n return acceptOrContentType\n .split(',')\n .map((s) => s.split(';')[0].trim())\n .some((mime) => mime === '*/*' || /xml|x?html/i.test(mime) || /^(text|application)\\/\\*$/.test(mime));\n}\n\n/**\n * Load the default export from a JS file passed as the `renderScript` in a route,\n * and return either the result of running the function, or an error page if something fails.\n */\nasync function renderCustomScript(\n params: RenderFunctionOptions & { renderScriptPath: string },\n): Promise<RenderFunctionResult> {\n const { renderScriptPath, ...options } = params;\n // Get the html factory function from a script default export.\n const renderScriptUrl = pathToFileURL(renderScriptPath).toString();\n\n // Note: because there isn't a way to purge the require cache, we need to add a cache breaker query param to the\n // script path to ensure we get the latest version of the script. This could be improved by using the git hash of\n // the file if it exists, or a hash of the content, or even the timestamp of the file.\n let cacheBreakerQueryParam = `?t=${Date.now()}`;\n try {\n const { mtime } = await fsPromises.stat(renderScriptPath);\n cacheBreakerQueryParam = `?t=${mtime.getTime()}`;\n } catch {\n /* no-op */\n }\n\n // Try importing the script\n let createHtml: RenderFunction | undefined;\n let errorMessage: string | undefined;\n try {\n const importResult = ((await import(renderScriptUrl + cacheBreakerQueryParam)) as RenderFunctionScript).default;\n if (typeof importResult === 'function') {\n createHtml = importResult;\n } else {\n errorMessage = `The render script at \"${renderScriptPath}\" does not export a default function.`;\n }\n } catch (e) {\n errorMessage = `Error importing render script at \"${renderScriptUrl}\":\\n${(e as Error).stack || e}`;\n }\n\n if (createHtml) {\n // Try running the script\n try {\n return await createHtml(options);\n } catch (e) {\n errorMessage = `Error running render script at \"${renderScriptPath}\":\\n${(e as Error).stack || e}`;\n }\n }\n\n // Return an error page. Doing this instead of returning a default or empty response ensures that\n // the user is aware of any configuration issues.\n errorMessage ??= `Unknown error loading render script at \"${renderScriptPath}\".`;\n console.error(errorMessage);\n return getHtmlErrorResponse(errorMessage);\n}\n\n/**\n * Modify the HTML response by injecting the import map, inline scripts, and entry/overlay scripts.\n *\n * Note that this just logs an error rather than returning an error response if something fails, for now.\n */\nfunction injectScripts(options: RenderFunctionOptions, result: ExpandedRenderFunctionResult): void {\n const { route, overlayScript, entryScripts, inlineScripts, importMap } = options;\n let jsdom: JSDOM;\n try {\n // TODO: JSDOM is overkill for what we're doing here--a full browser-like environment isn't\n // needed to just parse and modify the HTML. If it becomes a perf concern (less likely since\n // HTML page rendering is probably just done once per page load), we could switch to\n // a pure parser like parse5 or htmlparser2.\n jsdom = new JSDOM(result.content, { contentType: result.contentType } as ConstructorParameters<typeof JSDOM>[1]);\n } catch (e) {\n // Trying to write a test for the above, it seemed very permissive, but catch just in case\n console.error(\n `Error parsing html response for rendering route \"${JSON.stringify(route.match)}\":\\n${(e as Error).stack || e}`,\n );\n return;\n }\n\n try {\n const { document } = jsdom.window;\n\n if (entryScripts || overlayScript) {\n // Inject the import map at the top of the head, in case other scripts use it\n addScript({ document, type: 'importmap', prepend: true, content: JSON.stringify(importMap, null, 2) });\n }\n\n if (inlineScripts) {\n for (const inlineScript of inlineScripts) {\n addScript({ document, content: inlineScript });\n }\n }\n\n // inject the overlay and entry scripts\n addScript({ document, url: overlayScript });\n\n if (entryScripts) {\n for (const entryScript of entryScripts) {\n addScript({ document, url: entryScript });\n }\n }\n\n result.content = jsdom.serialize();\n } catch (e) {\n console.error(`Error injecting scripts for route \"${JSON.stringify(route.match)}\":\\n${(e as Error).stack || e}`);\n }\n}\n\n/**\n * Helper function to add a script to the document.\n * No-op if neither `url` nor `content` is provided.\n */\nfunction addScript(params: {\n document: Document;\n type?: string;\n prepend?: boolean;\n url?: string;\n content?: string;\n}): void {\n const { document, type = 'module', prepend, url, content } = params;\n if (!url && !content) {\n return;\n }\n\n const script = document.createElement('script');\n script.type = type;\n if (url) {\n script.src = url;\n } else if (content) {\n script.innerHTML = content;\n }\n\n if (prepend) {\n document.head.prepend(script);\n } else {\n document.head.appendChild(script);\n }\n}\n\n/**\n * Read a static HTML file, or return an error response if the file can't be read.\n */\nasync function readStaticHtml(renderScriptPath: string): Promise<RenderFunctionResult> {\n try {\n return (await fsPromises.readFile(renderScriptPath, 'utf8')) || '';\n } catch (e) {\n const message = `Error reading HTML file at \"${renderScriptPath}\":\\n${(e as Error).stack || e}`;\n console.error(message);\n return getHtmlErrorResponse(message);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"renderRoute.js","sourceRoot":"","sources":["../../src/renderRoute/renderRoute.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n RenderFunction,\n RenderFunctionOptions,\n RenderFunctionResult,\n ExpandedRenderFunctionResult,\n RenderedRoute,\n Request,\n RenderFunctionScript,\n} from '@ms-cloudpack/common-types';\nimport { makeUrl } from '@ms-cloudpack/path-string-parsing';\nimport fsPromises from 'fs/promises';\nimport { Window, type Document } from 'happy-dom';\nimport path from 'path';\nimport { pathToFileURL } from 'url';\nimport { getDefaultHtmlResponse } from './getDefaultHtmlResponse.js';\nimport { getHtmlErrorResponse } from './getHtmlErrorResponse.js';\nimport HTMLSerializer from 'happy-dom/lib/html-serializer/HTMLSerializer.js';\n\n/**\n * Get the response for the given route. If the route has a custom render script, use that.\n * Returns an error response if the file referenced by the script doesn't exist or throws an error.\n */\nexport async function renderRoute(options: RenderFunctionOptions): Promise<ExpandedRenderFunctionResult | null> {\n const { route, session } = options;\n const { config } = session;\n const { appPath } = config;\n\n // Get an initial result from either the render script or default handler.\n let rawResult: RenderFunctionResult;\n const renderScriptPath = route.renderScript && path.resolve(appPath, route.renderScript);\n if (renderScriptPath) {\n const scriptExt = path.extname(renderScriptPath).toLowerCase();\n if (scriptExt === '.html' || scriptExt === '.htm') {\n rawResult = await readStaticHtml(renderScriptPath);\n } else {\n rawResult = await renderCustomScript({ ...options, renderScriptPath });\n }\n } else {\n rawResult = await getDefaultHtmlResponse(options);\n }\n\n if (rawResult === null) {\n // This means the custom renderScript fully handled the request.\n return null;\n }\n\n if (rawResult === undefined) {\n return makeErrorResponse({\n message:\n `returned undefined. If the renderScript fully handled the request (sent a response), ` +\n `return null instead. Otherwise ensure that the function returns the content to be rendered.`,\n route,\n req: options.req,\n renderScriptPath,\n });\n }\n\n const result: ExpandedRenderFunctionResult = {\n contentType: 'text/html',\n statusCode: 200,\n ...(typeof rawResult === 'string' ? { content: rawResult } : rawResult),\n };\n\n // If it's HTML and a success statusCode, inject the import map and appropriate scripts.\n if (result.statusCode === 200 && isHtmlType(result.contentType)) {\n if (isHtmlAcceptable(options)) {\n // Inject the import map and scripts.\n await injectScripts(options, result);\n } else {\n // It appears we're accidentally returning HTML when a different file type was requested.\n // This could happen for overly broad route matches such as '*', or if no routes are configured.\n return makeErrorResponse({\n message:\n 'returned HTML, but this appears to be a non-HTML request. This is likely due to an ' +\n 'overly broad match or other misconfiguration of server.routes in the cloudpack config.',\n route,\n renderScriptPath,\n req: options.req,\n });\n }\n }\n\n return result;\n}\n\n/**\n * Fill in details of the message, log to console.error, and return an error response.\n * `Route ${route.match} with renderScript \"${renderScriptPath}\" ${message}`\n */\nfunction makeErrorResponse(params: {\n message: string;\n route: RenderedRoute;\n renderScriptPath: string | undefined;\n req: Request;\n}): ExpandedRenderFunctionResult {\n const { message, route, renderScriptPath, req } = params;\n const renderer = renderScriptPath ? `renderScript \"${renderScriptPath}\"` : 'the default renderer';\n const content = `Route ${JSON.stringify(route.match)} with ${renderer} ${message}`;\n console.error(`App server: request ${req.url} - ${content}`);\n\n return { statusCode: 500, contentType: 'text/plain', content };\n}\n\nfunction isHtmlAcceptable(options: Pick<RenderFunctionOptions, 'req' | 'baseUrl'>): boolean {\n const { req, baseUrl } = options;\n // Get the request path and extension (the URL.pathname conversion gets rid of any query or hash)\n const requestPath = makeUrl(req.url, baseUrl).pathname;\n const requestExt = path.extname(requestPath);\n // Determine whether HTML is (probably) an acceptable response type (can be refined later if needed).\n // In theory we should be able to use req.accepts() but not all requests set the accept header.\n return (!requestExt || requestExt.startsWith('.htm')) && !req.xhr && isHtmlType(req.headers.accept || '*/*');\n}\n\nfunction isHtmlType(acceptOrContentType: string): boolean {\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types\n return acceptOrContentType\n .split(',')\n .map((s) => s.split(';')[0].trim())\n .some((mime) => mime === '*/*' || /xml|x?html/i.test(mime) || /^(text|application)\\/\\*$/.test(mime));\n}\n\n/**\n * Load the default export from a JS file passed as the `renderScript` in a route,\n * and return either the result of running the function, or an error page if something fails.\n */\nasync function renderCustomScript(\n params: RenderFunctionOptions & { renderScriptPath: string },\n): Promise<RenderFunctionResult> {\n const { renderScriptPath, ...options } = params;\n // Get the html factory function from a script default export.\n const renderScriptUrl = pathToFileURL(renderScriptPath).toString();\n\n // Note: because there isn't a way to purge the require cache, we need to add a cache breaker query param to the\n // script path to ensure we get the latest version of the script. This could be improved by using the git hash of\n // the file if it exists, or a hash of the content, or even the timestamp of the file.\n let cacheBreakerQueryParam = `?t=${Date.now()}`;\n try {\n const { mtime } = await fsPromises.stat(renderScriptPath);\n cacheBreakerQueryParam = `?t=${mtime.getTime()}`;\n } catch {\n /* no-op */\n }\n\n // Try importing the script\n let createHtml: RenderFunction | undefined;\n let errorMessage: string | undefined;\n try {\n const importResult = ((await import(renderScriptUrl + cacheBreakerQueryParam)) as RenderFunctionScript).default;\n if (typeof importResult === 'function') {\n createHtml = importResult;\n } else {\n errorMessage = `The render script at \"${renderScriptPath}\" does not export a default function.`;\n }\n } catch (e) {\n errorMessage = `Error importing render script at \"${renderScriptUrl}\":\\n${(e as Error).stack || e}`;\n }\n\n if (createHtml) {\n // Try running the script\n try {\n return await createHtml(options);\n } catch (e) {\n errorMessage = `Error running render script at \"${renderScriptPath}\":\\n${(e as Error).stack || e}`;\n }\n }\n\n // Return an error page. Doing this instead of returning a default or empty response ensures that\n // the user is aware of any configuration issues.\n errorMessage ??= `Unknown error loading render script at \"${renderScriptPath}\".`;\n console.error(errorMessage);\n return getHtmlErrorResponse(errorMessage);\n}\n\n/**\n * Modify the HTML response by injecting the import map, inline scripts, and entry/overlay scripts.\n *\n * Note that this just logs an error rather than returning an error response if something fails, for now.\n */\nasync function injectScripts(options: RenderFunctionOptions, result: ExpandedRenderFunctionResult): Promise<void> {\n const { route, overlayScript, entryScripts, inlineScripts, importMap, baseUrl } = options;\n const window = new Window({ url: baseUrl });\n try {\n // TODO: happy-dom is overkill for what we're doing here--a full browser-like environment isn't\n // needed to just parse and modify the HTML. If it becomes a perf concern (less likely since\n // HTML page rendering is probably just done once per page load), we could switch to\n // a pure parser like parse5 or htmlparser2.\n window.document.write(result.content);\n } catch (e) {\n // Trying to write a test for the above, it seemed very permissive, but catch just in case\n console.error(\n `Error parsing html response for rendering route \"${JSON.stringify(route.match)}\":\\n${(e as Error).stack || e}`,\n );\n return;\n }\n\n try {\n const document = window.document;\n\n if (entryScripts || overlayScript) {\n // Inject the import map at the top of the head, in case other scripts use it\n addScript({ document, type: 'importmap', prepend: true, content: JSON.stringify(importMap, null, 2) });\n }\n\n if (inlineScripts) {\n for (const inlineScript of inlineScripts) {\n addScript({ document, content: inlineScript });\n }\n }\n\n // inject the overlay and entry scripts\n addScript({ document, url: overlayScript });\n\n if (entryScripts) {\n for (const entryScript of entryScripts) {\n addScript({ document, url: entryScript });\n }\n }\n\n const serializer = new HTMLSerializer();\n result.content = serializer.serializeToString(document);\n await window.happyDOM.close();\n } catch (e) {\n console.error(`Error injecting scripts for route \"${JSON.stringify(route.match)}\":\\n${(e as Error).stack || e}`);\n }\n}\n\n/**\n * Helper function to add a script to the document.\n * No-op if neither `url` nor `content` is provided.\n */\nfunction addScript(params: {\n document: Document;\n type?: string;\n prepend?: boolean;\n url?: string;\n content?: string;\n}): void {\n const { document, type = 'module', prepend, url, content } = params;\n if (!url && !content) {\n return;\n }\n\n const script = document.createElement('script');\n script.type = type;\n if (url) {\n script.src = url;\n } else if (content) {\n script.innerHTML = content;\n }\n\n if (prepend) {\n document.head.prepend(script);\n } else {\n document.head.appendChild(script);\n }\n}\n\n/**\n * Read a static HTML file, or return an error response if the file can't be read.\n */\nasync function readStaticHtml(renderScriptPath: string): Promise<RenderFunctionResult> {\n try {\n return (await fsPromises.readFile(renderScriptPath, 'utf8')) || '';\n } catch (e) {\n const message = `Error reading HTML file at \"${renderScriptPath}\":\\n${(e as Error).stack || e}`;\n console.error(message);\n return getHtmlErrorResponse(message);\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ms-cloudpack/app-server",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.58",
|
|
4
4
|
"description": "An implementation of the App server for Cloudpack.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -14,24 +14,23 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@ms-cloudpack/api-server": "^0.61.
|
|
18
|
-
"@ms-cloudpack/bundle-server": "^0.6.
|
|
17
|
+
"@ms-cloudpack/api-server": "^0.61.6",
|
|
18
|
+
"@ms-cloudpack/bundle-server": "^0.6.67",
|
|
19
19
|
"@ms-cloudpack/common-types": "^0.24.10",
|
|
20
20
|
"@ms-cloudpack/create-express-app": "^1.10.22",
|
|
21
21
|
"@ms-cloudpack/import-map": "^0.10.1",
|
|
22
|
-
"@ms-cloudpack/overlay": "^0.17.
|
|
22
|
+
"@ms-cloudpack/overlay": "^0.17.139",
|
|
23
23
|
"@ms-cloudpack/path-string-parsing": "^1.2.6",
|
|
24
24
|
"@ms-cloudpack/path-utilities": "^3.0.7",
|
|
25
25
|
"@ms-cloudpack/task-reporter": "^0.15.1",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
26
|
+
"happy-dom": "^17.1.1",
|
|
27
|
+
"http-proxy-middleware": "^2.0.6"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@ms-cloudpack/common-types-browser": "^0.5.4",
|
|
31
31
|
"@ms-cloudpack/eslint-plugin-internal": "^0.0.1",
|
|
32
32
|
"@ms-cloudpack/scripts": "^0.0.1",
|
|
33
|
-
"@ms-cloudpack/test-utilities": "^0.5.0"
|
|
34
|
-
"@types/jsdom": "^21.1.1"
|
|
33
|
+
"@ms-cloudpack/test-utilities": "^0.5.0"
|
|
35
34
|
},
|
|
36
35
|
"scripts": {
|
|
37
36
|
"api": "cloudpack-scripts api",
|