nitro-web 0.0.164 → 0.0.166
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/client/app.tsx
CHANGED
|
@@ -38,6 +38,9 @@ type RouteWithPolicies = Route & {
|
|
|
38
38
|
[key: string]: true | string | (string | true)[]
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
let lastRedirectUrl = ''
|
|
42
|
+
let lastRedirectTimesForSameUrl: number[] = []
|
|
43
|
+
|
|
41
44
|
export async function setupApp(config: Config, storeContainer: StoreContainer, layouts: React.FC<LayoutProps>[]) {
|
|
42
45
|
if (!layouts) throw new Error('layouts are required')
|
|
43
46
|
if (!(window as unknown as { useTracked: unknown }).useTracked) {
|
|
@@ -207,7 +210,8 @@ function getRouter({ settings, config }: { settings: Settings, config: Config })
|
|
|
207
210
|
<RouteComponent route={route} config={config} />
|
|
208
211
|
),
|
|
209
212
|
path: route.path,
|
|
210
|
-
loader: async () => { // request
|
|
213
|
+
loader: async ({ request }: { request: Request }) => { // request
|
|
214
|
+
catchRedirectLoop(request, route.name)
|
|
211
215
|
// wait for container/exposedStoreData to be setup (note that this causes ReactRouter to re-render, but not the page)
|
|
212
216
|
if (!nonce) {
|
|
213
217
|
nonce = true
|
|
@@ -215,6 +219,8 @@ function getRouter({ settings, config }: { settings: Settings, config: Config })
|
|
|
215
219
|
}
|
|
216
220
|
for (const key of route.middleware) {
|
|
217
221
|
const error = settings.middleware[key](route, exposedStoreData || {})
|
|
222
|
+
// Note: the redirect uses the new pathname for query string values, e.g. '?example=value'. We also can't use the
|
|
223
|
+
// current pathname, as this doesn't exist on page refresh.
|
|
218
224
|
if (error && error.redirect) {
|
|
219
225
|
return redirect(error.redirect)
|
|
220
226
|
}
|
|
@@ -269,6 +275,22 @@ function scrollbarElement() {
|
|
|
269
275
|
return document.getElementById('app') // was window.scrollY
|
|
270
276
|
}
|
|
271
277
|
|
|
278
|
+
function catchRedirectLoop(request: Request, routeName: string) {
|
|
279
|
+
if (request.url === lastRedirectUrl) {
|
|
280
|
+
const lastRedirectTime = lastRedirectTimesForSameUrl[lastRedirectTimesForSameUrl.length - 1] || 0
|
|
281
|
+
lastRedirectUrl = request.url
|
|
282
|
+
lastRedirectTimesForSameUrl.push(Date.now())
|
|
283
|
+
if (lastRedirectTimesForSameUrl.length > 5 && (Date.now() < lastRedirectTime + 100)) {
|
|
284
|
+
throw new Error(
|
|
285
|
+
`Nitro: A redirect loop has been detected for route '${routeName}'. This is most likely due to a redirect loop caused by your middleware. Consider triggered by redirect values without a pathname, e.g. '?example=value'.`
|
|
286
|
+
)
|
|
287
|
+
}
|
|
288
|
+
} else {
|
|
289
|
+
lastRedirectUrl = request.url
|
|
290
|
+
lastRedirectTimesForSameUrl = []
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
272
294
|
// ---- Overridable defaults ------------
|
|
273
295
|
|
|
274
296
|
async function beforeApp(config: Config) {
|
|
@@ -115,7 +115,7 @@ export function Message({ className, classNameWrapper, icons: iconsProp, positio
|
|
|
115
115
|
if (Array.isArray(query[key])) continue
|
|
116
116
|
const rawQueryValue = query[key] as string
|
|
117
117
|
|
|
118
|
-
if (rawQueryValue.match(
|
|
118
|
+
if (rawQueryValue.match(/~$/) && !isFirstRender) {
|
|
119
119
|
// Only show if first render, otherwise skip internal tracking of the message
|
|
120
120
|
continue
|
|
121
121
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nitro-web",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.166",
|
|
4
4
|
"repository": "github:boycce/nitro-web",
|
|
5
5
|
"homepage": "https://boycce.github.io/nitro-web/",
|
|
6
6
|
"description": "Nitro is a battle-tested, modular base project to turbocharge your projects, styled using Tailwind 🚀",
|