@solidjs/router 2.0.0-next.20 → 2.0.0-next.22

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,6 +1,6 @@
1
1
  import { $TRACK, action as createSolidAction, createMemo, onCleanup, getOwner } from "solid-js";
2
2
  import { isResponseEnvelope, isServer, REVALIDATE_HEADER } from "@solidjs/web";
3
- import { createServerReference, decodeResponsePayload, parseServerFunctionUrl, subscribeFlightData } from "@solidjs/web/server-functions";
3
+ import { createServerReference, decodeRedirectHeaderValue, decodeResponsePayload, parseServerFunctionUrl, REDIRECT_HEADER, subscribeFlightData } from "@solidjs/web/server-functions";
4
4
  // The explicit /server specifier is safe here: the only call site is
5
5
  // server-guarded, so client builds tree-shake the codec away.
6
6
  import { decodeFlashCookie } from "@solidjs/web/server-functions/server";
@@ -68,11 +68,13 @@ export function handleFormAction(evt, router, actionBase) {
68
68
  * carries everything an invocation needs — the function id in the path
69
69
  * (`<endpoint>/<id>`) and any bound `.with()` arguments (plain JSON in
70
70
  * `?args`, which the server prepends for natural-encoding bodies exactly as
71
- * it does for no-JS posts) — so the FormData is posted to it verbatim
72
- * through the server-function transport:
73
- * submissions, `aria-busy`, redirects, revalidation, and single-flight all
74
- * flow through the normal action machinery. Registered under the url, so
75
- * repeat submits reuse it (and a later real registration overrides it).
71
+ * it does for no-JS posts) — so the FormData is posted through the
72
+ * server-function transport, which addresses its own scripted calls at the
73
+ * url's data sibling (`<endpoint>/data/<id>`, solidjs/solid#3094) with the
74
+ * bound query intact: submissions, `aria-busy`, redirects, revalidation,
75
+ * and single-flight all flow through the normal action machinery.
76
+ * Registered under the rendered url, so repeat submits reuse it (and a
77
+ * later real registration overrides it).
76
78
  */
