Skip to content

Commit 2ccece3

Browse files
docs: re-sync the API reference against solid next and add the until page
- Disposition the exports added since the last sync: until (new reference page under Lifecycle & Actions, folding UntilOptions, Truthy, and TimeoutError), registerFlightDataSource (single-flight page), LiveServerFunction (live), DynamicOptions (dynamic), PreloadLink (renderToStream), and the attribution/observe types (DEV). - Hide the wire-protocol constants and the store-target introspection helpers consumed by the DOM list driver. - Add tone fixups for emphasis capitals in the upstream JSDoc. - Regenerate all 93 reference pages from solid@05725e84. - Stores: add 'fetch in memos, shape in stores' guidance. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 97d0aff commit 2ccece3

23 files changed

Lines changed: 999 additions & 129 deletions

File tree

scripts/extract-solid-ref.mjs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ const CANONICAL_ROUTES = {
109109
affects: ["lifecycle-actions/affects.mdx", "Lifecycle & Actions"],
110110
onSettled: ["lifecycle-actions/on-settled.mdx", "Lifecycle & Actions"],
111111
refresh: ["lifecycle-actions/refresh.mdx", "Lifecycle & Actions"],
112+
until: ["lifecycle-actions/until.mdx", "Lifecycle & Actions"],
112113

113114
children: ["components-context/children.mdx", "Components & Context"],
114115
createContext: [
@@ -315,6 +316,10 @@ const ADVANCED_ROUTES = {
315316
"server-functions/single-flight.mdx",
316317
"Server functions / Integration",
317318
],
319+
registerFlightDataSource: [
320+
"server-functions/single-flight.mdx",
321+
"Server functions / Integration",
322+
],
318323
decodeResponse: [
319324
"server-functions/single-flight.mdx",
320325
"Server functions / Integration",
@@ -368,9 +373,21 @@ const FOLD_INTO = {
368373
DiagnosticCode: "DEV",
369374
DiagnosticEvent: "DEV",
370375
DiagnosticKind: "DEV",
376+
DiagnosticListener: "DEV",
377+
DiagnosticSubject: "DEV",
371378
Diagnostics: "DEV",
372379
DiagnosticSeverity: "DEV",
380+
AttributionHooks: "DEV",
381+
AttributionSlot: "DEV",
382+
InteractionRef: "DEV",
383+
Observe: "DEV",
384+
OBSERVE: "DEV",
373385
DynamicProps: "Dynamic",
386+
DynamicOptions: "dynamic",
387+
Truthy: "until",
388+
UntilOptions: "until",
389+
TimeoutError: "until",
390+
PreloadLink: "renderToStream",
374391
EffectBundle: "createEffect",
375392
EffectFunction: "createEffect",
376393
EffectOptions: "createEffect",
@@ -417,6 +434,7 @@ const FOLD_INTO = {
417434
ServerFunction: "withMeta",
418435
ServerFunctionMetadata: "withMeta",
419436
LiveSource: "live",
437+
LiveServerFunction: "live",
420438
LiveSourceStatus: "live",
421439
InvokeOptions: "invoke",
422440
ServerFunctionInvoker: "invoke",
@@ -550,7 +568,17 @@ const HIDDEN_EXPORTS = new Set([
550568
"GENERIC_SERVER_ERROR_MESSAGE",
551569
"HREF",
552570
"INSTANCE_HEADER",
571+
"NULL_BODY_STATUSES",
572+
"REDIRECT_HEADER",
573+
"RESPONSE_HEADER_VALUE_LIMIT",
553574
"REVALIDATE_HEADER",
575+
"UNKNOWN_HEADER",
576+
"decodeRedirectHeaderValue",
577+
"getFlightDataSourceIds",
578+
// Store-target introspection consumed by the DOM list driver.
579+
"storeHasFamily",
580+
"storeHasOptimisticFamily",
581+
"storeIsShallow",
554582
"RequestContext",
555583
"SAFE_ERROR",
556584
"SERVER_FUNCTION_INVOKE",
@@ -626,6 +654,8 @@ const ENTRY_CALLOUTS = {
626654
};
627655

628656
const ENTRY_SUMMARY_OVERRIDES = {
657+
until:
658+
"Awaits a reactive predicate and resolves the first time it becomes truthy, with the narrowed value. A falsy result or a pending async read means not yet, so the subscription stays live and re-evaluates as sources change. A thrown error, a rejected async source, a timeout, or an abort rejects the promise.",
629659
affects:
630660
"Marks a reactive source or store location as pending while work that will change it is in flight. Marked values remain readable, and derived readers report the pending state until the surrounding action or update settles.",
631661
clientOnly:
@@ -923,6 +953,22 @@ const REFERENCE_FIXUPS = [
923953
"createSignal<T>(fn, options?:",
924954
],
925955
[/the payload just has to be/g, "the payload must be"],
956+
[/reads the AUTHORITATIVE view/g, "reads the authoritative view"],
957+
[/target's NEXT QUIESCENT\s+STATE/g, "target's next settled state"],
958+
[/transaction is STAGED;/g, "transaction is staged;"],
959+
[/IMPORTANT for implementers/g, "Important for implementers"],
960+
[/Fired BEFORE\b/g, "Fired before"],
961+
[/against the DOCUMENT\s+URL/g, "against the document URL"],
962+
[/it is ENTRY-ONLY:/g, "it is entry-only:"],
963+
[/from READING the response/g, "from reading the response"],
964+
[/to EXECUTE from any origin/g, "to execute from any origin"],
965+
[/The DEPLOYMENT SECRET:/g, "The deployment secret:"],
966+
[/the UNBOUND function base/g, "the unbound function base"],
967+
[
968+
/the optimistic store IS the live-fed store/g,
969+
"the optimistic store is the live-fed store",
970+
],
971+
[/This is\s+load-bearing, not a loophole: truth/g, "This is required: truth"],
926972
[/optimistic local edit/g, "temporary local edit"],
927973
[/\(a "transition"\)/g, ""],
928974
[

src/routes/(2)concepts/(1)stores.mdx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,22 @@ Check the box and "Write docs" appears above it; the row for "Review examples" i
163163

164164
See the [`createProjection` reference](/reference/solid-js/stores/create-projection) for mutation and return forms.
165165

166+
### Fetch in memos, shape in stores
167+
168+
A projection function may return a promise, so `createStore(async () => api.rows(period()), [])` fetches and reconciles in one step.
169+
That collapsed form is right when nothing needs to sit between the request and the store.
170+
171+
When something does, keep the two jobs apart: the memo owns the request, the store owns the shape.
172+
173+
```tsx
174+
const rows = createMemo(() => api.rows(period()));
175+
const [table] = createStore(() => rows(), [] as Row[]);
176+
```
177+
178+
`rows` is where you attach request-level concerns: [`isPending(rows)`](/reference/solid-js/reactivity/is-pending) for the refetch indicator, [`refresh(rows)`](/reference/solid-js/lifecycle-actions/refresh) to re-ask, a second consumer that reads the same response.
179+
`table` is where per-row tracking and reconciliation happen; when a new response lands, `rows` changes once and the store diffs it once.
180+
The line between them is the visible marker of where a request-level policy lives, and it is the shape the rest of the docs use when a fetch and a store appear together.
181+
166182
## Optimistic stores
167183

168184
`createOptimisticStore` has the same nested draft update model with a tentative overlay.

src/routes/(2)concepts/(3)async-reactivity.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,7 @@ Use `yield promise` as the suspension point, or place a bare `yield` before writ
762762
- Use [`refresh`](/reference/solid-js/lifecycle-actions/refresh) to rerun a derived source with the same inputs.
763763
- Use [`affects`](/reference/solid-js/lifecycle-actions/affects) to declare which data in-flight work can change.
764764
- Use [`resolve`](/reference/solid-js/advanced/interop-async/resolve) to await one reactive expression outside tracking.
765+
- Use [`until`](/reference/solid-js/lifecycle-actions/until) inside an action to hold it open until a predicate over confirmed state becomes true, such as a live source echoing the write.
765766
- Use [`onSettled`](/reference/solid-js/lifecycle-actions/on-settled) to run code after owned async work and queued updates settle.
766767
- Use `loadingValue` or `seedLoadingValue` when a placeholder value should answer for a source before its first result.
767768

src/routes/reference/(1)solid-js/(1)reactivity/create-effect.mdx

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,6 @@ system if there is none. It is _not_ routed to the bundle's `error` handler.
5555
createEffect<T>(compute, effectFn | { effect, error }, options?: EffectOptions);
5656
```
5757

58-
> Deprecated: `createEffect(compute)` (single argument) is no longer supported.
59-
> Pass a separate effect function as the second argument:
60-
> `createEffect(compute, effect)`. See `MISSING_EFFECT_FN`.
61-
62-
- For a side effect that reacts to changes, split the work:
63-
`createEffect(() => signal(), value => doWork(value))`.
64-
- For a derived value, use `createMemo(() => signal())`.
65-
- For a one-shot side effect at construction time, just call the function.
66-
6758
## Import
6859

6960
```ts
@@ -78,9 +69,6 @@ function createEffect<T>(
7869
effectFn: EffectFunction<NoInfer<T>, T> | EffectBundle<NoInfer<T>, T>,
7970
options?: EffectOptions
8071
): void;
81-
function createEffect<T>(
82-
compute: ComputeFunction<undefined | NoInfer<T>, T>
83-
): never;
8472
```
8573

8674
## Parameters

src/routes/reference/(1)solid-js/(2)stores/create-optimistic-store.mdx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ import { createOptimisticStore } from "solid-js";
3232
```ts
3333
const createOptimisticStore: {
3434
<T extends object = {}>(
35-
store: NoFn<T> | Store<NoFn<T>>
35+
initialValue: NoFn<T> | Store<NoFn<T>>,
36+
options?: StoreOptions
3637
): [get: Store<T>, set: StoreSetter<T>];
3738
<T extends object = {}>(
38-
fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>,
39-
store: NoFn<T> | Store<NoFn<T>>,
39+
fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>,
40+
seed: Partial<T> | Store<NoFn<T>>,
4041
options?: HydrationProjectionOptions
4142
): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
4243
};

src/routes/reference/(1)solid-js/(2)stores/create-projection.mdx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { createProjection } from "solid-js";
3131
```ts
3232
const createProjection: <T extends object = {}>(
3333
fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>,
34-
initialValue: Partial<T> | Store<NoFn<T>>,
34+
seed: Partial<T> | Store<NoFn<T>>,
3535
options?: HydrationProjectionOptions
3636
) => Refreshable<Store<T>>;
3737
```
@@ -40,12 +40,13 @@ const createProjection: <T extends object = {}>(
4040

4141
### `ProjectionOptions`
4242

43-
Options for derived/projected stores created with `createStore(fn)`, `createProjection`, or `createOptimisticStore(fn)`.
43+
Options for derived/projected stores created with
44+
`createStore(fn, seed, options?)`, `createProjection(fn, seed, options?)`,
45+
or `createOptimisticStore(fn, seed, options?)`.
4446

4547
```ts
4648
interface ProjectionOptions extends StoreOptions {
4749
key?: string | ((item: NonNullable<any>) => any) | null;
48-
shallow?: boolean;
4950
seedLoadingValue?: boolean;
5051
}
5152
```
@@ -56,12 +57,6 @@ interface ProjectionOptions extends StoreOptions {
5657

5758
Key property name or function for reconciliation identity; `null` merges positionally
5859

59-
#### `shallow`
60-
61-
- **Type:** `boolean`
62-
63-
Single-layer store: root keys reactive, values raw records replaced by reference
64-
6560
#### `seedLoadingValue`
6661

6762
- **Type:** `boolean`

src/routes/reference/(1)solid-js/(2)stores/create-store.mdx

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ tags:
1010
- "api"
1111
- "v2"
1212
version: "2.0"
13-
description: "Public createStore: plain form `(init, options?)` and derived writable\nform `(fn, seed, options?)`."
13+
description: "Public createStore: plain form `(initialValue, options?)` and derived writable\nform `(fn, seed, options?)`."
1414
source_repo: "solidjs/solid"
1515
source_ref: "next"
1616
source_path: "packages/signals/src/store/index.ts"
1717
---
1818

1919
{/* Generated by scripts/extract-solid-ref.mjs. Edit the source JSDoc or disposition map, then regenerate. */}
2020

21-
Public createStore: plain form `(init, options?)` and derived writable
21+
Public createStore: plain form `(initialValue, options?)` and derived writable
2222
form `(fn, seed, options?)`.
2323

2424
## Import
@@ -31,12 +31,12 @@ import { createStore } from "solid-js";
3131

3232
```ts
3333
function createStore<T extends object = {}>(
34-
store: NoFn<T> | Store<NoFn<T>>,
35-
options?: StoreOptions & { shallow?: boolean }
34+
initialValue: NoFn<T> | Store<NoFn<T>>,
35+
options?: StoreOptions
3636
): [get: Store<T>, set: StoreSetter<T>];
3737
function createStore<T extends object = {}>(
38-
fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>,
39-
store: Partial<T> | Store<NoFn<T>>,
38+
fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>,
39+
seed: Partial<T> | Store<NoFn<T>>,
4040
options?: ProjectionOptions
4141
): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
4242
```
@@ -45,12 +45,13 @@ function createStore<T extends object = {}>(
4545

4646
### `ProjectionOptions`
4747

48-
Options for derived/projected stores created with `createStore(fn)`, `createProjection`, or `createOptimisticStore(fn)`.
48+
Options for derived/projected stores created with
49+
`createStore(fn, seed, options?)`, `createProjection(fn, seed, options?)`,
50+
or `createOptimisticStore(fn, seed, options?)`.
4951

5052
```ts
5153
interface ProjectionOptions extends StoreOptions {
5254
key?: string | ((item: NonNullable<any>) => any) | null;
53-
shallow?: boolean;
5455
seedLoadingValue?: boolean;
5556
}
5657
```
@@ -61,12 +62,6 @@ interface ProjectionOptions extends StoreOptions {
6162

6263
Key property name or function for reconciliation identity; `null` merges positionally
6364

64-
#### `shallow`
65-
66-
- **Type:** `boolean`
67-
68-
Single-layer store: root keys reactive, values raw records replaced by reference
69-
7065
#### `seedLoadingValue`
7166

7267
- **Type:** `boolean`
@@ -109,11 +104,12 @@ type Refreshable<T> = T & { readonly [$REFRESH]: any };
109104

110105
### `StoreOptions`
111106

112-
Base options for store primitives.
107+
Options shared by all store primitives.
113108

114109
```ts
115110
interface StoreOptions {
116111
name?: string;
112+
shallow?: boolean;
117113
}
118114
```
119115

@@ -123,9 +119,15 @@ interface StoreOptions {
123119

124120
Debug name (dev mode only)
125121

122+
#### `shallow`
123+
124+
- **Type:** `boolean`
125+
126+
Single-layer store: root keys reactive, values raw records replaced by reference
127+
126128
### `StoreReturn`
127129

128-
Tuple returned by the plain `createStore(initialValue)` form.
130+
Tuple returned by the plain `createStore(initialValue, options?)` form.
129131

130132
```ts
131133
type StoreReturn<T> = [get: Store<T>, set: StoreSetter<T>];
@@ -144,8 +146,9 @@ A store setter. The callback receives a writable **draft** of the store.
144146

145147
The setter does **not** perform keyed reconciliation. If you need surviving
146148
items to keep their store identity across full-array replacement, use the
147-
projection form — `createStore(fn, seed, { key })` or `createProjection`
148-
whose derive function reconciles its return by `options.key`.
149+
projection form — `createStore(fn, seed, { key })` or
150+
`createProjection(fn, seed, { key })` — whose derive function reconciles
151+
its return by `options.key`.
149152

150153
```ts
151154
type StoreSetter<T> = (fn: (state: T) => T | void) => void;

src/routes/reference/(1)solid-js/(3)lifecycle-actions/refresh.mdx

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,42 @@ tags:
1010
- "api"
1111
- "v2"
1212
version: "2.0"
13-
description: "Invalidates one reactive source, forcing it to re-execute even if its inputs\nhaven't changed."
13+
description: "Invalidates one reactive source, forcing it to re-execute even if its inputs\nhaven't changed, and returns a promise for the target's next settled state — the re-ask (and anything that supersedes it) has settled."
1414
source_repo: "solidjs/solid"
1515
source_ref: "next"
16-
source_path: "packages/signals/src/core/core.ts"
16+
source_path: "packages/signals/src/signals.ts"
1717
---
1818

1919
{/* Generated by scripts/extract-solid-ref.mjs. Edit the source JSDoc or disposition map, then regenerate. */}
2020

2121
Invalidates one reactive source, forcing it to re-execute even if its inputs
22-
haven't changed.
22+
haven't changed, and returns a promise for the target's next settled state — the re-ask (and anything that supersedes it) has settled.
2323

2424
Pass either a Solid-created accessor or a projected store created from
2525
`createStore(fn, ...)` / `createProjection(...)`. `refresh()` is a
2626
write-like invalidation operation: it does not read the target's value, and
27-
refreshing a plain signal accessor is a no-op.
27+
refreshing a plain signal accessor is a no-op that resolves immediately.
2828

29-
Use it to invalidate cached async values (e.g. force a re-fetch) without
30-
tearing the consumer down.
29+
The returned promise is safe to ignore (fire-and-forget refresh is
30+
unchanged, and a failed refetch will not surface an unhandled rejection).
31+
Awaiting it gives imperative flows the settle point without a reactive
32+
read:
33+
34+
- Accessor targets resolve with the settled value; store targets resolve
35+
with the store node passed (reads through it are fresh after the await).
36+
- A failed re-ask rejects with the error (inside an action's generator,
37+
`yield refresh(x)` throws back at the yield point and the action reverts
38+
like any other failure).
39+
- Semantics are quiescence, not flight identity: if another refresh (or
40+
any invalidation) supersedes this one mid-flight, the promise waits for
41+
— and delivers — whatever finally lands.
42+
- Inside an action, truth landing into the held transaction is staged;
43+
the promise still settles then (matching `resolve()`/`until()`, #2930)
44+
and delivers the staged value — the caller's own optimistic override is
45+
never the delivered value.
46+
- The re-ask itself stays verdict-quiet exactly as before: `isPending`
47+
does not flip for a bare refresh (pair with `affects()` for a visible
48+
pending window).
3149

3250
## Import
3351

@@ -38,14 +56,19 @@ import { refresh } from "solid-js";
3856
## Type signature
3957

4058
```ts
41-
function refresh<T>(target: Refreshable<T>): void;
59+
function refresh<T>(
60+
target: Refreshable<T>
61+
): Promise<T extends (...args: any) => infer V ? V : T>;
4262
```
4363

4464
## Examples
4565

4666
```ts
4767
const user = createMemo(async () => fetch(`/users/${id()}`).then(r => r.json()));
4868

49-
// Re-fetch on demand
50-
<button onClick={() => refresh(user)}>Reload</button>
69+
// Fire-and-forget re-fetch
70+
<button onClick={() => refresh(user)}>Reload</button>;
71+
72+
// Imperative settle point
73+
const fresh = await refresh(user);
5174
```

0 commit comments

Comments
 (0)