nitro-web 0.0.164 → 0.0.165
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
|
|
@@ -216,7 +220,13 @@ function getRouter({ settings, config }: { settings: Settings, config: Config })
|
|
|
216
220
|
for (const key of route.middleware) {
|
|
217
221
|
const error = settings.middleware[key](route, exposedStoreData || {})
|
|
218
222
|
if (error && error.redirect) {
|
|
219
|
-
|
|
223
|
+
// Redirect() will use the new pathname instead of the current one for values without a pathname causing guard
|
|
224
|
+
// redirect loops! We assume these query string redirects are intended to be relative to the current path.
|
|
225
|
+
if (error.redirect.startsWith('?')) {
|
|
226
|
+
return redirect(window.location.pathname + error.redirect)
|
|
227
|
+
} else {
|
|
228
|
+
return redirect(error.redirect)
|
|
229
|
+
}
|
|
220
230
|
}
|
|
221
231
|
}
|
|
222
232
|
return null
|
|
@@ -269,6 +279,22 @@ function scrollbarElement() {
|
|
|
269
279
|
return document.getElementById('app') // was window.scrollY
|
|
270
280
|
}
|
|
271
281
|
|
|
282
|
+
function catchRedirectLoop(request: Request, routeName: string) {
|
|
283
|
+
if (request.url === lastRedirectUrl) {
|
|
284
|
+
const lastRedirectTime = lastRedirectTimesForSameUrl[lastRedirectTimesForSameUrl.length - 1] || 0
|
|
285
|
+
lastRedirectUrl = request.url
|
|
286
|
+
lastRedirectTimesForSameUrl.push(Date.now())
|
|
287
|
+
if (lastRedirectTimesForSameUrl.length > 5 && (Date.now() < lastRedirectTime + 100)) {
|
|
288
|
+
throw new Error(
|
|
289
|
+
`Nitro: A redirect loop has been detected for route '${routeName}'. This ismost likely due to a redirect loop caused by your middleware.`
|
|
290
|
+
)
|
|
291
|
+
}
|
|
292
|
+
} else {
|
|
293
|
+
lastRedirectUrl = request.url
|
|
294
|
+
lastRedirectTimesForSameUrl = []
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
272
298
|
// ---- Overridable defaults ------------
|
|
273
299
|
|
|
274
300
|
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.165",
|
|
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 🚀",
|