@bleedingdev/modern-js-runtime 3.2.0-ultramodern.120 → 3.2.0-ultramodern.122
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/cjs/boundary-debugger/index.js +4 -0
- package/dist/cjs/cli/index.js +11 -0
- package/dist/cjs/{router/runtime/tanstack/rsc/ClientSlot.js → core/context/extensions.js} +33 -21
- package/dist/cjs/{router/runtime/tanstack/rsc/SlotContext.js → core/context/helmetContext.js} +16 -20
- package/dist/cjs/core/context/index.js +65 -0
- package/dist/cjs/core/react/wrapper.js +6 -4
- package/dist/cjs/core/server/helmet.js +2 -1
- package/dist/cjs/core/server/requestHandler.js +42 -29
- package/dist/cjs/core/server/routerCleanup.js +110 -0
- package/dist/cjs/core/server/scriptOrder.js +75 -4
- package/dist/cjs/core/server/stream/afterTemplate.js +6 -18
- package/dist/cjs/core/server/stream/deferredScript.js +4 -1
- package/dist/cjs/core/server/string/index.js +1 -7
- package/dist/cjs/core/server/string/loadable.js +13 -40
- package/dist/cjs/core/server/string/ssrData.js +1 -1
- package/dist/cjs/core/server/utils.js +31 -8
- package/dist/cjs/exports/head.js +135 -74
- package/dist/cjs/exports/tanstack-router.js +36 -305
- package/dist/cjs/module-federation/index.js +178 -0
- package/dist/cjs/router/cli/code/index.js +1 -47
- package/dist/cjs/router/cli/code/templates.js +1 -14
- package/dist/cjs/router/cli/handler.js +1 -1
- package/dist/cjs/router/cli/index.js +2 -23
- package/dist/cjs/router/runtime/DeferredDataScripts.node.js +16 -4
- package/dist/cjs/router/runtime/PrefetchLink.js +2 -3
- package/dist/cjs/router/runtime/internal.js +20 -13
- package/dist/cjs/router/runtime/lifecycle.js +37 -22
- package/dist/cjs/router/runtime/plugin.js +2 -9
- package/dist/cjs/router/runtime/plugin.node.js +2 -7
- package/dist/cjs/router/runtime/provider.js +107 -0
- package/dist/cjs/router/runtime/utils.js +35 -9
- package/dist/esm/boundary-debugger/index.mjs +4 -0
- package/dist/esm/cli/index.mjs +4 -2
- package/dist/esm/core/context/extensions.mjs +28 -0
- package/dist/esm/core/context/helmetContext.mjs +13 -0
- package/dist/esm/core/context/index.mjs +5 -0
- package/dist/esm/core/react/wrapper.mjs +6 -4
- package/dist/esm/core/server/helmet.mjs +2 -1
- package/dist/esm/core/server/requestHandler.mjs +43 -30
- package/dist/esm/core/server/routerCleanup.mjs +66 -0
- package/dist/esm/core/server/scriptOrder.mjs +60 -1
- package/dist/esm/core/server/stream/afterTemplate.mjs +8 -20
- package/dist/esm/core/server/stream/deferredScript.mjs +4 -1
- package/dist/esm/core/server/string/index.mjs +3 -9
- package/dist/esm/core/server/string/loadable.mjs +11 -38
- package/dist/esm/core/server/string/ssrData.mjs +2 -2
- package/dist/esm/core/server/utils.mjs +31 -8
- package/dist/esm/exports/head.mjs +135 -74
- package/dist/esm/exports/tanstack-router.mjs +30 -4
- package/dist/esm/module-federation/index.mjs +109 -0
- package/dist/esm/router/cli/code/index.mjs +1 -47
- package/dist/esm/router/cli/code/templates.mjs +1 -14
- package/dist/esm/router/cli/handler.mjs +1 -1
- package/dist/esm/router/cli/index.mjs +3 -24
- package/dist/esm/router/runtime/DeferredDataScripts.node.mjs +16 -4
- package/dist/esm/router/runtime/PrefetchLink.mjs +2 -3
- package/dist/esm/router/runtime/internal.mjs +16 -15
- package/dist/esm/router/runtime/lifecycle.mjs +22 -13
- package/dist/esm/router/runtime/plugin.mjs +4 -11
- package/dist/esm/router/runtime/plugin.node.mjs +4 -9
- package/dist/esm/router/runtime/provider.mjs +57 -0
- package/dist/esm/router/runtime/utils.mjs +35 -9
- package/dist/esm-node/boundary-debugger/index.mjs +4 -0
- package/dist/esm-node/cli/index.mjs +4 -2
- package/dist/esm-node/core/context/extensions.mjs +29 -0
- package/dist/esm-node/core/context/helmetContext.mjs +14 -0
- package/dist/esm-node/core/context/index.mjs +5 -0
- package/dist/esm-node/core/react/wrapper.mjs +6 -4
- package/dist/esm-node/core/server/helmet.mjs +2 -1
- package/dist/esm-node/core/server/requestHandler.mjs +43 -30
- package/dist/esm-node/core/server/routerCleanup.mjs +67 -0
- package/dist/esm-node/core/server/scriptOrder.mjs +60 -1
- package/dist/esm-node/core/server/stream/afterTemplate.mjs +8 -20
- package/dist/esm-node/core/server/stream/deferredScript.mjs +4 -1
- package/dist/esm-node/core/server/string/index.mjs +3 -9
- package/dist/esm-node/core/server/string/loadable.mjs +11 -38
- package/dist/esm-node/core/server/string/ssrData.mjs +2 -2
- package/dist/esm-node/core/server/utils.mjs +31 -8
- package/dist/esm-node/exports/head.mjs +135 -74
- package/dist/esm-node/exports/tanstack-router.mjs +30 -4
- package/dist/esm-node/module-federation/index.mjs +110 -0
- package/dist/esm-node/router/cli/code/index.mjs +1 -47
- package/dist/esm-node/router/cli/code/templates.mjs +1 -14
- package/dist/esm-node/router/cli/handler.mjs +1 -1
- package/dist/esm-node/router/cli/index.mjs +3 -24
- package/dist/esm-node/router/runtime/DeferredDataScripts.node.mjs +16 -4
- package/dist/esm-node/router/runtime/PrefetchLink.mjs +2 -3
- package/dist/esm-node/router/runtime/internal.mjs +16 -15
- package/dist/esm-node/router/runtime/lifecycle.mjs +22 -13
- package/dist/esm-node/router/runtime/plugin.mjs +4 -11
- package/dist/esm-node/router/runtime/plugin.node.mjs +4 -9
- package/dist/esm-node/router/runtime/provider.mjs +58 -0
- package/dist/esm-node/router/runtime/utils.mjs +35 -9
- package/dist/types/cli/index.d.ts +3 -1
- package/dist/types/core/context/extensions.d.ts +37 -0
- package/dist/types/core/context/helmetContext.d.ts +10 -0
- package/dist/types/core/context/index.d.ts +6 -0
- package/dist/types/core/context/runtime.d.ts +1 -11
- package/dist/types/core/server/routerCleanup.d.ts +28 -0
- package/dist/types/core/server/scriptOrder.d.ts +24 -0
- package/dist/types/core/server/string/loadable.d.ts +1 -7
- package/dist/types/core/server/utils.d.ts +1 -0
- package/dist/types/exports/tanstack-router.d.ts +88 -7
- package/dist/types/module-federation/index.d.ts +65 -0
- package/dist/types/router/cli/code/index.d.ts +1 -3
- package/dist/types/router/cli/handler.d.ts +0 -3
- package/dist/types/router/runtime/internal.d.ts +1 -0
- package/dist/types/router/runtime/lifecycle.d.ts +2 -0
- package/dist/types/router/runtime/plugin.d.ts +1 -1
- package/dist/types/router/runtime/plugin.node.d.ts +1 -1
- package/dist/types/router/runtime/provider.d.ts +61 -0
- package/package.json +16 -12
- package/rstest.config.mts +2 -4
- package/dist/cjs/router/cli/code/tanstackTypes.js +0 -447
- package/dist/cjs/router/runtime/tanstack/basepathRewrite.js +0 -66
- package/dist/cjs/router/runtime/tanstack/dataMutation.js +0 -349
- package/dist/cjs/router/runtime/tanstack/hydrationBoundary.js +0 -48
- package/dist/cjs/router/runtime/tanstack/outlet.js +0 -58
- package/dist/cjs/router/runtime/tanstack/plugin.js +0 -342
- package/dist/cjs/router/runtime/tanstack/plugin.node.js +0 -272
- package/dist/cjs/router/runtime/tanstack/prefetchLink.js +0 -59
- package/dist/cjs/router/runtime/tanstack/routeTree.js +0 -525
- package/dist/cjs/router/runtime/tanstack/rsc/CompositeComponent.js +0 -79
- package/dist/cjs/router/runtime/tanstack/rsc/ReplayableStream.js +0 -146
- package/dist/cjs/router/runtime/tanstack/rsc/RscNodeRenderer.js +0 -69
- package/dist/cjs/router/runtime/tanstack/rsc/client.js +0 -97
- package/dist/cjs/router/runtime/tanstack/rsc/createRscProxy.js +0 -145
- package/dist/cjs/router/runtime/tanstack/rsc/index.js +0 -46
- package/dist/cjs/router/runtime/tanstack/rsc/server.js +0 -250
- package/dist/cjs/router/runtime/tanstack/rsc/slotUsageSanitizer.js +0 -69
- package/dist/cjs/router/runtime/tanstack/rsc/symbols.js +0 -77
- package/dist/cjs/ssr/index.node.js +0 -125
- package/dist/cjs/ssr/serverRender/renderToStream/buildTemplate.after.js +0 -88
- package/dist/cjs/ssr/serverRender/renderToString/entry.js +0 -200
- package/dist/cjs/ssr/serverRender/types.js +0 -40
- package/dist/esm/router/cli/code/tanstackTypes.mjs +0 -396
- package/dist/esm/router/runtime/tanstack/basepathRewrite.mjs +0 -28
- package/dist/esm/router/runtime/tanstack/dataMutation.mjs +0 -305
- package/dist/esm/router/runtime/tanstack/hydrationBoundary.mjs +0 -10
- package/dist/esm/router/runtime/tanstack/outlet.mjs +0 -17
- package/dist/esm/router/runtime/tanstack/plugin.mjs +0 -304
- package/dist/esm/router/runtime/tanstack/plugin.node.mjs +0 -234
- package/dist/esm/router/runtime/tanstack/prefetchLink.mjs +0 -18
- package/dist/esm/router/runtime/tanstack/routeTree.mjs +0 -481
- package/dist/esm/router/runtime/tanstack/rsc/ClientSlot.mjs +0 -19
- package/dist/esm/router/runtime/tanstack/rsc/CompositeComponent.mjs +0 -41
- package/dist/esm/router/runtime/tanstack/rsc/ReplayableStream.mjs +0 -104
- package/dist/esm/router/runtime/tanstack/rsc/RscNodeRenderer.mjs +0 -31
- package/dist/esm/router/runtime/tanstack/rsc/SlotContext.mjs +0 -17
- package/dist/esm/router/runtime/tanstack/rsc/client.mjs +0 -53
- package/dist/esm/router/runtime/tanstack/rsc/createRscProxy.mjs +0 -107
- package/dist/esm/router/runtime/tanstack/rsc/index.mjs +0 -1
- package/dist/esm/router/runtime/tanstack/rsc/server.mjs +0 -200
- package/dist/esm/router/runtime/tanstack/rsc/slotUsageSanitizer.mjs +0 -31
- package/dist/esm/router/runtime/tanstack/rsc/symbols.mjs +0 -17
- package/dist/esm/ssr/index.node.mjs +0 -44
- package/dist/esm/ssr/serverRender/renderToStream/buildTemplate.after.mjs +0 -50
- package/dist/esm/ssr/serverRender/renderToString/entry.mjs +0 -151
- package/dist/esm/ssr/serverRender/types.mjs +0 -1
- package/dist/esm-node/router/cli/code/tanstackTypes.mjs +0 -397
- package/dist/esm-node/router/runtime/tanstack/basepathRewrite.mjs +0 -29
- package/dist/esm-node/router/runtime/tanstack/dataMutation.mjs +0 -306
- package/dist/esm-node/router/runtime/tanstack/hydrationBoundary.mjs +0 -11
- package/dist/esm-node/router/runtime/tanstack/outlet.mjs +0 -18
- package/dist/esm-node/router/runtime/tanstack/plugin.mjs +0 -305
- package/dist/esm-node/router/runtime/tanstack/plugin.node.mjs +0 -235
- package/dist/esm-node/router/runtime/tanstack/prefetchLink.mjs +0 -19
- package/dist/esm-node/router/runtime/tanstack/routeTree.mjs +0 -482
- package/dist/esm-node/router/runtime/tanstack/rsc/ClientSlot.mjs +0 -20
- package/dist/esm-node/router/runtime/tanstack/rsc/CompositeComponent.mjs +0 -42
- package/dist/esm-node/router/runtime/tanstack/rsc/ReplayableStream.mjs +0 -105
- package/dist/esm-node/router/runtime/tanstack/rsc/RscNodeRenderer.mjs +0 -32
- package/dist/esm-node/router/runtime/tanstack/rsc/SlotContext.mjs +0 -18
- package/dist/esm-node/router/runtime/tanstack/rsc/client.mjs +0 -54
- package/dist/esm-node/router/runtime/tanstack/rsc/createRscProxy.mjs +0 -108
- package/dist/esm-node/router/runtime/tanstack/rsc/index.mjs +0 -2
- package/dist/esm-node/router/runtime/tanstack/rsc/server.mjs +0 -201
- package/dist/esm-node/router/runtime/tanstack/rsc/slotUsageSanitizer.mjs +0 -32
- package/dist/esm-node/router/runtime/tanstack/rsc/symbols.mjs +0 -18
- package/dist/esm-node/ssr/index.node.mjs +0 -45
- package/dist/esm-node/ssr/serverRender/renderToStream/buildTemplate.after.mjs +0 -51
- package/dist/esm-node/ssr/serverRender/renderToString/entry.mjs +0 -152
- package/dist/esm-node/ssr/serverRender/types.mjs +0 -2
- package/dist/types/router/cli/code/tanstackTypes.d.ts +0 -10
- package/dist/types/router/runtime/tanstack/basepathRewrite.d.ts +0 -8
- package/dist/types/router/runtime/tanstack/dataMutation.d.ts +0 -29
- package/dist/types/router/runtime/tanstack/hydrationBoundary.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/outlet.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/plugin.d.ts +0 -6
- package/dist/types/router/runtime/tanstack/plugin.node.d.ts +0 -6
- package/dist/types/router/runtime/tanstack/prefetchLink.d.ts +0 -11
- package/dist/types/router/runtime/tanstack/routeTree.d.ts +0 -8
- package/dist/types/router/runtime/tanstack/rsc/ClientSlot.d.ts +0 -5
- package/dist/types/router/runtime/tanstack/rsc/CompositeComponent.d.ts +0 -3
- package/dist/types/router/runtime/tanstack/rsc/ReplayableStream.d.ts +0 -24
- package/dist/types/router/runtime/tanstack/rsc/RscNodeRenderer.d.ts +0 -5
- package/dist/types/router/runtime/tanstack/rsc/SlotContext.d.ts +0 -11
- package/dist/types/router/runtime/tanstack/rsc/client.d.ts +0 -11
- package/dist/types/router/runtime/tanstack/rsc/createRscProxy.d.ts +0 -7
- package/dist/types/router/runtime/tanstack/rsc/index.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/rsc/server.d.ts +0 -14
- package/dist/types/router/runtime/tanstack/rsc/slotUsageSanitizer.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/rsc/symbols.d.ts +0 -46
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import react from "react";
|
|
3
3
|
import { Helmet, HelmetData, HelmetProvider } from "react-helmet-async";
|
|
4
4
|
import { InternalRuntimeContext } from "../core/context/index.mjs";
|
|
5
|
+
import { ensureHelmetContext } from "../core/context/helmetContext.mjs";
|
|
5
6
|
const ATTRIBUTE_NAME_MAP = {
|
|
6
7
|
charSet: 'charset',
|
|
7
8
|
className: 'class',
|
|
@@ -11,6 +12,10 @@ const ATTRIBUTE_NAME_MAP = {
|
|
|
11
12
|
itemProp: 'itemprop',
|
|
12
13
|
tabIndex: 'tabindex'
|
|
13
14
|
};
|
|
15
|
+
const CONTENT_PROPERTIES = new Set([
|
|
16
|
+
'innerHTML',
|
|
17
|
+
'cssText'
|
|
18
|
+
]);
|
|
14
19
|
const escapeHtml = (value)=>String(value).replaceAll('&', '&').replaceAll('"', '"').replaceAll('<', '<').replaceAll('>', '>');
|
|
15
20
|
const toHtmlAttributeName = (name)=>ATTRIBUTE_NAME_MAP[name] ?? name;
|
|
16
21
|
const attributesToString = (attributes, includeHelmetAttribute = false)=>{
|
|
@@ -18,6 +23,7 @@ const attributesToString = (attributes, includeHelmetAttribute = false)=>{
|
|
|
18
23
|
if (includeHelmetAttribute) pairs.push('data-rh="true"');
|
|
19
24
|
for (const [name, value] of Object.entries(attributes ?? {})){
|
|
20
25
|
if (false === value || null == value) continue;
|
|
26
|
+
if (CONTENT_PROPERTIES.has(name)) continue;
|
|
21
27
|
const htmlName = toHtmlAttributeName(name);
|
|
22
28
|
if (true === value) pairs.push(htmlName);
|
|
23
29
|
else pairs.push(`${htmlName}="${escapeHtml(value)}"`);
|
|
@@ -46,18 +52,6 @@ const createTitleDatum = (title, attributes)=>({
|
|
|
46
52
|
return `<title ${attrs}>${escapeHtml(title)}</title>`;
|
|
47
53
|
}
|
|
48
54
|
});
|
|
49
|
-
const createEmptyHelmetState = ()=>({
|
|
50
|
-
base: createDatum('base', []),
|
|
51
|
-
bodyAttributes: createAttributeDatum({}),
|
|
52
|
-
htmlAttributes: createAttributeDatum({}),
|
|
53
|
-
link: createDatum('link', []),
|
|
54
|
-
meta: createDatum('meta', []),
|
|
55
|
-
noscript: createDatum("noscript", []),
|
|
56
|
-
priority: createDatum('meta', []),
|
|
57
|
-
script: createDatum("script", []),
|
|
58
|
-
style: createDatum('style', []),
|
|
59
|
-
title: createTitleDatum(void 0, {})
|
|
60
|
-
});
|
|
61
55
|
const normalizeHelmetTitle = (title)=>{
|
|
62
56
|
if ('string' == typeof title) return title;
|
|
63
57
|
if (Array.isArray(title)) return title.map((part)=>String(part)).join('');
|
|
@@ -77,7 +71,14 @@ const collectChildren = (children, draft)=>{
|
|
|
77
71
|
draft.titleAttributes = mergeAttributes(draft.titleAttributes, props);
|
|
78
72
|
return;
|
|
79
73
|
}
|
|
80
|
-
if ('html' === child.type
|
|
74
|
+
if ('html' === child.type) {
|
|
75
|
+
draft.htmlAttributes = mergeAttributes(draft.htmlAttributes ?? {}, props);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if ('body' === child.type) {
|
|
79
|
+
draft.bodyAttributes = mergeAttributes(draft.bodyAttributes ?? {}, props);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
81
82
|
if ('base' === child.type || 'link' === child.type || 'meta' === child.type || "noscript" === child.type || "script" === child.type || 'style' === child.type) {
|
|
82
83
|
const tag = {
|
|
83
84
|
...props
|
|
@@ -87,8 +88,7 @@ const collectChildren = (children, draft)=>{
|
|
|
87
88
|
}
|
|
88
89
|
});
|
|
89
90
|
};
|
|
90
|
-
const
|
|
91
|
-
const baseState = current ?? createEmptyHelmetState();
|
|
91
|
+
const createHelmetRecord = (props)=>{
|
|
92
92
|
const draft = {
|
|
93
93
|
base: [
|
|
94
94
|
...void 0 !== props.base ? [
|
|
@@ -116,71 +116,132 @@ const collectHelmetProps = (current, props)=>{
|
|
|
116
116
|
titleAttributes: props.titleAttributes ?? {}
|
|
117
117
|
};
|
|
118
118
|
collectChildren(props.children, draft);
|
|
119
|
-
const title = void 0 !== draft.title && '' !== draft.title && void 0 !== props.titleTemplate ? props.titleTemplate.replaceAll('%s', draft.title) : draft.title ?? props.defaultTitle;
|
|
120
119
|
return {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
120
|
+
...draft,
|
|
121
|
+
titleTemplate: props.titleTemplate,
|
|
122
|
+
defaultTitle: props.defaultTitle
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
const getInnermostDefined = (records, pick)=>{
|
|
126
|
+
for(let i = records.length - 1; i >= 0; i -= 1){
|
|
127
|
+
const value = pick(records[i]);
|
|
128
|
+
if (void 0 !== value) return value;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const deriveTitle = (records)=>{
|
|
132
|
+
const innermostTitle = getInnermostDefined(records, (record)=>record.title);
|
|
133
|
+
const innermostTemplate = getInnermostDefined(records, (record)=>record.titleTemplate);
|
|
134
|
+
if (innermostTemplate && innermostTitle) return innermostTemplate.replaceAll('%s', innermostTitle);
|
|
135
|
+
return innermostTitle || getInnermostDefined(records, (record)=>record.defaultTitle);
|
|
136
|
+
};
|
|
137
|
+
const mergeRecordAttributes = (records, pick)=>records.reduce((merged, record)=>mergeAttributes(merged, pick(record)), {});
|
|
138
|
+
const deriveBaseTags = (records)=>{
|
|
139
|
+
for(let i = records.length - 1; i >= 0; i -= 1){
|
|
140
|
+
const tags = records[i].base;
|
|
141
|
+
for(let j = tags.length - 1; j >= 0; j -= 1)if (tags[j].href) return [
|
|
142
|
+
tags[j]
|
|
143
|
+
];
|
|
144
|
+
}
|
|
145
|
+
return [];
|
|
146
|
+
};
|
|
147
|
+
const TAG_PRIMARY_ATTRIBUTES = {
|
|
148
|
+
link: [
|
|
149
|
+
'rel',
|
|
150
|
+
'href'
|
|
151
|
+
],
|
|
152
|
+
meta: [
|
|
153
|
+
'name',
|
|
154
|
+
'charset',
|
|
155
|
+
'http-equiv',
|
|
156
|
+
'property',
|
|
157
|
+
'itemprop'
|
|
158
|
+
],
|
|
159
|
+
noscript: [
|
|
160
|
+
'innerHTML'
|
|
161
|
+
],
|
|
162
|
+
script: [
|
|
163
|
+
'src',
|
|
164
|
+
'innerHTML'
|
|
165
|
+
],
|
|
166
|
+
style: [
|
|
167
|
+
'cssText'
|
|
168
|
+
]
|
|
169
|
+
};
|
|
170
|
+
const getPrimaryAttribute = (tagName, tag)=>{
|
|
171
|
+
const candidates = TAG_PRIMARY_ATTRIBUTES[tagName];
|
|
172
|
+
let selectedKey;
|
|
173
|
+
let selectedValue;
|
|
174
|
+
for (const [key, value] of Object.entries(tag)){
|
|
175
|
+
const normalizedKey = CONTENT_PROPERTIES.has(key) ? key : toHtmlAttributeName(key).toLowerCase();
|
|
176
|
+
if (candidates.includes(normalizedKey)) {
|
|
177
|
+
if ('rel' !== selectedKey || 'canonical' !== String(selectedValue).toLowerCase()) {
|
|
178
|
+
if ('rel' !== normalizedKey || 'stylesheet' !== String(value).toLowerCase()) {
|
|
179
|
+
selectedKey = normalizedKey;
|
|
180
|
+
selectedValue = value;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (void 0 === selectedKey || !selectedValue) return;
|
|
186
|
+
return {
|
|
187
|
+
key: selectedKey,
|
|
188
|
+
value: String(selectedValue).toLowerCase()
|
|
177
189
|
};
|
|
178
190
|
};
|
|
191
|
+
const dedupeTags = (tagName, records)=>{
|
|
192
|
+
const approvedValues = new Map();
|
|
193
|
+
const approved = [];
|
|
194
|
+
for(let i = records.length - 1; i >= 0; i -= 1){
|
|
195
|
+
const instanceValues = new Map();
|
|
196
|
+
const kept = [];
|
|
197
|
+
for (const tag of records[i][tagName]){
|
|
198
|
+
const primary = getPrimaryAttribute(tagName, tag);
|
|
199
|
+
if (void 0 === primary) continue;
|
|
200
|
+
if (approvedValues.get(primary.key)?.has(primary.value)) continue;
|
|
201
|
+
let seen = instanceValues.get(primary.key);
|
|
202
|
+
if (void 0 === seen) {
|
|
203
|
+
seen = new Set();
|
|
204
|
+
instanceValues.set(primary.key, seen);
|
|
205
|
+
}
|
|
206
|
+
seen.add(primary.value);
|
|
207
|
+
kept.push(tag);
|
|
208
|
+
}
|
|
209
|
+
approved.unshift(...kept);
|
|
210
|
+
for (const [key, values] of instanceValues){
|
|
211
|
+
const target = approvedValues.get(key);
|
|
212
|
+
if (void 0 === target) approvedValues.set(key, values);
|
|
213
|
+
else for (const value of values)target.add(value);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return approved;
|
|
217
|
+
};
|
|
218
|
+
const deriveHelmetServerState = (records)=>({
|
|
219
|
+
base: createDatum('base', deriveBaseTags(records)),
|
|
220
|
+
bodyAttributes: createAttributeDatum(mergeRecordAttributes(records, (record)=>record.bodyAttributes)),
|
|
221
|
+
htmlAttributes: createAttributeDatum(mergeRecordAttributes(records, (record)=>record.htmlAttributes)),
|
|
222
|
+
link: createDatum('link', dedupeTags('link', records)),
|
|
223
|
+
meta: createDatum('meta', dedupeTags('meta', records)),
|
|
224
|
+
noscript: createDatum("noscript", dedupeTags("noscript", records)),
|
|
225
|
+
priority: createDatum('meta', []),
|
|
226
|
+
script: createDatum("script", dedupeTags("script", records)),
|
|
227
|
+
style: createDatum('style', dedupeTags('style', records)),
|
|
228
|
+
title: createTitleDatum(deriveTitle(records), mergeRecordAttributes(records, (record)=>record.titleAttributes))
|
|
229
|
+
});
|
|
230
|
+
const serverHelmetRecords = new WeakMap();
|
|
231
|
+
const collectServerHelmet = (runtimeContext, props)=>{
|
|
232
|
+
const helmetContext = ensureHelmetContext(runtimeContext);
|
|
233
|
+
let records = serverHelmetRecords.get(helmetContext);
|
|
234
|
+
if (void 0 === records) {
|
|
235
|
+
records = [];
|
|
236
|
+
serverHelmetRecords.set(helmetContext, records);
|
|
237
|
+
}
|
|
238
|
+
records.push(createHelmetRecord(props));
|
|
239
|
+
helmetContext.helmet = deriveHelmetServerState(records);
|
|
240
|
+
};
|
|
179
241
|
const head_Helmet = (props)=>{
|
|
180
242
|
const runtimeContext = react.useContext(InternalRuntimeContext);
|
|
181
243
|
if (null !== runtimeContext && false === runtimeContext.isBrowser) {
|
|
182
|
-
runtimeContext
|
|
183
|
-
runtimeContext._helmetContext.helmet = collectHelmetProps(runtimeContext._helmetContext.helmet ?? void 0, props);
|
|
244
|
+
collectServerHelmet(runtimeContext, props);
|
|
184
245
|
return null;
|
|
185
246
|
}
|
|
186
247
|
return react.createElement(Helmet, props);
|
|
@@ -1,4 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { createElement } from "react";
|
|
2
|
+
const COMPAT_BINDINGS_SLOT = Symbol.for('@modern-js/plugin-tanstack:runtime-compat-bindings');
|
|
3
|
+
function readCompatBindings() {
|
|
4
|
+
return globalThis[COMPAT_BINDINGS_SLOT];
|
|
5
|
+
}
|
|
6
|
+
function resolveCompatBindings(exportName) {
|
|
7
|
+
const bindings = readCompatBindings();
|
|
8
|
+
if (void 0 === bindings) throw new Error(`[@modern-js/runtime] '${exportName}' from the deprecated '@modern-js/runtime/tanstack-router' alias is provided by @modern-js/plugin-tanstack. Install @modern-js/plugin-tanstack, add \`tanstackRouterPlugin()\` to the \`plugins\` array in modern.config.ts, and make sure '@modern-js/plugin-tanstack/runtime' is imported (e.g. in modern.runtime.ts) before '${exportName}' is used. Prefer importing '${exportName}' from '@modern-js/plugin-tanstack/runtime' directly.`);
|
|
9
|
+
return bindings;
|
|
10
|
+
}
|
|
11
|
+
const Link = (props)=>createElement(resolveCompatBindings('Link').Link, props);
|
|
12
|
+
const NavLink = (props)=>createElement(resolveCompatBindings('NavLink').NavLink, props);
|
|
13
|
+
const Outlet = ()=>createElement(resolveCompatBindings('Outlet').Outlet);
|
|
14
|
+
const Form = (props)=>createElement(resolveCompatBindings('Form').Form, props);
|
|
15
|
+
function useFetcher() {
|
|
16
|
+
return resolveCompatBindings('useFetcher').useFetcher();
|
|
17
|
+
}
|
|
18
|
+
function RouteActionResponseErrorPlaceholder() {}
|
|
19
|
+
const RouteActionResponseError = new Proxy(RouteActionResponseErrorPlaceholder, {
|
|
20
|
+
construct (_target, args) {
|
|
21
|
+
const RealError = resolveCompatBindings('RouteActionResponseError').RouteActionResponseError;
|
|
22
|
+
return new RealError(...args);
|
|
23
|
+
},
|
|
24
|
+
get (target, property, receiver) {
|
|
25
|
+
const RealError = readCompatBindings()?.RouteActionResponseError;
|
|
26
|
+
if (void 0 !== RealError) return Reflect.get(RealError, property);
|
|
27
|
+
return Reflect.get(target, property, receiver);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
export { Form, Link, NavLink, Outlet, RouteActionResponseError, useFetcher };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const MODULE_FEDERATION_FALLBACK_SIGNAL_EVENT = 'modernjs:mf-runtime-fallback';
|
|
2
|
+
const MODULE_FEDERATION_RECOVERY_SIGNAL_EVENT = 'modernjs:mf-runtime-recovery';
|
|
3
|
+
const DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT = '/_modern/contract-gates/runtime-fallback';
|
|
4
|
+
const DEFAULT_RUNTIME_FALLBACK_SIGNAL_AUTH_HEADER = 'x-modernjs-runtime-signal-token';
|
|
5
|
+
class ModuleFederationRemoteLoadTimeoutError extends Error {
|
|
6
|
+
constructor(remote, timeoutMs){
|
|
7
|
+
super(`Loading remote "${remote}" timed out after ${timeoutMs}ms`);
|
|
8
|
+
this.name = 'ModuleFederationRemoteLoadTimeoutError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
class ModuleFederationRemoteLoadError extends Error {
|
|
12
|
+
constructor(remote, attempts, causeError){
|
|
13
|
+
super(`Unable to load remote "${remote}" after ${attempts} attempt${attempts > 1 ? 's' : ''}: ${causeError.message}`);
|
|
14
|
+
this.name = 'ModuleFederationRemoteLoadError';
|
|
15
|
+
this.remote = remote;
|
|
16
|
+
this.attempts = attempts;
|
|
17
|
+
this.causeError = causeError;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
class ModuleFederationRemoteComponentContractError extends Error {
|
|
21
|
+
constructor(remote, exportName){
|
|
22
|
+
super(`Remote "${remote}" export "${exportName}" is not a valid React component`);
|
|
23
|
+
this.name = 'ModuleFederationRemoteComponentContractError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function toError(error) {
|
|
27
|
+
if (error instanceof Error) return error;
|
|
28
|
+
return new Error('string' == typeof error ? error : 'Unknown remote load error');
|
|
29
|
+
}
|
|
30
|
+
function classifyModuleFederationFallback(error) {
|
|
31
|
+
const normalizedError = toError(error);
|
|
32
|
+
if (normalizedError instanceof ModuleFederationRemoteLoadError) return classifyModuleFederationFallback(normalizedError.causeError);
|
|
33
|
+
if (normalizedError instanceof ModuleFederationRemoteLoadTimeoutError) return 'timeout';
|
|
34
|
+
if (normalizedError instanceof ModuleFederationRemoteComponentContractError) return 'contract';
|
|
35
|
+
const message = normalizedError.message;
|
|
36
|
+
if (/version|requiredVersion|singleton|share scope|shared module/i.test(message)) return 'version-skew';
|
|
37
|
+
if (/network|fetch|script|timeout|chunk|loading/i.test(message)) return 'network';
|
|
38
|
+
return 'remote-unavailable';
|
|
39
|
+
}
|
|
40
|
+
function createModuleFederationFallbackTelemetry(input) {
|
|
41
|
+
const error = void 0 !== input.error ? toError(input.error) : void 0;
|
|
42
|
+
const status = input.status ?? 'degraded';
|
|
43
|
+
const eventName = input.eventName ?? ('recovered' === status ? MODULE_FEDERATION_RECOVERY_SIGNAL_EVENT : MODULE_FEDERATION_FALLBACK_SIGNAL_EVENT);
|
|
44
|
+
const metadata = {
|
|
45
|
+
...input.metadata ?? {},
|
|
46
|
+
classification: input.classification,
|
|
47
|
+
remote: input.remote,
|
|
48
|
+
status
|
|
49
|
+
};
|
|
50
|
+
if (void 0 !== input.exportName) metadata.exportName = input.exportName;
|
|
51
|
+
if (void 0 !== input.runtimeDigest) metadata.runtimeDigest = input.runtimeDigest;
|
|
52
|
+
if (void 0 !== error) {
|
|
53
|
+
metadata.errorName = error.name;
|
|
54
|
+
metadata.errorMessage = error.message;
|
|
55
|
+
}
|
|
56
|
+
const payload = {
|
|
57
|
+
appName: input.appName,
|
|
58
|
+
eventName,
|
|
59
|
+
metadata,
|
|
60
|
+
phase: input.phase,
|
|
61
|
+
reason: input.classification,
|
|
62
|
+
schemaVersion: 1
|
|
63
|
+
};
|
|
64
|
+
if (void 0 !== input.entry) payload.entry = input.entry;
|
|
65
|
+
if (void 0 !== input.runtimeDigest) payload.runtimeDigest = input.runtimeDigest;
|
|
66
|
+
return payload;
|
|
67
|
+
}
|
|
68
|
+
function toModuleFederationFallbackAttributes(payload) {
|
|
69
|
+
return {
|
|
70
|
+
'data-mf-fallback-app': payload.appName,
|
|
71
|
+
'data-mf-fallback-classification': payload.reason,
|
|
72
|
+
'data-mf-fallback-phase': payload.phase,
|
|
73
|
+
'data-mf-fallback-remote': String(payload.metadata.remote),
|
|
74
|
+
'data-mf-fallback-status': String(payload.metadata.status),
|
|
75
|
+
'data-mf-telemetry-event': payload.eventName
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async function emitModuleFederationFallbackTelemetry(input, options = {}) {
|
|
79
|
+
const payload = createModuleFederationFallbackTelemetry(input);
|
|
80
|
+
if ("u" > typeof window && 'function' == typeof window.dispatchEvent && "u" > typeof CustomEvent) window.dispatchEvent(new CustomEvent(payload.eventName, {
|
|
81
|
+
detail: payload
|
|
82
|
+
}));
|
|
83
|
+
const shouldPost = true === options.postSignal || Boolean(options.endpoint);
|
|
84
|
+
if (!shouldPost) return {
|
|
85
|
+
dispatched: true,
|
|
86
|
+
posted: false
|
|
87
|
+
};
|
|
88
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
89
|
+
if ('function' != typeof fetchImpl) return {
|
|
90
|
+
dispatched: true,
|
|
91
|
+
posted: false
|
|
92
|
+
};
|
|
93
|
+
const headers = new Headers({
|
|
94
|
+
'content-type': 'application/json'
|
|
95
|
+
});
|
|
96
|
+
if (void 0 !== options.authToken && options.authToken.length > 0) headers.set(options.authHeaderName ?? DEFAULT_RUNTIME_FALLBACK_SIGNAL_AUTH_HEADER, options.authToken);
|
|
97
|
+
const response = await fetchImpl(options.endpoint ?? DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT, {
|
|
98
|
+
body: JSON.stringify(payload),
|
|
99
|
+
headers,
|
|
100
|
+
method: 'POST',
|
|
101
|
+
keepalive: true
|
|
102
|
+
});
|
|
103
|
+
return {
|
|
104
|
+
dispatched: true,
|
|
105
|
+
posted: true,
|
|
106
|
+
postStatus: response.status
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export { DEFAULT_RUNTIME_FALLBACK_SIGNAL_AUTH_HEADER, DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT, MODULE_FEDERATION_FALLBACK_SIGNAL_EVENT, MODULE_FEDERATION_RECOVERY_SIGNAL_EVENT, ModuleFederationRemoteComponentContractError, ModuleFederationRemoteLoadError, ModuleFederationRemoteLoadTimeoutError, classifyModuleFederationFallback, createModuleFederationFallbackTelemetry, emitModuleFederationFallbackTelemetry, toModuleFederationFallbackAttributes };
|
|
@@ -5,7 +5,6 @@ import { ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME } from "../../../cli/const
|
|
|
5
5
|
import { resolveSSRMode } from "../../../cli/ssr/mode.mjs";
|
|
6
6
|
import { FILE_SYSTEM_ROUTES_FILE_NAME } from "../constants.mjs";
|
|
7
7
|
import { walk } from "./nestedRoutes.mjs";
|
|
8
|
-
import { generateTanstackRouterTypesSourceForEntry, isTanstackRouterFrameworkEnabled } from "./tanstackTypes.mjs";
|
|
9
8
|
import { getServerCombinedModuleFile, getServerLoadersFile } from "./utils.mjs";
|
|
10
9
|
import * as __rspack_external__templates_mjs_4da4c6c8 from "./templates.mjs";
|
|
11
10
|
async function generateRoutesForEntry(entrypoint, appContext) {
|
|
@@ -40,42 +39,11 @@ async function generateRoutesForEntry(entrypoint, appContext) {
|
|
|
40
39
|
}
|
|
41
40
|
return routes;
|
|
42
41
|
}
|
|
43
|
-
const generateCode = async (appContext, config, entrypoints, api
|
|
42
|
+
const generateCode = async (appContext, config, entrypoints, api)=>{
|
|
44
43
|
const { internalDirectory, srcDirectory, internalSrcAlias, packageName } = appContext;
|
|
45
44
|
const hooks = api.getHooks();
|
|
46
|
-
const enableTanstackTypes = options?.enableTanstackTypes ?? await isTanstackRouterFrameworkEnabled(appContext);
|
|
47
45
|
const generatedRoutesByEntry = {};
|
|
48
46
|
await Promise.all(entrypoints.map(generateEntryCode));
|
|
49
|
-
if (enableTanstackTypes) {
|
|
50
|
-
const allEntries = Array.from(new Set(entrypoints.map((e)=>e.entryName).filter(Boolean)));
|
|
51
|
-
const mainEntry = entrypoints.find((e)=>e.isMainEntry)?.entryName;
|
|
52
|
-
const registerEntries = allEntries.sort((a, b)=>{
|
|
53
|
-
if (mainEntry && a === mainEntry) return -1;
|
|
54
|
-
if (mainEntry && b === mainEntry) return 1;
|
|
55
|
-
return a.localeCompare(b);
|
|
56
|
-
});
|
|
57
|
-
if (registerEntries.length > 0) {
|
|
58
|
-
const registerDtsPath = path.join(srcDirectory, 'modern-tanstack', 'register.gen.d.ts');
|
|
59
|
-
const importStatements = registerEntries.map((entryName, index)=>`import type { router as router${index} } from './${entryName}/router.gen';`).join('\n');
|
|
60
|
-
const routerUnionType = registerEntries.map((_, index)=>`typeof router${index}`).join(' | ');
|
|
61
|
-
const registerContent = `// This file is auto-generated by Modern.js. Do not edit manually.
|
|
62
|
-
|
|
63
|
-
${importStatements}
|
|
64
|
-
|
|
65
|
-
declare module '@modern-js/runtime/tanstack-router' {
|
|
66
|
-
interface Register {
|
|
67
|
-
router: ${routerUnionType};
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
`;
|
|
71
|
-
try {
|
|
72
|
-
const prev = await fs.pathExists(registerDtsPath) ? await fs.readFile(registerDtsPath, 'utf-8') : null;
|
|
73
|
-
if (prev !== registerContent) await fs.outputFile(registerDtsPath, registerContent, 'utf-8');
|
|
74
|
-
} catch {
|
|
75
|
-
await fs.outputFile(registerDtsPath, registerContent, 'utf-8');
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
47
|
async function generateEntryCode(entrypoint) {
|
|
80
48
|
const { entryName, isMainEntry, isAutoMount, pageRoutesEntry, nestedRoutesEntry } = entrypoint;
|
|
81
49
|
const { metaName } = api.getAppContext();
|
|
@@ -157,20 +125,6 @@ declare module '@modern-js/runtime/tanstack-router' {
|
|
|
157
125
|
await fs.outputFile(serverLoaderFile, serverLoaderCombined);
|
|
158
126
|
}
|
|
159
127
|
await fs.outputFile(path.resolve(internalDirectory, `./${entryName}/${FILE_SYSTEM_ROUTES_FILE_NAME}`), code, 'utf8');
|
|
160
|
-
if (enableTanstackTypes) {
|
|
161
|
-
const { routerGenTs } = await generateTanstackRouterTypesSourceForEntry({
|
|
162
|
-
appContext,
|
|
163
|
-
entryName,
|
|
164
|
-
routes: routes
|
|
165
|
-
});
|
|
166
|
-
const outPath = path.join(srcDirectory, 'modern-tanstack', entryName, 'router.gen.ts');
|
|
167
|
-
try {
|
|
168
|
-
const prev = await fs.pathExists(outPath) ? await fs.readFile(outPath, 'utf-8') : null;
|
|
169
|
-
if (prev !== routerGenTs) await fs.outputFile(outPath, routerGenTs, 'utf-8');
|
|
170
|
-
} catch {
|
|
171
|
-
await fs.outputFile(outPath, routerGenTs, 'utf-8');
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
128
|
}
|
|
175
129
|
}
|
|
176
130
|
}
|
|
@@ -100,20 +100,7 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
|
|
|
100
100
|
const loadersMapFile = path.join(internalDirectory, entryName, TEMP_LOADERS_DIR, 'map.json');
|
|
101
101
|
const importLazyCode = `
|
|
102
102
|
import { lazy } from "react";
|
|
103
|
-
import
|
|
104
|
-
|
|
105
|
-
const resolveLoadableExport = module => {
|
|
106
|
-
const candidates = [module, module.default, module.default?.default];
|
|
107
|
-
const loadable = candidates.find(candidate => typeof candidate === 'function');
|
|
108
|
-
|
|
109
|
-
if (!loadable) {
|
|
110
|
-
throw new TypeError('Modern.js runtime loadable export must resolve to a function');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return loadable;
|
|
114
|
-
};
|
|
115
|
-
const loadable = resolveLoadableExport(loadableModule);
|
|
116
|
-
const loadableLazy = loadableModule.lazy || loadableModule.default?.lazy || loadable.lazy;
|
|
103
|
+
import loadable, { lazy as loadableLazy } from "@${metaName}/runtime/loadable"
|
|
117
104
|
`;
|
|
118
105
|
let rootLayoutCode = "";
|
|
119
106
|
const getDataLoaderPath = ({ loaderId, clientData, action, inline, routeId, inValidSSRRoute })=>{
|
|
@@ -20,7 +20,7 @@ async function handleGeneratorEntryCode(api, entrypoints, options = {}) {
|
|
|
20
20
|
const { generatorRegisterCode, generateCode, generatorServerRegisterCode } = await import("./code/index.mjs");
|
|
21
21
|
originEntrypointsByKey.set(entrypointsKey, cloneDeep(entrypoints));
|
|
22
22
|
const enableRsc = resolvedConfig?.server?.rsc;
|
|
23
|
-
const routesByEntry = await generateCode(appContext, resolvedConfig, entrypoints, api
|
|
23
|
+
const routesByEntry = await generateCode(appContext, resolvedConfig, entrypoints, api);
|
|
24
24
|
await Promise.all(entrypoints.map(async (entrypoint)=>{
|
|
25
25
|
if (entrypoint.nestedRoutesEntry || entrypoint.pageRoutesEntry) {
|
|
26
26
|
const route = appContext.serverRoutes.find((r)=>r.entryName === entrypoint.entryName);
|
|
@@ -1,28 +1,8 @@
|
|
|
1
1
|
import node_path from "node:path";
|
|
2
|
-
import { NESTED_ROUTE_SPEC_FILE, filterRoutesForServer,
|
|
2
|
+
import { NESTED_ROUTE_SPEC_FILE, filterRoutesForServer, fs } from "@modern-js/utils";
|
|
3
3
|
import { NESTED_ROUTES_DIR } from "./constants.mjs";
|
|
4
4
|
import { BUILT_IN_ROUTES_OWNER, getEntrypointRoutesDir, getEntrypointRoutesOwner, isRouteEntry } from "./entry.mjs";
|
|
5
5
|
import { handleFileChange, handleGeneratorEntryCode, handleModifyEntrypoints } from "./handler.mjs";
|
|
6
|
-
const JS_OR_TS_EXTS = [
|
|
7
|
-
'.js',
|
|
8
|
-
'.jsx',
|
|
9
|
-
'.ts',
|
|
10
|
-
'.tsx',
|
|
11
|
-
'.mjs',
|
|
12
|
-
'.mts',
|
|
13
|
-
'.cjs',
|
|
14
|
-
'.cts'
|
|
15
|
-
];
|
|
16
|
-
function hasRouterConfigInRuntimeFile(runtimeConfigBase) {
|
|
17
|
-
const runtimeConfigFile = findExists(JS_OR_TS_EXTS.map((ext)=>`${runtimeConfigBase}${ext}`));
|
|
18
|
-
if (!runtimeConfigFile) return false;
|
|
19
|
-
try {
|
|
20
|
-
const content = fs.readFileSync(runtimeConfigFile, 'utf-8');
|
|
21
|
-
return /router\s*:/.test(content);
|
|
22
|
-
} catch {
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
6
|
function isBuiltInRouteEntrypoint(entrypoint) {
|
|
27
7
|
const entrypointRoutesOwner = getEntrypointRoutesOwner(entrypoint);
|
|
28
8
|
if (entrypointRoutesOwner) return entrypointRoutesOwner === BUILT_IN_ROUTES_OWNER;
|
|
@@ -52,12 +32,11 @@ const routerPlugin = ()=>({
|
|
|
52
32
|
});
|
|
53
33
|
});
|
|
54
34
|
api._internalRuntimePlugins(({ entrypoint, plugins })=>{
|
|
55
|
-
const { serverRoutes, metaName
|
|
35
|
+
const { serverRoutes, metaName } = api.getAppContext();
|
|
56
36
|
const normalizedConfig = api.getNormalizedConfig();
|
|
57
37
|
const hasUserRouterConfig = normalizedConfig.router && Object.keys(normalizedConfig.router).length > 0;
|
|
58
|
-
const hasRuntimeRouterConfig = hasRouterConfigInRuntimeFile(node_path.join(srcDirectory, runtimeConfigFile));
|
|
59
38
|
const serverBase = serverRoutes.filter((route)=>route.entryName === entrypoint.entryName).map((route)=>route.urlPath).sort((a, b)=>a.length - b.length > 0 ? -1 : 1);
|
|
60
|
-
const shouldInstallBuiltInRouter = isBuiltInRouteEntrypoint(entrypoint) || !isPluginOwnedRouteEntrypoint(entrypoint) &&
|
|
39
|
+
const shouldInstallBuiltInRouter = isBuiltInRouteEntrypoint(entrypoint) || !isPluginOwnedRouteEntrypoint(entrypoint) && hasUserRouterConfig;
|
|
61
40
|
if (shouldInstallBuiltInRouter) plugins.push({
|
|
62
41
|
name: 'router',
|
|
63
42
|
path: `@${metaName}/runtime/router/internal`,
|
|
@@ -4,6 +4,21 @@ import { useEffect, useMemo, useRef } from "react";
|
|
|
4
4
|
import { ROUTER_DATA_JSON_ID } from "../../core/constants.mjs";
|
|
5
5
|
import { modernInline, runWindowFnStr } from "./constants.mjs";
|
|
6
6
|
import { serializeErrors } from "./utils.mjs";
|
|
7
|
+
function toDeferredErrorInfo(error) {
|
|
8
|
+
if ('production' === process.env.NODE_ENV) return {
|
|
9
|
+
message: 'Unexpected Server Error'
|
|
10
|
+
};
|
|
11
|
+
if (error && 'object' == typeof error) {
|
|
12
|
+
const maybeMessage = error.message;
|
|
13
|
+
return {
|
|
14
|
+
message: 'string' == typeof maybeMessage ? maybeMessage : String(maybeMessage ?? error),
|
|
15
|
+
stack: error.stack
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
message: String(error)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
7
22
|
const DeferredDataScripts = (props)=>{
|
|
8
23
|
const staticContext = props?.context;
|
|
9
24
|
const useJsonScript = props?.useJsonScript;
|
|
@@ -39,10 +54,7 @@ const DeferredDataScripts = (props)=>{
|
|
|
39
54
|
{
|
|
40
55
|
const trackedPromise = deferredData.data[key];
|
|
41
56
|
if (void 0 !== trackedPromise._error) {
|
|
42
|
-
const error =
|
|
43
|
-
message: trackedPromise._error.message,
|
|
44
|
-
stack: 'production' !== process.env.NODE_ENV ? trackedPromise._error.stack : void 0
|
|
45
|
-
};
|
|
57
|
+
const error = toDeferredErrorInfo(trackedPromise._error);
|
|
46
58
|
return {
|
|
47
59
|
key,
|
|
48
60
|
routerDataFnName: 'p',
|
|
@@ -11,7 +11,6 @@ function composeEventHandlers(theirHandler, ourHandler) {
|
|
|
11
11
|
}
|
|
12
12
|
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
13
13
|
const DEFAULT_PREFETCH_BEHAVIOR = 'render';
|
|
14
|
-
const DEFAULT_PRELOAD_BEHAVIOR = 'viewport';
|
|
15
14
|
const INTENT_DELAY = 100;
|
|
16
15
|
const VIEWPORT_ROOT_MARGIN = '200px';
|
|
17
16
|
const MAX_CONCURRENT_WARMUPS = 4;
|
|
@@ -76,7 +75,7 @@ const setRef = (ref, value)=>{
|
|
|
76
75
|
};
|
|
77
76
|
const isDataWarmupEnabled = (route)=>{
|
|
78
77
|
const handle = route.handle;
|
|
79
|
-
return handle?.navigationWarmup?.data
|
|
78
|
+
return handle?.navigationWarmup?.data !== false;
|
|
80
79
|
};
|
|
81
80
|
function usePrefetchBehavior(prefetch, preload, theirElementProps) {
|
|
82
81
|
const [maybeWarmup, setMaybeWarmup] = react.useState(false);
|
|
@@ -250,7 +249,7 @@ const normalizePreloadBehavior = (preload, prefetch)=>{
|
|
|
250
249
|
if (false === preload || 'none' === preload) return 'none';
|
|
251
250
|
if (void 0 !== preload) return preload;
|
|
252
251
|
if ('none' === prefetch) return 'none';
|
|
253
|
-
return
|
|
252
|
+
return prefetch;
|
|
254
253
|
};
|
|
255
254
|
const createPrefetchLink = (Link)=>/*#__PURE__*/ react.forwardRef(({ to, prefetch = DEFAULT_PREFETCH_BEHAVIOR, preload, ...props }, forwardedRef)=>{
|
|
256
255
|
const isAbsolute = 'string' == typeof to && ABSOLUTE_URL_REGEX.test(to);
|