@jk2908/solas 0.3.4 → 0.3.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.6 - 2026-04-24
4
+
5
+ - Fixed broken client-side `<Link />` navigation in Vite dev by excluding Solas browser runtime entry points from `optimizeDeps`, so the browser entry and client-reference router modules share a single `BrowserRouterContext` instance.
6
+
7
+ ## 0.3.5 - 2026-04-23
8
+
9
+ - Fixed client-side navigation to same-origin routes that later resolve to a 404 or error state by committing the target URL to browser history before the RSC payload finishes loading, so broken internal links no longer leave the route unchanged.
10
+
3
11
  ## 0.3.4 - 2026-04-23
4
12
 
5
13
  - Fixed `hydrateRoot` missing named export error in the browser by removing the erroneous `optimizeDeps.exclude` for `react-dom/client`. Excluding it prevented Vite from pre-bundling the CommonJS wrapper, so the named export was never exposed to browser ESM consumers.
package/dist/index.js CHANGED
@@ -173,6 +173,9 @@ function solas(c) {
173
173
  async config(viteConfig) {
174
174
  await build();
175
175
  const pkg = JSON.parse(fsSync.readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
176
+ if (typeof pkg.name !== 'string' || pkg.name.length === 0) {
177
+ throw new Error(`Missing ${Solas.Config.NAME} package name`);
178
+ }
176
179
  if (typeof pkg.version !== 'string' || pkg.version.length === 0) {
177
180
  throw new Error(`Missing ${Solas.Config.NAME} package version`);
178
181
  }
@@ -184,11 +187,28 @@ function solas(c) {
184
187
  viteConfig.define ??= {};
185
188
  viteConfig.define['import.meta.env.VITE_APP_URL'] = JSON.stringify(config.url);
186
189
  viteConfig.define['import.meta.env.SOLAS_VERSION'] = JSON.stringify(pkg.version);
190
+ viteConfig.optimizeDeps ??= {};
191
+ viteConfig.optimizeDeps.exclude = [
192
+ ...new Set([
193
+ ...(viteConfig.optimizeDeps.exclude ?? []),
194
+ pkg.name,
195
+ `${pkg.name}/env/browser`,
196
+ `${pkg.name}/router`,
197
+ ]),
198
+ ];
187
199
  viteConfig.resolve ??= {};
188
- viteConfig.resolve.alias = {
189
- ...(viteConfig.resolve.alias ?? {}),
190
- '.solas': path.resolve(process.cwd(), Solas.Config.GENERATED_DIR),
191
- };
200
+ viteConfig.resolve.alias = Array.isArray(viteConfig.resolve.alias)
201
+ ? [
202
+ ...viteConfig.resolve.alias,
203
+ {
204
+ find: '.solas',
205
+ replacement: path.resolve(process.cwd(), Solas.Config.GENERATED_DIR),
206
+ },
207
+ ]
208
+ : {
209
+ ...viteConfig.resolve.alias,
210
+ '.solas': path.resolve(process.cwd(), Solas.Config.GENERATED_DIR),
211
+ };
192
212
  },
193
213
  configureServer(server) {
194
214
  logger.info('[configureServer]', `Watching for changes in ./${Solas.Config.APP_DIR}...`);
@@ -95,7 +95,8 @@ export function BrowserRouterProvider({ children, setPayload, isNavigating = fal
95
95
  id.current += 1;
96
96
  const navigationId = id.current;
97
97
  // fallback for abort/error paths
98
- let path = window.location.pathname + window.location.search;
98
+ const currentPath = window.location.pathname + window.location.search;
99
+ let path = currentPath;
99
100
  const replace = opts?.replace ?? DEFAULT_GO_CONFIG.replace;
100
101
  controller.current?.abort();
101
102
  controller.current = null;
@@ -113,6 +114,16 @@ export function BrowserRouterProvider({ children, setPayload, isNavigating = fal
113
114
  throw new Error('Invalid navigation url');
114
115
  // switch to the normalised target once the url is valid
115
116
  path = key;
117
+ // internal client navigation should update the route immediately, even
118
+ // if the subsequent fetch resolves to a 404 or other error state
119
+ if (path !== currentPath) {
120
+ if (replace) {
121
+ window.history.replaceState(null, '', path);
122
+ }
123
+ else {
124
+ window.history.pushState(null, '', path);
125
+ }
126
+ }
116
127
  // if the target was already prefetched, use the cached response promise
117
128
  // and set existing to true so we don't remove it from cache
118
129
  // after navigation
@@ -143,15 +154,12 @@ export function BrowserRouterProvider({ children, setPayload, isNavigating = fal
143
154
  // the response
144
155
  if (navigationId !== id.current)
145
156
  return resolvedPath;
157
+ if (resolvedPath !== path) {
158
+ window.history.replaceState(null, '', resolvedPath);
159
+ }
146
160
  // this state update is already wrapped in a
147
161
  // transition before being passed as props
148
162
  setPayload?.(payload);
149
- if (replace) {
150
- window.history.replaceState(null, '', resolvedPath);
151
- }
152
- else {
153
- window.history.pushState(null, '', resolvedPath);
154
- }
155
163
  window.dispatchEvent(new CustomEvent(Solas.Events.names.NAVIGATION, {
156
164
  detail: { path: resolvedPath },
157
165
  }));
@@ -214,5 +222,5 @@ export function BrowserRouterProvider({ children, setPayload, isNavigating = fal
214
222
  search: url?.search,
215
223
  },
216
224
  }), [go, prefetch, isNavigating, url]);
217
- return _jsx(BrowserRouterContext, { value: value, children: children });
225
+ return _jsx(BrowserRouterContext.Provider, { value: value, children: children });
218
226
  }
@@ -162,7 +162,7 @@ async function writePayload(payload, controller, nonce) {
162
162
  catch {
163
163
  // most rows are text, but keep binary chunks intact when a payload
164
164
  // row cannot be decoded as utf-8
165
- const base64 = JSON.stringify(window.btoa(String.fromCodePoint(...chunk)));
165
+ const base64 = JSON.stringify(btoa(String.fromCodePoint(...chunk)));
166
166
  writePayloadScript(`Uint8Array.from(atob(${base64}), value => value.codePointAt(0))`, controller, nonce);
167
167
  }
168
168
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jk2908/solas",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "A React Server Components meta-framework powered by Vite",
5
5
  "keywords": [
6
6
  "framework",