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(/=$/) && !isFirstRender) {
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.164",
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 🚀",