tungsten 0.3.1 → 0.3.3
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/dist/.build-complete +1 -0
- package/dist/Components.d.ts +2 -1
- package/dist/Components.d.ts.map +1 -1
- package/dist/Components.js +10 -1
- package/dist/DomRegion.js +1 -1
- package/dist/Framework.d.ts +2 -0
- package/dist/Framework.d.ts.map +1 -1
- package/dist/Framework.js +68 -57
- package/dist/FrameworkConfig.d.ts +6 -0
- package/dist/FrameworkConfig.d.ts.map +1 -1
- package/dist/FunctionComponentStandIn.d.ts +2 -0
- package/dist/FunctionComponentStandIn.d.ts.map +1 -1
- package/dist/FunctionComponentStandIn.js +10 -1
- package/dist/Instance/Instance.d.ts.map +1 -1
- package/dist/Instance/Instance.js +18 -1
- package/dist/Instance/InstanceConfig.d.ts +1 -0
- package/dist/Instance/InstanceConfig.d.ts.map +1 -1
- package/dist/PopMessage.type.d.ts +6 -0
- package/dist/PopMessage.type.d.ts.map +1 -0
- package/dist/PopMessage.type.js +1 -0
- package/dist/Servers/DevServer.d.ts +4 -0
- package/dist/Servers/DevServer.d.ts.map +1 -1
- package/dist/Servers/DevServer.js +116 -13
- package/dist/Servers/MatchedRouteInfo.d.ts +1 -1
- package/dist/Servers/MatchedRouteInfo.d.ts.map +1 -1
- package/dist/Servers/ProdServer.d.ts +1 -0
- package/dist/Servers/ProdServer.d.ts.map +1 -1
- package/dist/Servers/ProdServer.js +79 -5
- package/dist/Servers/devErrorPageAutoRetry.d.ts +4 -0
- package/dist/Servers/devErrorPageAutoRetry.d.ts.map +1 -0
- package/dist/Servers/devErrorPageAutoRetry.js +26 -0
- package/dist/Servers/hono/DevServerHono.js +25 -29
- package/dist/Servers/hono/ProdServerHono.js +49 -142
- package/dist/Servers/hono/TungstenServerHono.d.ts +1 -1
- package/dist/Servers/hono/TungstenServerHono.d.ts.map +1 -1
- package/dist/Servers/hono/TungstenServerHono.js +12 -29
- package/dist/Servers/routing.d.ts.map +1 -1
- package/dist/Servers/routing.js +10 -6
- package/dist/Servers/tungstenCorePrivateEnvSchema.d.ts +0 -3
- package/dist/Servers/tungstenCorePrivateEnvSchema.d.ts.map +1 -1
- package/dist/Servers/tungstenCorePrivateEnvSchema.js +3 -3
- package/dist/Servers/tungstenCorePublicEnvSchema.d.ts +8 -0
- package/dist/Servers/tungstenCorePublicEnvSchema.d.ts.map +1 -0
- package/dist/Servers/tungstenCorePublicEnvSchema.js +14 -0
- package/dist/Store/InternalStoreSchema.d.ts +2 -0
- package/dist/Store/InternalStoreSchema.d.ts.map +1 -1
- package/dist/Store/InternalStoreSchema.js +1 -0
- package/dist/api/Request.d.ts +1 -1
- package/dist/api/Request.d.ts.map +1 -1
- package/dist/api/Response.d.ts +1 -1
- package/dist/api/Response.d.ts.map +1 -1
- package/dist/api/getExport.d.ts.map +1 -1
- package/dist/api/getExport.js +2 -1
- package/dist/babelPlugins/BabelAddDevCacheBust.d.ts +11 -0
- package/dist/babelPlugins/BabelAddDevCacheBust.d.ts.map +1 -0
- package/dist/babelPlugins/BabelAddDevCacheBust.js +68 -0
- package/dist/babelPlugins/BabelTypes.d.ts +2 -2
- package/dist/babelPlugins/BabelTypes.d.ts.map +1 -1
- package/dist/babelPlugins/BabelTypes.js +0 -1
- package/dist/bin/commands/build.d.ts.map +1 -1
- package/dist/bin/commands/build.js +3 -0
- package/dist/bin/commands/dev.d.ts.map +1 -1
- package/dist/bin/commands/dev.js +16 -3
- package/dist/bin/commands/devmon.d.ts +2 -0
- package/dist/bin/commands/devmon.d.ts.map +1 -0
- package/dist/bin/commands/devmon.js +66 -0
- package/dist/bin/index.d.ts.map +1 -1
- package/dist/bin/index.js +6 -0
- package/dist/booleanAttributeValue.d.ts +21 -0
- package/dist/booleanAttributeValue.d.ts.map +1 -0
- package/dist/booleanAttributeValue.js +23 -0
- package/dist/build/compileJavascript.js +1 -1
- package/dist/build/compileUserApp.d.ts +2 -1
- package/dist/build/compileUserApp.d.ts.map +1 -1
- package/dist/build/compileUserApp.js +10 -9
- package/dist/build/createInstanceConfigFile.js +1 -1
- package/dist/build/makeBabelUserDevConfig.d.ts.map +1 -1
- package/dist/build/makeBabelUserDevConfig.js +6 -1
- package/dist/compat/types.d.ts +1 -1
- package/dist/compat/types.d.ts.map +1 -1
- package/dist/components/PopMessages.d.ts +12 -0
- package/dist/components/PopMessages.d.ts.map +1 -0
- package/dist/components/PopMessages.js +45 -0
- package/dist/defaultConfig.d.ts +3 -0
- package/dist/defaultConfig.d.ts.map +1 -1
- package/dist/defaultConfig.js +4 -1
- package/dist/env/Interfaces.d.ts +2 -1
- package/dist/env/Interfaces.d.ts.map +1 -1
- package/dist/env/getEnvSchemas.d.ts +1 -1
- package/dist/env/getEnvSchemas.d.ts.map +1 -1
- package/dist/env/getEnvSchemas.js +2 -1
- package/dist/env/publicEnv.d.ts.map +1 -1
- package/dist/env/publicEnv.js +4 -1
- package/dist/frameworkConfigSchema.d.ts +4 -0
- package/dist/frameworkConfigSchema.d.ts.map +1 -1
- package/dist/frameworkConfigSchema.js +2 -1
- package/dist/getComponent.d.ts.map +1 -1
- package/dist/getComponent.js +2 -1
- package/dist/getRoutes.d.ts.map +1 -1
- package/dist/getRoutes.js +2 -1
- package/dist/hmr/applyHmrModule.d.ts +11 -0
- package/dist/hmr/applyHmrModule.d.ts.map +1 -0
- package/dist/hmr/applyHmrModule.js +78 -0
- package/dist/hmr/componentIdentity.d.ts +9 -0
- package/dist/hmr/componentIdentity.d.ts.map +1 -0
- package/dist/hmr/componentIdentity.js +17 -0
- package/dist/hmr/instanceRegistry.d.ts +4 -0
- package/dist/hmr/instanceRegistry.d.ts.map +1 -0
- package/dist/hmr/instanceRegistry.js +6 -0
- package/dist/hmr/liveReloadHub.d.ts +10 -0
- package/dist/hmr/liveReloadHub.d.ts.map +1 -0
- package/dist/{dev → hmr}/liveReloadHub.js +8 -2
- package/dist/hmr/refreshStylesheets.d.ts +2 -0
- package/dist/hmr/refreshStylesheets.d.ts.map +1 -0
- package/dist/hmr/refreshStylesheets.js +26 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useInstance.d.ts +3 -0
- package/dist/hooks/useInstance.d.ts.map +1 -0
- package/dist/hooks/useInstance.js +4 -0
- package/dist/hydrate/hydrate.d.ts +10 -0
- package/dist/hydrate/hydrate.d.ts.map +1 -1
- package/dist/hydrate/hydrate.js +81 -19
- package/dist/hydrate/reconcileHydratedAttributes.d.ts.map +1 -1
- package/dist/hydrate/reconcileHydratedAttributes.js +14 -5
- package/dist/hydrate/renderHydrationMismatchBanner.d.ts +7 -0
- package/dist/hydrate/renderHydrationMismatchBanner.d.ts.map +1 -0
- package/dist/hydrate/renderHydrationMismatchBanner.js +69 -0
- package/dist/importDevModuleWithRetry.d.ts +3 -0
- package/dist/importDevModuleWithRetry.d.ts.map +1 -0
- package/dist/importDevModuleWithRetry.js +46 -0
- package/dist/indexInner.d.ts +8 -0
- package/dist/indexInner.d.ts.map +1 -1
- package/dist/indexInner.js +7 -1
- package/dist/makeInstanceConfigFromFrameworkConfig.d.ts.map +1 -1
- package/dist/makeInstanceConfigFromFrameworkConfig.js +2 -1
- package/dist/pop.d.ts +10 -0
- package/dist/pop.d.ts.map +1 -0
- package/dist/pop.js +49 -0
- package/dist/rawHtml/filterContentNode.d.ts +20 -0
- package/dist/rawHtml/filterContentNode.d.ts.map +1 -0
- package/dist/rawHtml/filterContentNode.js +96 -0
- package/dist/rawHtml/parseHtml.d.ts +14 -0
- package/dist/rawHtml/parseHtml.d.ts.map +1 -1
- package/dist/rawHtml/parseHtml.js +4 -4
- package/dist/rawHtml/sanitizeHtml.d.ts +17 -0
- package/dist/rawHtml/sanitizeHtml.d.ts.map +1 -0
- package/dist/rawHtml/sanitizeHtml.js +19 -0
- package/dist/render/HeadData.d.ts +2 -0
- package/dist/render/HeadData.d.ts.map +1 -1
- package/dist/render/contentNodeToHtml.d.ts +18 -0
- package/dist/render/contentNodeToHtml.d.ts.map +1 -0
- package/dist/render/contentNodeToHtml.js +66 -0
- package/dist/render/contentToHtml.d.ts.map +1 -1
- package/dist/render/contentToHtml.js +3 -1
- package/dist/render/processHead.d.ts.map +1 -1
- package/dist/render/processHead.js +53 -6
- package/dist/render/renderingTreeToHtml.d.ts.map +1 -1
- package/dist/render/renderingTreeToHtml.js +8 -1
- package/dist/routing/ErrorRouteType.d.ts +6 -0
- package/dist/routing/ErrorRouteType.d.ts.map +1 -0
- package/dist/routing/ErrorRouteType.js +1 -0
- package/dist/routing/RouteTypes.d.ts +2 -1
- package/dist/routing/RouteTypes.d.ts.map +1 -1
- package/dist/routing/Routes.d.ts +5 -0
- package/dist/routing/Routes.d.ts.map +1 -1
- package/dist/routing/TungstenErrorInfo.d.ts +6 -0
- package/dist/routing/TungstenErrorInfo.d.ts.map +1 -0
- package/dist/routing/TungstenErrorInfo.js +6 -0
- package/dist/style/styleContentSxy.js +21 -0
- package/dist/testing/hydrateTestApp.d.ts +38 -0
- package/dist/testing/hydrateTestApp.d.ts.map +1 -0
- package/dist/testing/hydrateTestApp.js +242 -0
- package/dist/testing/index.d.ts +4 -3
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +16 -2
- package/dist/timeProfiler.d.ts +6 -0
- package/dist/timeProfiler.d.ts.map +1 -0
- package/dist/timeProfiler.js +31 -0
- package/dist/update/integrateUpdateVdom.d.ts +16 -1
- package/dist/update/integrateUpdateVdom.d.ts.map +1 -1
- package/dist/update/integrateUpdateVdom.js +116 -7
- package/dist/warnOnFrameworkChange.d.ts +2 -0
- package/dist/warnOnFrameworkChange.d.ts.map +1 -0
- package/dist/warnOnFrameworkChange.js +27 -0
- package/package.json +18 -16
- package/dist/Instance/gotoRedirect.sxyt.d.ts +0 -2
- package/dist/Instance/gotoRedirect.sxyt.d.ts.map +0 -1
- package/dist/Instance/gotoRedirect.sxyt.js +0 -148
- package/dist/Instance/runTrackedWork.sxyt.d.ts +0 -2
- package/dist/Instance/runTrackedWork.sxyt.d.ts.map +0 -1
- package/dist/Instance/runTrackedWork.sxyt.js +0 -35
- package/dist/_client/cjsHelpers.sxyt.d.ts +0 -2
- package/dist/_client/cjsHelpers.sxyt.d.ts.map +0 -1
- package/dist/_client/cjsHelpers.sxyt.js +0 -45
- package/dist/auth/passwordHashing.sxyt.d.ts +0 -2
- package/dist/auth/passwordHashing.sxyt.d.ts.map +0 -1
- package/dist/auth/passwordHashing.sxyt.js +0 -46
- package/dist/auth/ref/checkPasswordResetToken.sxyt.d.ts +0 -2
- package/dist/auth/ref/checkPasswordResetToken.sxyt.d.ts.map +0 -1
- package/dist/auth/ref/checkPasswordResetToken.sxyt.js +0 -40
- package/dist/auth/ref/createPasswordResetToken.sxyt.d.ts +0 -2
- package/dist/auth/ref/createPasswordResetToken.sxyt.d.ts.map +0 -1
- package/dist/auth/ref/createPasswordResetToken.sxyt.js +0 -10
- package/dist/babelPlugins/fixImportsInSassErrorMessage.sxyt.d.ts +0 -2
- package/dist/babelPlugins/fixImportsInSassErrorMessage.sxyt.d.ts.map +0 -1
- package/dist/babelPlugins/fixImportsInSassErrorMessage.sxyt.js +0 -108
- package/dist/babelPlugins/transformPackageImports/resolveBareImport.sxyt.d.ts +0 -2
- package/dist/babelPlugins/transformPackageImports/resolveBareImport.sxyt.d.ts.map +0 -1
- package/dist/babelPlugins/transformPackageImports/resolveBareImport.sxyt.js +0 -104
- package/dist/bin/commands/compile.sxyt.d.ts +0 -2
- package/dist/bin/commands/compile.sxyt.d.ts.map +0 -1
- package/dist/bin/commands/compile.sxyt.js +0 -255
- package/dist/build/modifySassImports.sxyt.d.ts +0 -2
- package/dist/build/modifySassImports.sxyt.d.ts.map +0 -1
- package/dist/build/modifySassImports.sxyt.js +0 -55
- package/dist/build/sassImportParser.sxyt.d.ts +0 -2
- package/dist/build/sassImportParser.sxyt.d.ts.map +0 -1
- package/dist/build/sassImportParser.sxyt.js +0 -110
- package/dist/build/scssImportParserChatgpt.sxyt.d.ts +0 -2
- package/dist/build/scssImportParserChatgpt.sxyt.d.ts.map +0 -1
- package/dist/build/scssImportParserChatgpt.sxyt.js +0 -120
- package/dist/clone.sxyt.d.ts +0 -2
- package/dist/clone.sxyt.d.ts.map +0 -1
- package/dist/clone.sxyt.js +0 -24
- package/dist/componentProxyHandlers.sxyt.d.ts +0 -2
- package/dist/componentProxyHandlers.sxyt.d.ts.map +0 -1
- package/dist/componentProxyHandlers.sxyt.js +0 -130
- package/dist/components/RawHtml.sxyt.d.ts +0 -2
- package/dist/components/RawHtml.sxyt.d.ts.map +0 -1
- package/dist/components/RawHtml.sxyt.js +0 -104
- package/dist/components/bindable/BindableSelect.sxyt.d.ts +0 -2
- package/dist/components/bindable/BindableSelect.sxyt.d.ts.map +0 -1
- package/dist/components/bindable/BindableSelect.sxyt.js +0 -186
- package/dist/dev/liveReloadHub.d.ts +0 -6
- package/dist/dev/liveReloadHub.d.ts.map +0 -1
- package/dist/env/injectEnv.sxyt.d.ts +0 -2
- package/dist/env/injectEnv.sxyt.d.ts.map +0 -1
- package/dist/env/injectEnv.sxyt.js +0 -20
- package/dist/env/parseEnv.sxyt.d.ts +0 -2
- package/dist/env/parseEnv.sxyt.d.ts.map +0 -1
- package/dist/env/parseEnv.sxyt.js +0 -11
- package/dist/findProjectDir.sxyt.d.ts +0 -2
- package/dist/findProjectDir.sxyt.d.ts.map +0 -1
- package/dist/findProjectDir.sxyt.js +0 -82
- package/dist/hydrate/reconcileHydratedAttributes.sxyt.d.ts +0 -2
- package/dist/hydrate/reconcileHydratedAttributes.sxyt.d.ts.map +0 -1
- package/dist/hydrate/reconcileHydratedAttributes.sxyt.js +0 -173
- package/dist/innerHtmlFromProps.sxyt.d.ts +0 -2
- package/dist/innerHtmlFromProps.sxyt.d.ts.map +0 -1
- package/dist/innerHtmlFromProps.sxyt.js +0 -99
- package/dist/postcssPlugins/parseSelectors.sxyt.d.ts +0 -2
- package/dist/postcssPlugins/parseSelectors.sxyt.d.ts.map +0 -1
- package/dist/postcssPlugins/parseSelectors.sxyt.js +0 -62
- package/dist/postcssPlugins/parseSelectorsRich.sxyt.d.ts +0 -2
- package/dist/postcssPlugins/parseSelectorsRich.sxyt.d.ts.map +0 -1
- package/dist/postcssPlugins/parseSelectorsRich.sxyt.js +0 -155
- package/dist/rawHtml/parseHtml.sxyt.d.ts +0 -2
- package/dist/rawHtml/parseHtml.sxyt.d.ts.map +0 -1
- package/dist/rawHtml/parseHtml.sxyt.js +0 -239
- package/dist/render/getFunctionBodyAsString.sxyt.d.ts +0 -2
- package/dist/render/getFunctionBodyAsString.sxyt.d.ts.map +0 -1
- package/dist/render/getFunctionBodyAsString.sxyt.js +0 -37
- package/dist/render/processProps.sxyt.d.ts +0 -2
- package/dist/render/processProps.sxyt.d.ts.map +0 -1
- package/dist/render/processProps.sxyt.js +0 -90
- package/dist/routing/compareRequestToRegex.sxyt.d.ts +0 -2
- package/dist/routing/compareRequestToRegex.sxyt.d.ts.map +0 -1
- package/dist/routing/compareRequestToRegex.sxyt.js +0 -65
- package/dist/routing/getPathPriority.sxyt.d.ts +0 -2
- package/dist/routing/getPathPriority.sxyt.d.ts.map +0 -1
- package/dist/routing/getPathPriority.sxyt.js +0 -24
- package/dist/routing/matchPath.sxyt.d.ts +0 -2
- package/dist/routing/matchPath.sxyt.d.ts.map +0 -1
- package/dist/routing/matchPath.sxyt.js +0 -41
- package/dist/routing/patternToRegex.sxyt.d.ts +0 -2
- package/dist/routing/patternToRegex.sxyt.d.ts.map +0 -1
- package/dist/routing/patternToRegex.sxyt.js +0 -69
- package/dist/routing/splitRequest.sxyt.d.ts +0 -2
- package/dist/routing/splitRequest.sxyt.d.ts.map +0 -1
- package/dist/routing/splitRequest.sxyt.js +0 -47
- package/dist/style/jssToCss.sxyt.d.ts +0 -2
- package/dist/style/jssToCss.sxyt.d.ts.map +0 -1
- package/dist/style/jssToCss.sxyt.js +0 -17
- package/dist/testing/createTestApp.sxyt.d.ts +0 -2
- package/dist/testing/createTestApp.sxyt.d.ts.map +0 -1
- package/dist/testing/createTestApp.sxyt.js +0 -470
- package/dist/testing/ensureTestEnvLoaded.sxyt.d.ts +0 -2
- package/dist/testing/ensureTestEnvLoaded.sxyt.d.ts.map +0 -1
- package/dist/testing/ensureTestEnvLoaded.sxyt.js +0 -20
|
@@ -2,7 +2,8 @@ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object
|
|
|
2
2
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
3
3
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4
4
|
import express from 'express';
|
|
5
|
-
import { join } from 'path';
|
|
5
|
+
import { join, relative } from 'path';
|
|
6
|
+
import slash from 'slash';
|
|
6
7
|
import "../moduleReloader.js"; // V important ES module cache control
|
|
7
8
|
import { allObj as promiseAllObj } from 'sxy-lib/promises.js';
|
|
8
9
|
import { staticFolder, assetsFolder, publicFolder, packagesFolder, clientFolder, componentCssFolder } from "../settings.js";
|
|
@@ -24,9 +25,12 @@ import { TungstenServer } from "./TungstenServer.js";
|
|
|
24
25
|
import { portError } from "./portError.js";
|
|
25
26
|
import { loadEnvsDev } from "./loadEnvsDev.js";
|
|
26
27
|
import { initStores } from "./initStores.js";
|
|
28
|
+
import { makeTungstenErrorInfo } from "../routing/TungstenErrorInfo.js";
|
|
27
29
|
import { MatchedRoute } from "../routing/MatchedRoute.js";
|
|
28
30
|
import { iterationQueryString } from "../iterationQueryString.js";
|
|
29
|
-
import { onReloadEvent } from "../
|
|
31
|
+
import { onReloadEvent } from "../hmr/liveReloadHub.js";
|
|
32
|
+
import { importDevModuleWithRetry } from "../importDevModuleWithRetry.js";
|
|
33
|
+
import { devErrorPageAutoRetryScript } from "./devErrorPageAutoRetry.js";
|
|
30
34
|
//import cookieParser from 'cookie-parser'
|
|
31
35
|
function debug(...texts) {
|
|
32
36
|
// console.log(...texts)
|
|
@@ -51,6 +55,10 @@ export class DevServer extends TungstenServer {
|
|
|
51
55
|
_defineProperty(this, "serverIterationCount", 0);
|
|
52
56
|
_defineProperty(this, "liveReloadClients", new Set());
|
|
53
57
|
_defineProperty(this, "unsubscribeReload", null);
|
|
58
|
+
// Sent as the first event on every live-reload connection (see handleLiveReloadStream), so
|
|
59
|
+
// the client can tell a fresh reconnect (server process restarted, e.g. by tungsten devmon)
|
|
60
|
+
// apart from its first-ever connection, and reload only in the former case.
|
|
61
|
+
_defineProperty(this, "bootId", `${Date.now()}-${Math.random()}`);
|
|
54
62
|
_defineProperty(this, "addServerMiddleware", serverMiddleware => {
|
|
55
63
|
//console.log('addServerMiddleware')
|
|
56
64
|
const [middlewareFile, middlewareExportName, middlewarePath] = serverMiddleware;
|
|
@@ -83,7 +91,7 @@ export class DevServer extends TungstenServer {
|
|
|
83
91
|
//const load = await createLoad(import.meta.url, sxyLoaderConfig)
|
|
84
92
|
const fullFilePath = 'file://' + join(this.compilationInfo.codeLocation, middlewareFile);
|
|
85
93
|
//const middlewareModule = await load(fullFilePath)
|
|
86
|
-
const middlewareModule = await
|
|
94
|
+
const middlewareModule = await importDevModuleWithRetry(iterationQueryString(fullFilePath, this.serverIterationCount++, 'middleware'));
|
|
87
95
|
if (!(middlewareExportName in middlewareModule)) {
|
|
88
96
|
throwError('DevServer', `export ${middlewareExportName} not found in ${middlewareFile}` + ` when trying to load server middleware`);
|
|
89
97
|
}
|
|
@@ -121,6 +129,9 @@ export class DevServer extends TungstenServer {
|
|
|
121
129
|
res.setHeader('Cache-Control', 'no-cache');
|
|
122
130
|
res.setHeader('Connection', 'keep-alive');
|
|
123
131
|
res.flushHeaders();
|
|
132
|
+
res.write(`event: boot\ndata: ${JSON.stringify({
|
|
133
|
+
bootId: this.bootId
|
|
134
|
+
})}\n\n`);
|
|
124
135
|
this.liveReloadClients.add(res);
|
|
125
136
|
req.on('close', () => {
|
|
126
137
|
this.liveReloadClients.delete(res);
|
|
@@ -128,21 +139,43 @@ export class DevServer extends TungstenServer {
|
|
|
128
139
|
});
|
|
129
140
|
_defineProperty(this, "reloadDebounceTimer", null);
|
|
130
141
|
_defineProperty(this, "pendingReloadKind", null);
|
|
131
|
-
_defineProperty(this, "
|
|
142
|
+
_defineProperty(this, "pendingReloadFiles", new Set());
|
|
143
|
+
_defineProperty(this, "broadcastReloadEvent", ({
|
|
144
|
+
kind,
|
|
145
|
+
file
|
|
146
|
+
}) => {
|
|
132
147
|
// A single save can fire several filesystem events in quick succession -
|
|
133
148
|
// tsc's writer often truncates a file before writing its new contents, and each
|
|
134
149
|
// of those steps runs back through this framework's own watch -> transform -> write
|
|
135
150
|
// cycle. Reloading on the first signal can land the browser on a momentarily
|
|
136
151
|
// half-written file, so wait for the burst to go quiet before actually reloading.
|
|
137
152
|
this.pendingReloadKind = this.pendingReloadKind === 'js' || kind === 'js' ? 'js' : kind;
|
|
153
|
+
if (file !== undefined) this.pendingReloadFiles.add(file);
|
|
138
154
|
if (this.reloadDebounceTimer !== null) clearTimeout(this.reloadDebounceTimer);
|
|
139
155
|
this.reloadDebounceTimer = setTimeout(() => {
|
|
140
156
|
const finalKind = this.pendingReloadKind ?? kind;
|
|
141
|
-
|
|
157
|
+
// 'files' carries the compiled-URL path of every changed component file, so the
|
|
158
|
+
// browser can attempt an in-place HMR swap instead of a full reload. Left empty for
|
|
159
|
+
// css events, or if a js event arrived with no known source file - the client falls
|
|
160
|
+
// back to a full reload in both cases.
|
|
161
|
+
const files = finalKind === 'js' ? [...this.pendingReloadFiles].map(this.sourceFileToUrlPath) : [];
|
|
162
|
+
const payload = JSON.stringify({
|
|
163
|
+
files
|
|
164
|
+
});
|
|
165
|
+
for (const client of this.liveReloadClients) client.write(`event: ${finalKind}\ndata: ${payload}\n\n`);
|
|
142
166
|
this.reloadDebounceTimer = null;
|
|
143
167
|
this.pendingReloadKind = null;
|
|
168
|
+
this.pendingReloadFiles.clear();
|
|
144
169
|
}, DevServer.reloadDebounceMs);
|
|
145
170
|
});
|
|
171
|
+
_defineProperty(this, "sourceFileToUrlPath", file => {
|
|
172
|
+
let rel = slash(relative(this.compilationInfo.codeLocation, file));
|
|
173
|
+
// compileJavascript strips the trailing 'x' off '.jsx' when writing the compiled
|
|
174
|
+
// output (the file no longer contains literal JSX after the babel transform) - match
|
|
175
|
+
// that here so the URL points at the file that's actually served.
|
|
176
|
+
if (rel.endsWith('.jsx')) rel = rel.slice(0, -1);
|
|
177
|
+
return `/${this.compilationInfo.codeSubPath}/${rel}`;
|
|
178
|
+
});
|
|
146
179
|
_defineProperty(this, "handleRequestApi", async (req, res, next) => {
|
|
147
180
|
req.params.foo;
|
|
148
181
|
this.apiRoutes = await getApiRoutes(this.config, this.compilationInfo, 'dev');
|
|
@@ -168,7 +201,19 @@ export class DevServer extends TungstenServer {
|
|
|
168
201
|
res.status(404).end();
|
|
169
202
|
return;
|
|
170
203
|
}
|
|
204
|
+
cliLog('handling ' + req.url);
|
|
171
205
|
const errorTrack = [];
|
|
206
|
+
// Captured as soon as each resolves, independent of the promiseAllObj combinators
|
|
207
|
+
// below - those are all-or-nothing, so if routing/data-fetching/rendering fails
|
|
208
|
+
// afterwards, the destructured `routes`/`RootComponentClass` locals never get
|
|
209
|
+
// assigned even though resolving them didn't fail. The catch block below uses these
|
|
210
|
+
// to tell "app routes resolved fine, something later failed" apart from "routes
|
|
211
|
+
// themselves couldn't be resolved" - only the former can show the app's 'error' route.
|
|
212
|
+
let capturedRoutes;
|
|
213
|
+
let capturedRootComponentClass = null;
|
|
214
|
+
// Defaults to {} to match the "no global data function registered" branch below,
|
|
215
|
+
// which resolves synchronously to {} and is never itself a failure case.
|
|
216
|
+
let capturedGlobalData = {};
|
|
172
217
|
try {
|
|
173
218
|
const _firstRender = this.firstRender;
|
|
174
219
|
this.firstRender = false;
|
|
@@ -205,11 +250,15 @@ export class DevServer extends TungstenServer {
|
|
|
205
250
|
//const routingPromise = getRoutesDev(this.compilationInfo, this.config, load).then(
|
|
206
251
|
const routingPromise = getRoutesDev(this.compilationInfo, this.config, iteration).then(async appRoutes => {
|
|
207
252
|
const routes = typeof appRoutes === 'function' ? appRoutes(reqRes) : appRoutes;
|
|
253
|
+
capturedRoutes = routes;
|
|
208
254
|
// load data, and do routing
|
|
209
255
|
return promiseAllObj({
|
|
210
256
|
appRoutes,
|
|
211
257
|
routes,
|
|
212
|
-
globalData: globalDataFunc.value !== undefined ? this.getGlobalData(globalDataFunc.value, reqRes).
|
|
258
|
+
globalData: globalDataFunc.value !== undefined ? this.getGlobalData(globalDataFunc.value, reqRes).then(globalData => {
|
|
259
|
+
capturedGlobalData = globalData;
|
|
260
|
+
return globalData;
|
|
261
|
+
}).catch(e => {
|
|
213
262
|
const msg = 'Error getting global data';
|
|
214
263
|
cliError(msg);
|
|
215
264
|
errorTrack.push(msg);
|
|
@@ -253,7 +302,10 @@ export class DevServer extends TungstenServer {
|
|
|
253
302
|
} = await promiseAllObj({
|
|
254
303
|
routing: routingPromise,
|
|
255
304
|
//RootComponentClass: getComponentDev(rootComponentFileFull, this.config.rootComponent, load)
|
|
256
|
-
RootComponentClass: getComponentDev(rootComponentFileFull, this.config.rootComponent, iteration)
|
|
305
|
+
RootComponentClass: getComponentDev(rootComponentFileFull, this.config.rootComponent, iteration).then(c => {
|
|
306
|
+
capturedRootComponentClass = c;
|
|
307
|
+
return c;
|
|
308
|
+
})
|
|
257
309
|
})
|
|
258
310
|
// .catch(e => {
|
|
259
311
|
// cliError('ROUTING AND ROOT ERR')
|
|
@@ -315,11 +367,60 @@ export class DevServer extends TungstenServer {
|
|
|
315
367
|
res.send(html);
|
|
316
368
|
} catch (e) {
|
|
317
369
|
cliLog('error in TungstenServer handleRequest', e);
|
|
318
|
-
res.setHeader('Content-Type', 'text/html');
|
|
319
|
-
res.status(500);
|
|
320
370
|
this.errorLog(e);
|
|
321
371
|
cliLog('');
|
|
322
|
-
|
|
372
|
+
const errorRouteHtml = await this.tryRenderErrorRoute(req, res, capturedRoutes, capturedRootComponentClass, capturedGlobalData, e);
|
|
373
|
+
res.setHeader('Content-Type', 'text/html');
|
|
374
|
+
res.status(500);
|
|
375
|
+
res.send(errorRouteHtml ?? this.errorPage(e, errorTrack));
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
// Attempts to render the app's own 'error' route instead of the dev server's generic
|
|
379
|
+
// error dump, using whatever `routes`/`RootComponentClass`/`globalData` handleRequest
|
|
380
|
+
// above managed to capture before it failed. Global data and route data are independent
|
|
381
|
+
// tRPC calls (batched together, but batching doesn't couple their success/failure - see
|
|
382
|
+
// resolveResponse.ts in @trpc/server), so global data commonly did resolve even when
|
|
383
|
+
// route data or rendering is what actually failed; passing the real value through here
|
|
384
|
+
// (rather than defaulting to {}) lets the error route render with it, e.g. the real theme
|
|
385
|
+
// colour or username instead of framework defaults. Only succeeds when routes actually
|
|
386
|
+
// resolved (so `routes` is defined) and the app defines an 'error' route. Never throws -
|
|
387
|
+
// falls back to null (the caller's default error page) on any failure, since we're
|
|
388
|
+
// already handling one error and can't risk a second, unhandled one taking the dev
|
|
389
|
+
// server down.
|
|
390
|
+
_defineProperty(this, "tryRenderErrorRoute", async (req, res, routes, RootComponentClass, globalData, error) => {
|
|
391
|
+
try {
|
|
392
|
+
if (routes === undefined) return null;
|
|
393
|
+
const errorRouteDef = routes.error;
|
|
394
|
+
if (errorRouteDef === undefined) return null;
|
|
395
|
+
if (this.framework.clientImportAliases === undefined) {
|
|
396
|
+
throwError('DevServer.tryRenderErrorRoute()', 'framework.clientImportAliases is undefined');
|
|
397
|
+
}
|
|
398
|
+
const reqRes = {
|
|
399
|
+
req,
|
|
400
|
+
res
|
|
401
|
+
};
|
|
402
|
+
const instanceConfig = makeInstanceConfigFromFrameworkConfig(this.config, true);
|
|
403
|
+
const matchedRouteInfo = {
|
|
404
|
+
key: 'error',
|
|
405
|
+
params: {},
|
|
406
|
+
content: errorRouteDef.content,
|
|
407
|
+
data: makeTungstenErrorInfo(error)
|
|
408
|
+
};
|
|
409
|
+
const serverDataLoading = {
|
|
410
|
+
value: false
|
|
411
|
+
};
|
|
412
|
+
const {
|
|
413
|
+
internalStore,
|
|
414
|
+
stores,
|
|
415
|
+
storeSubscriptions
|
|
416
|
+
} = initStores(req.url, reqRes, globalData, matchedRouteInfo, serverDataLoading);
|
|
417
|
+
const instance = new Instance(req.url, instanceConfig, reqRes, routes, routes, internalStore, stores, storeSubscriptions, globalData, matchedRouteInfo);
|
|
418
|
+
return await renderRootToHtmlDev(this.compilationInfo, this.framework.clientImportAliases, RootComponentClass ?? MatchedRoute, instance, this.config, global.tungstenPublicEnv, '' // siteBasePathOverride
|
|
419
|
+
);
|
|
420
|
+
} catch (renderError) {
|
|
421
|
+
cliError('Error rendering app error route, falling back to default error page');
|
|
422
|
+
cliLog(renderError);
|
|
423
|
+
return null;
|
|
323
424
|
}
|
|
324
425
|
});
|
|
325
426
|
// private async handlePost(req: express.Request, res: express.Response): Promise<void> {
|
|
@@ -340,11 +441,13 @@ export class DevServer extends TungstenServer {
|
|
|
340
441
|
log('end error log');
|
|
341
442
|
});
|
|
342
443
|
_defineProperty(this, "errorPage", (error, errorTrack) => {
|
|
444
|
+
const autoRetryScript = devErrorPageAutoRetryScript(error);
|
|
343
445
|
return `<!DOCTYPE html>
|
|
344
|
-
|
|
446
|
+
<html>
|
|
345
447
|
<head>
|
|
346
448
|
<title>Error</title>
|
|
347
449
|
<style>html { font-family: arial }</style>
|
|
450
|
+
${autoRetryScript ? `<script>${autoRetryScript}</script>` : ''}
|
|
348
451
|
</head>
|
|
349
452
|
<body>
|
|
350
453
|
<h1>Application Error</h1>
|
|
@@ -381,8 +484,8 @@ export class DevServer extends TungstenServer {
|
|
|
381
484
|
// + '\n Ensure that you have an env schema with this field, and a matching env file'
|
|
382
485
|
// )
|
|
383
486
|
// }
|
|
384
|
-
const proto =
|
|
385
|
-
const host =
|
|
487
|
+
const proto = tungstenPublicEnv.FRONTEND_PROTO ?? 'http';
|
|
488
|
+
const host = tungstenPublicEnv.FRONTEND_HOST ?? 'localhost';
|
|
386
489
|
const port = tungstenPrivateEnv.TUNGSTEN_SERVER_PORT ?? 3000;
|
|
387
490
|
if (isNaN(port) || port === 0) throwError('DevServer', portError(port));
|
|
388
491
|
this.port = port;
|
|
@@ -5,7 +5,7 @@ import type { RouteContentFunction } from '../routing/RouteContentFunction.js';
|
|
|
5
5
|
export type MatchedRouteInfo = {
|
|
6
6
|
key: RouteKey | null;
|
|
7
7
|
params: Record<string, string>;
|
|
8
|
-
content: ContentNode | RouteContentFunction
|
|
8
|
+
content: ContentNode | RouteContentFunction<any, any>;
|
|
9
9
|
data?: unknown | RoutingRedirect;
|
|
10
10
|
};
|
|
11
11
|
//# sourceMappingURL=MatchedRouteInfo.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MatchedRouteInfo.d.ts","sourceRoot":"","sources":["../../src/Servers/MatchedRouteInfo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AAE9E,MAAM,MAAM,gBAAgB,GAAG;IAC3B,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;IAErB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"MatchedRouteInfo.d.ts","sourceRoot":"","sources":["../../src/Servers/MatchedRouteInfo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AAE9E,MAAM,MAAM,gBAAgB,GAAG;IAC3B,GAAG,EAAE,QAAQ,GAAG,IAAI,CAAC;IAErB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAK9B,OAAO,EAAE,WAAW,GAAG,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACrD,IAAI,CAAC,EAAE,OAAO,GAAG,eAAe,CAAA;CACnC,CAAA"}
|
|
@@ -22,6 +22,7 @@ export declare class ProdServer extends TungstenServer {
|
|
|
22
22
|
constructor(framework: Framework, config: FrameworkConfigComplete, compilationInfo: CompilationInfo, appRoutes: AppRoutes, RootComponentOrNull: AnyComponentType | null, serverMiddleware: ServerMiddleware | null);
|
|
23
23
|
private handleRequestApi;
|
|
24
24
|
handleRequest: (req: express.Request, res: express.Response) => Promise<void>;
|
|
25
|
+
private tryRenderErrorRoute;
|
|
25
26
|
errorPage: () => string;
|
|
26
27
|
start(portOverride?: number | null, mute?: boolean): Promise<string>;
|
|
27
28
|
stop(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProdServer.d.ts","sourceRoot":"","sources":["../../src/Servers/ProdServer.ts"],"names":[],"mappings":"AAEA,OAAO,OAAO,MAAM,SAAS,CAAA;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAI7B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAQpD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAM3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAKnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"ProdServer.d.ts","sourceRoot":"","sources":["../../src/Servers/ProdServer.ts"],"names":[],"mappings":"AAEA,OAAO,OAAO,MAAM,SAAS,CAAA;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAI7B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAQpD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAM3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAKnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAWrD,qBAAa,UAAW,SAAQ,cAAc;IAC1C,SAAS,EAAE,SAAS,CAAA;IACpB,MAAM,EAAE,uBAAuB,CAAA;IAC/B,eAAe,EAAE,eAAe,CAAA;IAChC,SAAS,EAAE,SAAS,CAAA;IACpB,mBAAmB,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAK5C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAO;IAC9B,GAAG,EAAE,OAAO,CAAC,WAAW,CAAA;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;IACrC,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;gBAEX,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,uBAAuB,EAC/B,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,SAAS,EACpB,mBAAmB,EAAE,gBAAgB,GAAG,IAAI,EAC5C,gBAAgB,EAAE,gBAAgB,GAAG,IAAI;IA8H7C,OAAO,CAAC,gBAAgB,CAgBvB;IACD,aAAa,GAAU,KAAK,OAAO,CAAC,OAAO,EAAE,KAAK,OAAO,CAAC,QAAQ,KAAG,OAAO,CAAC,IAAI,CAAC,CA2HjF;IASD,OAAO,CAAC,mBAAmB,CA+C1B;IACD,SAAS,eASR;IAMD,KAAK,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,UAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAwBlE,IAAI;CAKP"}
|
|
@@ -19,6 +19,7 @@ import { globalDataFunc } from "../routing/registerGlobalData.js";
|
|
|
19
19
|
import { TungstenServer } from "./TungstenServer.js";
|
|
20
20
|
import { portError } from "./portError.js";
|
|
21
21
|
import { initStores } from "./initStores.js";
|
|
22
|
+
import { makeTungstenErrorInfo } from "../routing/TungstenErrorInfo.js";
|
|
22
23
|
function debug(...texts) {
|
|
23
24
|
// console.log(...texts)
|
|
24
25
|
}
|
|
@@ -83,6 +84,14 @@ export class ProdServer extends TungstenServer {
|
|
|
83
84
|
res.status(404).end();
|
|
84
85
|
return;
|
|
85
86
|
}
|
|
87
|
+
// Captured as soon as it resolves, independent of the Promise.all below - that's
|
|
88
|
+
// all-or-nothing, so if routing/route-data-fetching fails afterwards, `globalData`
|
|
89
|
+
// never gets assigned even though fetching it didn't fail (global data and route data
|
|
90
|
+
// are independent tRPC calls, batched together but not coupled - see
|
|
91
|
+
// resolveResponse.ts in @trpc/server). tryRenderErrorRoute uses this to render the
|
|
92
|
+
// app's error route with the real global data (theme colour, username, ...) rather
|
|
93
|
+
// than framework defaults, when it did resolve.
|
|
94
|
+
let capturedGlobalData = {};
|
|
86
95
|
try {
|
|
87
96
|
const location = req.url;
|
|
88
97
|
const instanceConfig = makeInstanceConfigFromFrameworkConfig(this.config);
|
|
@@ -115,7 +124,10 @@ export class ProdServer extends TungstenServer {
|
|
|
115
124
|
value: false
|
|
116
125
|
};
|
|
117
126
|
const routes = typeof appRoutes === 'function' ? appRoutes(reqRes) : appRoutes;
|
|
118
|
-
const [globalData, matchedRouteInfo] = await Promise.all([globalDataFunc.value !== undefined ? globalDataFunc.value(reqRes)
|
|
127
|
+
const [globalData, matchedRouteInfo] = await Promise.all([globalDataFunc.value !== undefined ? globalDataFunc.value(reqRes).then(globalData => {
|
|
128
|
+
capturedGlobalData = globalData;
|
|
129
|
+
return globalData;
|
|
130
|
+
}) : {}, routing(location, routes, serverDataLoading)]);
|
|
119
131
|
//instance.matchedRouteInfo =
|
|
120
132
|
//cliTodo('Can we move redirect handling to base class?')
|
|
121
133
|
// // 2025-03-14 copied this code here from Dev server,
|
|
@@ -165,14 +177,76 @@ export class ProdServer extends TungstenServer {
|
|
|
165
177
|
res.send(html);
|
|
166
178
|
} catch (e) {
|
|
167
179
|
cliLog('handleRequest() error', e);
|
|
180
|
+
const errorRouteHtml = await this.tryRenderErrorRoute(req, res, capturedGlobalData, e);
|
|
168
181
|
res.setHeader('Content-Type', 'text/html');
|
|
169
182
|
res.status(500);
|
|
170
|
-
res.send(this.errorPage());
|
|
183
|
+
res.send(errorRouteHtml ?? this.errorPage());
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
// Attempts to render the app's own 'error' route in place of the framework's generic
|
|
187
|
+
// error page, using whatever `globalData` handleRequest above managed to capture before
|
|
188
|
+
// it failed (see the capturedGlobalData comment there for why that's not always {}). Only
|
|
189
|
+
// usable when the app routes themselves could be resolved (this runs from the catch block
|
|
190
|
+
// of handleRequest, so anything from route resolution onward may have failed) and the app
|
|
191
|
+
// actually defines an 'error' route. Never throws - falls back to null (the caller's
|
|
192
|
+
// default error page) on any failure, since we're already handling one error and can't
|
|
193
|
+
// risk a second, unhandled one taking the server down.
|
|
194
|
+
_defineProperty(this, "tryRenderErrorRoute", async (req, res, globalData, error) => {
|
|
195
|
+
try {
|
|
196
|
+
if (this.framework.clientImportAliases === undefined) {
|
|
197
|
+
throwError('ProdServer.tryRenderErrorRoute()', 'framework.clientImportAliases is undefined');
|
|
198
|
+
}
|
|
199
|
+
const {
|
|
200
|
+
config,
|
|
201
|
+
appRoutes,
|
|
202
|
+
RootComponentOrNull
|
|
203
|
+
} = this;
|
|
204
|
+
const reqRes = {
|
|
205
|
+
req,
|
|
206
|
+
res
|
|
207
|
+
};
|
|
208
|
+
const routes = typeof appRoutes === 'function' ? appRoutes(reqRes) : appRoutes;
|
|
209
|
+
const errorRouteDef = routes.error;
|
|
210
|
+
if (errorRouteDef === undefined) return null;
|
|
211
|
+
const location = req.url;
|
|
212
|
+
const instanceConfig = makeInstanceConfigFromFrameworkConfig(this.config);
|
|
213
|
+
const matchedRouteInfo = {
|
|
214
|
+
key: 'error',
|
|
215
|
+
params: {},
|
|
216
|
+
content: errorRouteDef.content,
|
|
217
|
+
data: makeTungstenErrorInfo(error)
|
|
218
|
+
};
|
|
219
|
+
const serverDataLoading = {
|
|
220
|
+
value: false
|
|
221
|
+
};
|
|
222
|
+
const {
|
|
223
|
+
internalStore,
|
|
224
|
+
stores,
|
|
225
|
+
storeSubscriptions
|
|
226
|
+
} = initStores(location, reqRes, globalData, matchedRouteInfo, serverDataLoading);
|
|
227
|
+
const instance = new Instance(location, instanceConfig, reqRes, appRoutes, routes, internalStore, stores, storeSubscriptions, globalData, matchedRouteInfo);
|
|
228
|
+
if (RootComponentOrNull !== null) {
|
|
229
|
+
return await renderRootToHtml(this.compilationInfo, this.framework.clientImportAliases, RootComponentOrNull, instance, config, this.config.siteBasePath);
|
|
230
|
+
}
|
|
231
|
+
const {
|
|
232
|
+
params,
|
|
233
|
+
data
|
|
234
|
+
} = matchedRouteInfo;
|
|
235
|
+
let {
|
|
236
|
+
content
|
|
237
|
+
} = matchedRouteInfo;
|
|
238
|
+
if (typeof content === 'function') {
|
|
239
|
+
content = content(data, params, {} /* props */, globalData, location);
|
|
240
|
+
}
|
|
241
|
+
return await renderContentToHtml(this.compilationInfo, this.framework.clientImportAliases, content, instance, config, this.config.siteBasePath);
|
|
242
|
+
} catch (renderError) {
|
|
243
|
+
cliLog('Error rendering app error route, falling back to default error page', renderError);
|
|
244
|
+
return null;
|
|
171
245
|
}
|
|
172
246
|
});
|
|
173
247
|
_defineProperty(this, "errorPage", () => {
|
|
174
248
|
return `<!DOCTYPE html>
|
|
175
|
-
|
|
249
|
+
<html>
|
|
176
250
|
<head><title>Error</title></head>
|
|
177
251
|
<body>
|
|
178
252
|
<h1>Internal error</h1>
|
|
@@ -263,8 +337,8 @@ export class ProdServer extends TungstenServer {
|
|
|
263
337
|
// I don't think we ever override the port, not sure why
|
|
264
338
|
start(portOverride, mute = false) {
|
|
265
339
|
return new Promise(resolve => {
|
|
266
|
-
const proto =
|
|
267
|
-
const host =
|
|
340
|
+
const proto = tungstenPublicEnv.FRONTEND_PROTO ?? 'http';
|
|
341
|
+
const host = tungstenPublicEnv.FRONTEND_HOST ?? 'localhost';
|
|
268
342
|
let port;
|
|
269
343
|
if (portOverride !== undefined) {
|
|
270
344
|
port = portOverride;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const maxAutoRetryAttempts = 8;
|
|
2
|
+
export declare function devErrorPageAutoRetryScript(error: unknown): string;
|
|
3
|
+
export declare const devErrorPageClearRetryScript = "try{sessionStorage.removeItem('tungstenDevErrorRetryCount')}catch(e){}";
|
|
4
|
+
//# sourceMappingURL=devErrorPageAutoRetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devErrorPageAutoRetry.d.ts","sourceRoot":"","sources":["../../src/Servers/devErrorPageAutoRetry.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAGrC,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAqBlE;AAKD,eAAO,MAAM,4BAA4B,2EAC6B,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// devErrorPageAutoRetry
|
|
2
|
+
// exports devErrorPageAutoRetryScript, devErrorPageClearRetryScript, maxAutoRetryAttempts
|
|
3
|
+
//
|
|
4
|
+
// Dev-only. importDevModuleWithRetry.ts already rides out the common case of a transient,
|
|
5
|
+
// self-resolving module-shape error from a multi-file edit landing mid-compile - but under heavy
|
|
6
|
+
// load its bounded retry budget can still be exhausted before the underlying tsc/babel pipeline
|
|
7
|
+
// settles (see docs/hmr.md), leaving the developer looking at a dead dev error page for what's
|
|
8
|
+
// still, in fact, a self-resolving situation. If the error that reached the error page still
|
|
9
|
+
// looks like that same transient shape, embed a tiny script that auto-reloads a few times before
|
|
10
|
+
// giving up - capped via sessionStorage so a genuine, permanent error doesn't loop forever.
|
|
11
|
+
import { isTransientDevModuleError } from "../importDevModuleWithRetry.js";
|
|
12
|
+
const sessionStorageKey = 'tungstenDevErrorRetryCount';
|
|
13
|
+
export const maxAutoRetryAttempts = 8;
|
|
14
|
+
const retryDelayMs = 500;
|
|
15
|
+
export function devErrorPageAutoRetryScript(error) {
|
|
16
|
+
if (!isTransientDevModuleError(error)) return '';
|
|
17
|
+
// Wrapped in try/catch: sessionStorage can throw (some private-browsing modes, restrictive
|
|
18
|
+
// embedding contexts) rather than just being absent. Without a working store there's no way
|
|
19
|
+
// to safely cap attempts, so degrade to doing nothing rather than risk retrying unbounded -
|
|
20
|
+
// same as if this feature didn't exist, not worse.
|
|
21
|
+
return `(function(){` + `try{` + `var key='${sessionStorageKey}';` + `var count=parseInt(sessionStorage.getItem(key)||'0',10);` + `if(count<${maxAutoRetryAttempts}){` + `sessionStorage.setItem(key,String(count+1));` + `setTimeout(function(){location.reload()},${retryDelayMs})` + `}else{` + `console.error('[tungsten-dev] gave up auto-retrying a transient-looking error after ` + `${maxAutoRetryAttempts} attempts - this may be a real error, not a transient compile race')` + `}` + `}catch(e){` + `console.error('[tungsten-dev] could not auto-retry - sessionStorage unavailable',e)` + `}` + `})();`;
|
|
22
|
+
}
|
|
23
|
+
// Injected into every successfully-rendered dev page (see processHead.ts), so a later, unrelated
|
|
24
|
+
// transient error starts its own retry budget from zero rather than inheriting a stale count.
|
|
25
|
+
// Same try/catch reasoning as above - a successful render should never itself error out over this.
|
|
26
|
+
export const devErrorPageClearRetryScript = `try{sessionStorage.removeItem('${sessionStorageKey}')}catch(e){}`;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
//
|
|
2
|
-
// //import express, { Request, Response, NextFunction, RequestHandler } from 'express'
|
|
1
|
+
// Status/known gaps: see ./README.md
|
|
3
2
|
// import { Context, Hono } from 'hono'
|
|
4
3
|
// import type { BlankEnv, BlankSchema, Handler, Next } from 'hono/types'
|
|
5
|
-
// import { serve } from '@hono/node-server'
|
|
4
|
+
// import { serve, type ServerType } from '@hono/node-server'
|
|
6
5
|
// import { serveStatic } from '@hono/node-server/serve-static'
|
|
7
6
|
// import { join } from 'path'
|
|
8
7
|
// import { allObj as promiseAllObj } from 'sxy-lib/promises.js'
|
|
@@ -35,7 +34,6 @@
|
|
|
35
34
|
// import { ServerDataLoading } from '../../Store/ServerDataLoading.js'
|
|
36
35
|
// import { TungstenServer } from '../TungstenServer.jsx'
|
|
37
36
|
// import { Routes } from '../../routing/Routes.js'
|
|
38
|
-
// import { RedirectCode, RoutingRedirect } from '../../routing/RoutingRedirect.js'
|
|
39
37
|
// import { portError } from '../portError.js'
|
|
40
38
|
// import { loadEnvsDev } from '../loadEnvsDev.js'
|
|
41
39
|
// import { initStores } from '../initStores.js'
|
|
@@ -45,7 +43,6 @@
|
|
|
45
43
|
// import { MatchedRoute } from '../../routing/MatchedRoute.js'
|
|
46
44
|
// import { ContentNodeIsClassComponent } from '../../ContentNode.js'
|
|
47
45
|
// import { $props, $type } from '../../contentNodeSymbols.js'
|
|
48
|
-
// import { RedirectComponent } from '../../components/RedirectComponent.js'
|
|
49
46
|
// import { Path } from '../../routing/RouteTypes.js'
|
|
50
47
|
// import type { ApiRoutesHono } from '../../api/ApiRoutesHono.js'
|
|
51
48
|
// import { TungstenServerHono } from './TungstenServerHono.jsx'
|
|
@@ -64,9 +61,10 @@ export {};
|
|
|
64
61
|
// app: Hono<BlankEnv, BlankSchema, '/'>
|
|
65
62
|
// apiRoutes?: ApiRoutesHono
|
|
66
63
|
// apiPath?: string
|
|
67
|
-
// server?:
|
|
64
|
+
// server?: ServerType
|
|
68
65
|
// reqId: number
|
|
69
66
|
// firstRender: boolean = true
|
|
67
|
+
// iterationCount: number = 0
|
|
70
68
|
// constructor(
|
|
71
69
|
// framework: Framework, config: FrameworkConfigComplete, compilationInfo: CompilationInfo,
|
|
72
70
|
// initialProcessEnv: Record<string, string> = {}/* FIX ME */
|
|
@@ -83,8 +81,8 @@ export {};
|
|
|
83
81
|
// // + '\n Ensure that you have an env schema with this field, and a matching env file'
|
|
84
82
|
// // )
|
|
85
83
|
// // }
|
|
86
|
-
// const proto =
|
|
87
|
-
// const host =
|
|
84
|
+
// const proto = tungstenPublicEnv.FRONTEND_PROTO ?? 'http'
|
|
85
|
+
// const host = tungstenPublicEnv.FRONTEND_HOST ?? 'localhost'
|
|
88
86
|
// const port = tungstenPrivateEnv.TUNGSTEN_SERVER_PORT ?? 3000
|
|
89
87
|
// if (isNaN(port) || port === 0) throwError('DevServer', portError(port))
|
|
90
88
|
// this.port = port
|
|
@@ -301,21 +299,24 @@ export {};
|
|
|
301
299
|
// )
|
|
302
300
|
// }
|
|
303
301
|
// globalDataFunc.value = undefined
|
|
304
|
-
// const
|
|
305
|
-
// await loadEnvsDev(this.config,
|
|
306
|
-
// //
|
|
307
|
-
// //
|
|
308
|
-
// //
|
|
302
|
+
// const iteration = this.iterationCount++
|
|
303
|
+
// await loadEnvsDev(this.config, iteration, this.initialProcessEnv, false)
|
|
304
|
+
// // ReqRes is Express-shaped ({req, res}) and Hono's Context isn't - this cast is a
|
|
305
|
+
// // type-only bridge so the (Express-only) Instance/initStores/routing plumbing below
|
|
306
|
+
// // still compiles. Not behaviorally correct; fine since this dev server isn't wired
|
|
307
|
+
// // up anywhere live (see Framework.createDevServer, which only builds DevServer).
|
|
308
|
+
// // eslint-disable-next-line no-type-assertion/no-type-assertion -- see comment above
|
|
309
|
+
// const reqRes = c as unknown as ReqRes
|
|
309
310
|
// // Save some state. I think this is a placeholder for later
|
|
310
311
|
// const serverDataLoading: ServerDataLoading = { value: false }
|
|
311
|
-
// const routingPromise = getRoutesDev(this.compilationInfo, this.config,
|
|
312
|
+
// const routingPromise = getRoutesDev(this.compilationInfo, this.config, iteration).then(
|
|
312
313
|
// async (appRoutes) => {
|
|
313
|
-
// const routes = (typeof appRoutes === 'function') ? appRoutes(
|
|
314
|
+
// const routes = (typeof appRoutes === 'function') ? appRoutes(reqRes) : appRoutes
|
|
314
315
|
// // load data, and do routing
|
|
315
316
|
// return promiseAllObj({
|
|
316
317
|
// appRoutes,
|
|
317
318
|
// routes,
|
|
318
|
-
// globalData: (globalDataFunc.value !== undefined) ? globalDataFunc.value(
|
|
319
|
+
// globalData: (globalDataFunc.value !== undefined) ? globalDataFunc.value(reqRes) : {},
|
|
319
320
|
// matchedRouteInfo: routing(location, routes, serverDataLoading)
|
|
320
321
|
// })
|
|
321
322
|
// }
|
|
@@ -330,7 +331,7 @@ export {};
|
|
|
330
331
|
// ;({ routing: { appRoutes, routes, globalData, matchedRouteInfo }, RootComponentClass }
|
|
331
332
|
// = await promiseAllObj({
|
|
332
333
|
// routing: routingPromise,
|
|
333
|
-
// RootComponentClass: getComponentDev(rootComponentFileFull, this.config.rootComponent,
|
|
334
|
+
// RootComponentClass: getComponentDev(rootComponentFileFull, this.config.rootComponent, iteration)
|
|
334
335
|
// }))
|
|
335
336
|
// } else {
|
|
336
337
|
// ({ appRoutes, routes, globalData, matchedRouteInfo } = await routingPromise)
|
|
@@ -344,13 +345,13 @@ export {};
|
|
|
344
345
|
// // routing(location, routes, serverDataLoading)
|
|
345
346
|
// // ])
|
|
346
347
|
// const redirected = this.handleRedirects(c, matchedRouteInfo)
|
|
347
|
-
// if (redirected) return // end early
|
|
348
|
+
// if (redirected !== false) return redirected // end early
|
|
348
349
|
// // make stores
|
|
349
350
|
// const { internalStore, stores, storeSubscriptions }
|
|
350
|
-
// = initStores(location,
|
|
351
|
+
// = initStores(location, reqRes, globalData, matchedRouteInfo, serverDataLoading)
|
|
351
352
|
// // create the instance
|
|
352
|
-
// const instance = new Instance(
|
|
353
|
-
// location, instanceConfig,
|
|
353
|
+
// const instance = new Instance(
|
|
354
|
+
// location, instanceConfig, reqRes, appRoutes, routes, internalStore,
|
|
354
355
|
// stores, storeSubscriptions, globalData, matchedRouteInfo
|
|
355
356
|
// )
|
|
356
357
|
// let html: string
|
|
@@ -379,16 +380,11 @@ export {};
|
|
|
379
380
|
// // '' // siteBasePathOverride
|
|
380
381
|
// // )
|
|
381
382
|
// }
|
|
382
|
-
//
|
|
383
|
-
// res.setHeader('Content-Type', 'text/html')
|
|
384
|
-
// res.status((instance.matchedRouteInfo.key === '404') ? 404 : 200)
|
|
385
|
-
// res.send(html)
|
|
383
|
+
// return c.html(html, (instance.matchedRouteInfo.key === '404') ? 404 : 200)
|
|
386
384
|
// } catch(e) {
|
|
387
385
|
// cliLog('error', e)
|
|
388
|
-
// res.setHeader('Content-Type', 'text/html')
|
|
389
|
-
// res.status(500)
|
|
390
386
|
// this.errorLog(e)
|
|
391
|
-
//
|
|
387
|
+
// return c.html(this.errorPage(e), 500)
|
|
392
388
|
// }
|
|
393
389
|
// }
|
|
394
390
|
// // private async handlePost(req: express.Request, res: express.Response): Promise<void> {
|
|
@@ -414,7 +410,7 @@ export {};
|
|
|
414
410
|
// }
|
|
415
411
|
// start = (): Promise<string> => {
|
|
416
412
|
// return new Promise( resolve => {
|
|
417
|
-
// this.server = this.app.
|
|
413
|
+
// this.server = serve({ fetch: this.app.fetch, port: this.port }, () => {
|
|
418
414
|
// cliNews(`Dev server ready at ${this.location}`)
|
|
419
415
|
// resolve(this.location ?? '')
|
|
420
416
|
// })
|