@autobusal/providers 1.42.0 → 1.43.1

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.
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import Message from './Message';
3
+ import { isRecoveringFromStaleChunk } from '../Setup/staleChunk';
3
4
 
4
5
  interface Props {
5
6
  children: JSX.Element[] | JSX.Element
@@ -36,6 +37,26 @@ class ErrorBoundary extends React.Component<Props, { hasError: boolean; missing:
36
37
 
37
38
  render() {
38
39
  if (this.state.hasError) {
40
+ /*
41
+ * Claude - 2026-08-31: say nothing while a stale-chunk reload is on its
42
+ * way.
43
+ *
44
+ * A build replaces every hashed chunk, so a tab left open overnight
45
+ * asks for files that no longer exist the moment somebody clicks a
46
+ * link. Setup/staleChunk catches that and reloads - which works, and
47
+ * which the visitor experienced as a flash of "something went wrong"
48
+ * first, because a synchronous re-render beats a navigation the browser
49
+ * has merely been asked to perform.
50
+ *
51
+ * Nothing at all rather than a spinner: the reload is a few hundred
52
+ * milliseconds away and the document is about to be replaced wholesale.
53
+ * A spinner appearing and vanishing in that window is the same flicker
54
+ * in a friendlier colour.
55
+ */
56
+ if (isRecoveringFromStaleChunk()) {
57
+ return null;
58
+ }
59
+
39
60
  return <Message type={ this.state.missing ? 'not_found' : 'error' } />;
40
61
  }
41
62
 
@@ -93,6 +93,30 @@ const remember = (path: string): boolean => {
93
93
  * sites. Calling preventDefault stops Vite rethrowing, since we are handling
94
94
  * it by replacing the document.
95
95
  */
96
+ /*
97
+ * Whether a recovery reload is already on its way.
98
+ *
99
+ * Claude - 2026-08-31. Ferjolt: "When the page is left open for some time and
100
+ * then click on any link on it, firstly it displays an error page for a
101
+ * extremely short moment and after that renders the right page."
102
+ *
103
+ * That flash is the ERROR BOUNDARY, and it is a race we were always going to
104
+ * lose. A failed dynamic import produces two things at once: this event, and
105
+ * a rejected lazy component that React hands to the nearest boundary. The
106
+ * boundary re-renders synchronously; window.location.reload() only asks the
107
+ * browser to navigate, and the browser is free to paint the frame it already
108
+ * has work for first. So the visitor sees "something went wrong" for one
109
+ * frame of a recovery that is working perfectly.
110
+ *
111
+ * A module-level flag rather than state: the boundary that needs to read this
112
+ * is a class component reacting to a throw, with no chance to subscribe to
113
+ * anything, and the answer has to be available synchronously inside
114
+ * getDerivedStateFromError.
115
+ */
116
+ let recovering = false;
117
+
118
+ export const isRecoveringFromStaleChunk = (): boolean => recovering;
119
+
96
120
  const registerStaleChunkRecovery = (): void => {
97
121
  window.addEventListener('vite:preloadError', (event) => {
98
122
  if (!remember(budgetKey())) {
@@ -103,6 +127,14 @@ const registerStaleChunkRecovery = (): void => {
103
127
 
104
128
  event.preventDefault();
105
129
 
130
+ /*
131
+ * Set BEFORE the reload is requested, so the error boundary can already
132
+ * see it on the render that the failed import is about to trigger. Never
133
+ * cleared: the only thing that follows is a fresh document, which starts
134
+ * with a fresh module and the flag back to false.
135
+ */
136
+ recovering = true;
137
+
106
138
  // reload() and not assign(): the URL is already the destination - React
107
139
  // Router changes it before rendering the route whose chunk just failed -
108
140
  // so this fetches a fresh index.html and lands on the page that was asked
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autobusal/providers",
3
- "version": "1.42.0",
3
+ "version": "1.43.1",
4
4
  "author": "Ferjolt Ozuni",
5
5
  "type": "module",
6
6
  "main": "index.ts",
package/types/users.ts CHANGED
@@ -19,6 +19,12 @@ export interface UserData {
19
19
  // operator/employee accounts - whether the company's Shipments module is
20
20
  // on, so menus can hide the link instead of advertising a 403.
21
21
  shipping_enabled?: boolean | null
22
+ // Claude - 2026-08-31: whether this admin belongs to the MAIN label. Same
23
+ // job as shipping_enabled above - the platform-wide screens (database
24
+ // backups) answer a 404 to a whitelabel admin, and a menu should hide the
25
+ // link rather than advertise a door that does not open. Null for every
26
+ // non-admin type.
27
+ is_main_label?: boolean | null
22
28
  comissions: ComissionData
23
29
  subscription: SubscribedData
24
30
  api: ApiData