77
79
  function createServerFormAction(url) {
78
80
  const id = parseServerFunctionUrl(url);
@@ -116,6 +118,7 @@ function installRouterIntegrations() {
116
118
  if (isServer) {
117
119
  // Server-only: initSubmissions only decodes during SSR, so client builds
118
120
  // tree-shake the codec (which now lives behind the runtime's server entry).
121
+ // The codec is async from @solidjs/web 2.0.0-rc.7 (encrypted cookie).
119
122
  provideFlashDecoder(decodeFlashCookie);
120
123
  }
121
124
  else {
@@ -290,6 +293,10 @@ async function settleActionResult(result) {
290
293
  // response's metadata (and so the default revalidation pass must not run
291
294
  // again and wipe the freshly seeded cache).
292
295
  let flightApplications = 0;
296
+ // The statuses fetch follows (Fetch §2.2.3) — the set the server masks into
297
+ // the redirect carrier for scripted calls, and the set a locally-produced
298
+ // redirect() envelope wears for real.
299
+ const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
293
300
  /**
294
301
  * Registers the router as the single-flight consumer of the server function
295
302
  * transport. Subscribing is the opt-in: while registered, the transport
@@ -309,23 +316,43 @@ export function setupFlightDataConsumer(router) {
309
316
  }
310
317
  /**
311
318
  * Applies a server function response's integration metadata: `X-Revalidate`
312
- * keys invalidate, `Location` navigates (hard for absolute urls), flight
313
- * data seeds the query cache, and matching entries revalidate. Shared by
314
- * the flight-data consumer and the action response path (which still sees
315
- * metadata-bearing responses when no flight data was collected).
319
+ * keys invalidate, the redirect carrier navigates (soft when same-origin,
320
+ * hard otherwise), flight data seeds the query cache, and matching entries
321
+ * revalidate. Shared by the flight-data consumer and the action response
322
+ * path (which still sees metadata-bearing responses when no flight data was
323
+ * collected).
316
324
  */
317
325
  function applyResponseMetadata(metadata, navigate, flightData) {
318
326
  let keys;
319
327
  if (metadata) {
320
328
  if (metadata.headers.has(REVALIDATE_HEADER))
321
329
  keys = metadata.headers.get(REVALIDATE_HEADER).split(",");
322
- if (metadata.headers.has("Location")) {
323
- const locationUrl = metadata.headers.get("Location") || "/";
324
- if (locationUrl.startsWith("http")) {
325
- window.location.href = locationUrl;
330
+ // The carrier delivers the target RESOLVED to an absolute url
331
+ // (solidjs/solid#3102), so the soft/hard split is a real origin
332
+ // comparison — never a guess from how the author spelled the target,
333
+ // which sent `redirect("/")` and `redirect(new URL("/", url).href)`
334
+ // down different navigation paths (solidjs/solid#3107). A redirect
335
+ // produced locally (a client-side action's `redirect()`) never crossed
336
+ // the wire, so no carrier was attached: it is the real 3xx with its
337
+ // Location, resolved against the page it runs in. A `Location` on any
338
+ // other status is the author's data (a 201's created-at) and never
339
+ // navigates. Same-origin targets navigate softly under the router;
340
+ // anything else leaves the app, so the document goes with it.
341
+ // `replace` matches what HTTP gives a form post: the target takes the
342
+ // submission's place in history rather than stacking on it.
343
+ const carried = decodeRedirectHeaderValue(metadata.headers.get(REDIRECT_HEADER));
344
+ const local = !carried && REDIRECT_STATUSES.has(metadata.status) && metadata.headers.get("Location");
345
+ const target = carried
346
+ ? new URL(carried.url)
347
+ : local
348
+ ? new URL(local, window.location.href)
349
+ : undefined;
350
+ if (target) {
351
+ if (target.origin === window.location.origin) {
352
+ navigate(target.pathname + target.search + target.hash, { replace: true });
326
353
  }
327
354
  else {
328
- navigate(locationUrl);
355
+ window.location.href = target.href;
329
356
  }
330
357
  }
331
358
  }
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { getOwner, runWithOwner, createMemo, createRenderEffect, onCleanup, untrack, createContext, createSignal, useContext, NotReadyError, isPending, DEV, latest, createComponent, createRoot, Show, createEffect, sharedConfig, onSettled, getObserver, $TRACK, action as action$1 } from 'solid-js';
2
2
  import { registerElementClaim, delegateEvents, isServer, getRequestEvent, hasFlashCookie, clearFlashCookie, createComponent as createComponent$1, memo, isServerFunction, getServerFunctionMetadata, getServerFunctionRPC, isResponseEnvelope, REVALIDATE_HEADER } from '@solidjs/web';
3
- import { subscribeFlightData, decodeResponsePayload, parseServerFunctionUrl, createServerReference } from '@solidjs/web/server-functions';
3
+ import { subscribeFlightData, decodeRedirectHeaderValue, REDIRECT_HEADER, decodeResponsePayload, parseServerFunctionUrl, createServerReference } from '@solidjs/web/server-functions';
4
4
  import { decodeFlashCookie } from '@solidjs/web/server-functions/server';
5
5
 
6
6
  const hasSchemeRegex = /^(?:[a-z0-9]+:)?\/\//i;
@@ -1097,7 +1097,12 @@ function provideFlightConsumer(factory) {
1097
1097
  * decoder is always installed before useSubmission can read — and a
1098
1098
  * router-only app, where it never installs, has no actions that could have
1099
1099
  * produced a flash cookie in the first place.
1100
+ *
1101
+ * The decoder is async: the flash cookie is encrypted (solidjs/solid#3239),
1102
+ * so the runtime's `decodeFlashCookie` decrypts through WebCrypto and the
1103
+ * seeding read parks on the not-ready protocol until the decode settles.
1100
1104
  */
1105
+
1101
1106
  let flashDecoder;
1102
1107
  function provideFlashDecoder(decoder) {
1103
1108
  flashDecoder || (flashDecoder = decoder);
@@ -1153,6 +1158,54 @@ function createRouterContext(integration, branches, getContext, options = {}) {
1153
1158
  }
1154
1159
  }
1155
1160
  }
1161
+
1162
+ // The decode, at most once per request: the decoder may answer with a
1163
+ // Promise (the cookie is encrypted; the runtime's decodeFlashCookie is
1164
+ // async), and this cache is what keeps the parked read's rerun from
1165
+ // restarting it — resumption finds the settled outcome and just reads it.
1166
+ // A decoder that rejects reads as "no flash", matching the runtime's own
1167
+ // malformed-cookie semantics.
1168
+ let flashDecode;
1169
+
1170
+ // The seeding read, as a memo: NotReadyError must surface from a reactive
1171
+ // node the graph can park and retry — never from router setup, which no
1172
+ // boundary guards — and the memo bounds the recompute to this function;
1173
+ // a parked reader resumes into the settled cache above, never a second
1174
+ // decode. Created only when a flash cookie actually arrived (server-only
1175
+ // by construction: flashCookieHeader is only ever set there), and
1176
+ // - `lazy`: server memos compute eagerly by default — deferred to first
1177
+ // read, a request whose submissions are never read never decodes;
1178
+ // - `transparent`: the memo exists on the server only, so its owner
1179
+ // must not consume a hydration-id slot — the client, which seeds
1180
+ // submissions as [] without ever creating this memo, would miss it
1181
+ // and every sibling id would shift.
1182
+ const flashSubmission = flashCookieHeader !== undefined ? createMemo(() => {
1183
+ if (!flashDecoder) return undefined;
1184
+ if (!flashDecode) {
1185
+ const promise = flashDecoder(flashCookieHeader).then(value => {
1186
+ flashDecode = {
1187
+ done: true,
1188
+ value
1189
+ };
1190
+ }, () => {
1191
+ flashDecode = {
1192
+ done: true,
1193
+ value: undefined
1194
+ };
1195
+ });
1196
+ flashDecode = {
1197
+ done: false,
1198
+ promise
1199
+ };
1200
+ }
1201
+ // SSR carries the Promise through NotReadyError so the parked
1202
+ // reader can resume, exactly like the lazy matches above.
1203
+ if (!flashDecode.done) throw new NotReadyError(flashDecode.promise);
1204
+ return flashDecode.value;
1205
+ }, {
1206
+ lazy: true,
1207
+ transparent: true
1208
+ }) : undefined;
1156
1209
  let submissions;
1157
1210
 
1158
1211
  // NotReadyError's source must be a reactive async node, not the raw
@@ -1384,12 +1437,16 @@ function createRouterContext(integration, branches, getContext, options = {}) {
1384
1437
  // Seeds the initial submission from a no-JS form post: the server
1385
1438
  // function runtime redirected back with the outcome in a one-shot flash
1386
1439
  // cookie (its default no-JS convention), consumed eagerly above and
1387
- // decoded here — so the post-redirect SSR renders useSubmission() state
1388
- // exactly as a scripted submission would. An explicitly pre-seeded
1389
- // `event.router.submission` (framework integrations) takes precedence.
1440
+ // decoded through the flashSubmission memo — so the post-redirect SSR
1441
+ // renders useSubmission() state exactly as a scripted submission would.
1442
+ // The memo read may throw NotReadyError while the (encrypted) cookie
1443
+ // decodes; the assignment in the submissions getter never completed, so
1444
+ // the resumed rerun retries it against the settled decode. An explicitly
1445
+ // pre-seeded `event.router.submission` (framework integrations) takes
1446
+ // precedence.
1390
1447
  function initSubmissions() {
1391
1448
  const e = getRequestEvent();
1392
- const submission = e && e.router && e.router.submission || (flashDecoder && flashCookieHeader !== undefined ? flashDecoder(flashCookieHeader) : undefined);
1449
+ const submission = e && e.router && e.router.submission || flashSubmission && flashSubmission();
1393
1450
  if (!submission) return [];
1394
1451
  return [{
1395
1452
  ...submission,
@@ -2562,11 +2619,13 @@ function handleFormAction(evt, router, actionBase) {
2562
2619
  * carries everything an invocation needs — the function id in the path
2563
2620
  * (`<endpoint>/<id>`) and any bound `.with()` arguments (plain JSON in
2564
2621
  * `?args`, which the server prepends for natural-encoding bodies exactly as
2565
- * it does for no-JS posts) — so the FormData is posted to it verbatim
2566
- * through the server-function transport:
2567
- * submissions, `aria-busy`, redirects, revalidation, and single-flight all
2568
- * flow through the normal action machinery. Registered under the url, so
2569
- * repeat submits reuse it (and a later real registration overrides it).
2622
+ * it does for no-JS posts) — so the FormData is posted through the
2623
+ * server-function transport, which addresses its own scripted calls at the
2624
+ * url's data sibling (`<endpoint>/data/<id>`, solidjs/solid#3094) with the
2625
+ * bound query intact: submissions, `aria-busy`, redirects, revalidation,
2626
+ * and single-flight all flow through the normal action machinery.
2627
+ * Registered under the rendered url, so repeat submits reuse it (and a
2628
+ * later real registration overrides it).
2570
2629
  */
2571
2630
  function createServerFormAction(url) {
2572
2631
  const id = parseServerFunctionUrl(url);
@@ -2614,6 +2673,7 @@ function installRouterIntegrations() {
2614
2673
  if (isServer) {
2615
2674
  // Server-only: initSubmissions only decodes during SSR, so client builds
2616
2675
  // tree-shake the codec (which now lives behind the runtime's server entry).
2676
+ // The codec is async from @solidjs/web 2.0.0-rc.7 (encrypted cookie).
2617
2677
  provideFlashDecoder(decodeFlashCookie);
2618
2678
  } else {
2619
2679
  setRouterFormHandler(handleFormAction);
@@ -2791,6 +2851,11 @@ async function settleActionResult(result) {
2791
2851
  // again and wipe the freshly seeded cache).
2792
2852
  let flightApplications = 0;
2793
2853
 
2854
+ // The statuses fetch follows (Fetch §2.2.3) — the set the server masks into
2855
+ // the redirect carrier for scripted calls, and the set a locally-produced
2856
+ // redirect() envelope wears for real.
2857
+ const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
2858
+
2794
2859
  /**
2795
2860
  * Registers the router as the single-flight consumer of the server function
2796
2861
  * transport. Subscribing is the opt-in: while registered, the transport
@@ -2813,21 +2878,39 @@ function setupFlightDataConsumer(router) {
2813
2878
 
2814
2879
  /**
2815
2880
  * Applies a server function response's integration metadata: `X-Revalidate`
2816
- * keys invalidate, `Location` navigates (hard for absolute urls), flight
2817
- * data seeds the query cache, and matching entries revalidate. Shared by
2818
- * the flight-data consumer and the action response path (which still sees
2819
- * metadata-bearing responses when no flight data was collected).
2881
+ * keys invalidate, the redirect carrier navigates (soft when same-origin,
2882
+ * hard otherwise), flight data seeds the query cache, and matching entries
2883
+ * revalidate. Shared by the flight-data consumer and the action response
2884
+ * path (which still sees metadata-bearing responses when no flight data was
2885
+ * collected).
2820
2886
  */
2821
2887
  function applyResponseMetadata(metadata, navigate, flightData) {
2822
2888
  let keys;
2823
2889
  if (metadata) {
2824
2890
  if (metadata.headers.has(REVALIDATE_HEADER)) keys = metadata.headers.get(REVALIDATE_HEADER).split(",");
2825
- if (metadata.headers.has("Location")) {
2826
- const locationUrl = metadata.headers.get("Location") || "/";
2827
- if (locationUrl.startsWith("http")) {
2828
- window.location.href = locationUrl;
2891
+ // The carrier delivers the target RESOLVED to an absolute url
2892
+ // (solidjs/solid#3102), so the soft/hard split is a real origin
2893
+ // comparison — never a guess from how the author spelled the target,
2894
+ // which sent `redirect("/")` and `redirect(new URL("/", url).href)`
2895
+ // down different navigation paths (solidjs/solid#3107). A redirect
2896
+ // produced locally (a client-side action's `redirect()`) never crossed
2897
+ // the wire, so no carrier was attached: it is the real 3xx with its
2898
+ // Location, resolved against the page it runs in. A `Location` on any
2899
+ // other status is the author's data (a 201's created-at) and never
2900
+ // navigates. Same-origin targets navigate softly under the router;
2901
+ // anything else leaves the app, so the document goes with it.
2902
+ // `replace` matches what HTTP gives a form post: the target takes the
2903
+ // submission's place in history rather than stacking on it.
2904
+ const carried = decodeRedirectHeaderValue(metadata.headers.get(REDIRECT_HEADER));
2905
+ const local = !carried && REDIRECT_STATUSES.has(metadata.status) && metadata.headers.get("Location");
2906
+ const target = carried ? new URL(carried.url) : local ? new URL(local, window.location.href) : undefined;
2907
+ if (target) {
2908
+ if (target.origin === window.location.origin) {
2909
+ navigate(target.pathname + target.search + target.hash, {
2910
+ replace: true
2911
+ });
2829
2912
  } else {
2830
- navigate(locationUrl);
2913
+ window.location.href = target.href;
2831
2914
  }
2832
2915
  }
2833
2916
  }
package/dist/routing.d.ts CHANGED
@@ -216,7 +216,22 @@ export declare function getRouteMatches(branches: Branch[], location: string): R
216
216
  export declare function mergeParams(matches: RouteMatch[]): Params;
217
217
  export declare function registerFlightRouter(router: RouterContext): () => void;
218
218
  export declare function provideFlightConsumer(factory: (router: RouterContext) => () => void): void;
219
- export declare function provideFlashDecoder(decoder: (cookieHeader: string | null) => FlashSubmission | undefined): void;
219
+ /**
220
+ * The flash-cookie codec, provided by the action side (data/action.ts) so
221
+ * the router core never carries it: the core consumes the cookie eagerly
222
+ * per request (detection + one-shot clear via the runtime's isomorphic half)
223
+ * but defers decoding to this slot, read when the submissions signal
224
+ * initializes. Actions are created at module scope, so on the server the
225
+ * decoder is always installed before useSubmission can read — and a
226
+ * router-only app, where it never installs, has no actions that could have
227
+ * produced a flash cookie in the first place.
228
+ *
229
+ * The decoder is async: the flash cookie is encrypted (solidjs/solid#3239),
230
+ * so the runtime's `decodeFlashCookie` decrypts through WebCrypto and the
231
+ * seeding read parks on the not-ready protocol until the decode settles.
232
+ */
233
+ type FlashDecoder = (cookieHeader: string | null) => Promise<FlashSubmission | undefined>;
234
+ export declare function provideFlashDecoder(decoder: FlashDecoder): void;
220
235
  export declare function getIntent(): Intent | undefined;
221
236
  export declare function getInPreloadFn(): boolean;
222
237
  export declare function setInPreloadFn(value: boolean): void;
@@ -226,3 +241,4 @@ export declare function createRouterContext(integration: RouterIntegration, bran
226
241
  transformUrl?: (url: string) => string;
227
242
  }): RouterContext;
228
243
  export declare function createRouteContext(router: RouterContext, parent: RouteContext, outlet: () => JSX.Element, match: () => RouteMatch, matches?: () => RouteMatch[]): RouteContext;
244
+ export {};
package/dist/routing.js CHANGED
@@ -541,16 +541,6 @@ export function provideFlightConsumer(factory) {
541
541
  flightRouters.set(router, factory(router));
542
542
  }
543
543
  }
544
- /**
545
- * The flash-cookie codec, provided by the action side (data/action.ts) so
546
- * the router core never carries it: the core consumes the cookie eagerly
547
- * per request (detection + one-shot clear via the runtime's isomorphic half)
548
- * but defers decoding to this slot, read when the submissions signal
549
- * initializes. Actions are created at module scope, so on the server the
550
- * decoder is always installed before useSubmission can read — and a
551
- * router-only app, where it never installs, has no actions that could have
552
- * produced a flash cookie in the first place.
553
- */
554
544
  let flashDecoder;
555
545
  export function provideFlashDecoder(decoder) {
556
546
  flashDecoder || (flashDecoder = decoder);
@@ -605,6 +595,44 @@ export function createRouterContext(integration, branches, getContext, options =
605
595
  }
606
596
  }
607
597
  }
598
+ // The decode, at most once per request: the decoder may answer with a
599
+ // Promise (the cookie is encrypted; the runtime's decodeFlashCookie is
600
+ // async), and this cache is what keeps the parked read's rerun from
601
+ // restarting it — resumption finds the settled outcome and just reads it.
602
+ // A decoder that rejects reads as "no flash", matching the runtime's own
603
+ // malformed-cookie semantics.
604
+ let flashDecode;
605
+ // The seeding read, as a memo: NotReadyError must surface from a reactive
606
+ // node the graph can park and retry — never from router setup, which no
607
+ // boundary guards — and the memo bounds the recompute to this function;
608
+ // a parked reader resumes into the settled cache above, never a second
609
+ // decode. Created only when a flash cookie actually arrived (server-only
610
+ // by construction: flashCookieHeader is only ever set there), and
611
+ // - `lazy`: server memos compute eagerly by default — deferred to first
612
+ // read, a request whose submissions are never read never decodes;
613
+ // - `transparent`: the memo exists on the server only, so its owner
614
+ // must not consume a hydration-id slot — the client, which seeds
615
+ // submissions as [] without ever creating this memo, would miss it
616
+ // and every sibling id would shift.
617
+ const flashSubmission = flashCookieHeader !== undefined
618
+ ? createMemo(() => {
619
+ if (!flashDecoder)
620
+ return undefined;
621
+ if (!flashDecode) {
622
+ const promise = flashDecoder(flashCookieHeader).then(value => {
623
+ flashDecode = { done: true, value };
624
+ }, () => {
625
+ flashDecode = { done: true, value: undefined };
626
+ });
627
+ flashDecode = { done: false, promise };
628
+ }
629
+ // SSR carries the Promise through NotReadyError so the parked
630
+ // reader can resume, exactly like the lazy matches above.
631
+ if (!flashDecode.done)
632
+ throw new NotReadyError(flashDecode.promise);
633
+ return flashDecode.value;
634
+ }, { lazy: true, transparent: true })
635
+ : undefined;
608
636
  let submissions;
609
637
  // NotReadyError's source must be a reactive async node, not the raw
610
638
  // Promise. Keep one reader per boundary for this router owner so rejection
@@ -843,15 +871,16 @@ export function createRouterContext(integration, branches, getContext, options =
843
871
  // Seeds the initial submission from a no-JS form post: the server
844
872
  // function runtime redirected back with the outcome in a one-shot flash
845
873
  // cookie (its default no-JS convention), consumed eagerly above and
846
- // decoded here — so the post-redirect SSR renders useSubmission() state
847
- // exactly as a scripted submission would. An explicitly pre-seeded
848
- // `event.router.submission` (framework integrations) takes precedence.
874
+ // decoded through the flashSubmission memo — so the post-redirect SSR
875
+ // renders useSubmission() state exactly as a scripted submission would.
876
+ // The memo read may throw NotReadyError while the (encrypted) cookie
877
+ // decodes; the assignment in the submissions getter never completed, so
878
+ // the resumed rerun retries it against the settled decode. An explicitly
879
+ // pre-seeded `event.router.submission` (framework integrations) takes
880
+ // precedence.
849
881
  function initSubmissions() {
850
882
  const e = getRequestEvent();
851
- const submission = (e && e.router && e.router.submission) ||
852
- (flashDecoder && flashCookieHeader !== undefined
853
- ? flashDecoder(flashCookieHeader)
854
- : undefined);
883
+ const submission = (e && e.router && e.router.submission) || (flashSubmission && flashSubmission());
855
884
  if (!submission)
856
885
  return [];
857
886
  return [
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "Ryan Turnquist"
7
7
  ],
8
8
  "license": "MIT",
9
- "version": "2.0.0-next.20",
9
+ "version": "2.0.0-next.22",
10
10
  "homepage": "https://github.com/solidjs/solid-router#readme",
11
11
  "repository": {
12
12
  "type": "git",
@@ -38,21 +38,21 @@
38
38
  "@rollup/plugin-node-resolve": "15.3.0",
39
39
  "@rollup/plugin-terser": "0.4.4",
40
40
  "@solidjs/vite-plugin": "3.0.0-next.35",
41
- "@solidjs/web": "^2.0.0-rc.4",
41
+ "@solidjs/web": "^2.0.0-rc.7",
42
42
  "@types/jest": "^29.5.14",
43
43
  "@types/node": "^22.10.0",
44
44
  "babel-preset-solid": "^2.0.0-rc.2",
45
45
  "jsdom": "^25.0.1",
46
46
  "prettier": "^3.4.1",
47
47
  "rollup": "^4.27.4",
48
- "solid-js": "^2.0.0-rc.4",
48
+ "solid-js": "^2.0.0-rc.7",
49
49
  "typescript": "^5.7.2",
50
50
  "vite": "^8.2.2",
51
51
  "vitest": "^4.1.11"
52
52
  },
53
53
  "peerDependencies": {
54
- "@solidjs/web": "^2.0.0-rc.4",
55
- "solid-js": "^2.0.0-rc.4"
54
+ "@solidjs/web": "^2.0.0-rc.7",
55
+ "solid-js": "^2.0.0-rc.7"
56
56
  },
57
57
  "scripts": {
58
58
  "build": "rm -rf dist && tsc && rollup -c",