-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(transfer-state): new library for managing state in an isolated w…
…ay with server to client transfer (#4) * feat(transfer-state): new library for managing state in a n isolated way * feat(transfer-state): add dev toolbar integration to view the transferred state * ci: add validation workflow * ci: fix name of validate action
- Loading branch information
Showing
27 changed files
with
604 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@astro-tools/transfer-state": minor | ||
--- | ||
|
||
Initial version of transfer-state package: a state management integration for having request isolated state transferred from server to client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
name: Validate | ||
|
||
on: | ||
pull_request: | ||
|
||
concurrency: ${{ github.workflow }}-${{ github.ref }} | ||
|
||
jobs: | ||
validate: | ||
name: Release | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout Repo | ||
uses: actions/checkout@v4 | ||
|
||
- name: Setup PNPM | ||
uses: pnpm/action-setup@v4 | ||
|
||
- name: Setup Node.js | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version-file: .nvmrc | ||
cache: 'pnpm' | ||
|
||
- name: Cache turbo build setup | ||
uses: actions/cache@v4 | ||
with: | ||
path: .turbo | ||
key: ${{ runner.os }}-turbo-${{ github.sha }} | ||
restore-keys: | | ||
${{ runner.os }}-turbo- | ||
- name: Install dependencies | ||
run: pnpm install | ||
|
||
- name: Build packages | ||
run: pnpm exec turbo build --filter="./packages/*" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
.../src/content/docs/state-management/_examples/transfer-state/after-hydration/Example.astro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
--- | ||
import { setState } from '@astro-tools:transfer-state'; | ||
import ExampleComponent from './Example.svelte'; | ||
interface Props { | ||
id: string; | ||
} | ||
const { id } = Astro.props; | ||
setState('uuid-after-hydration', 'bed6fb83-0dd9-4566-a675-55052529f18e'); | ||
--- | ||
<button id="after-hydration-trigger">Click me to hydrate!</button> | ||
<hr /> | ||
<ExampleComponent {id} client:on="click #after-hydration-trigger" /> |
21 changes: 21 additions & 0 deletions
21
...src/content/docs/state-management/_examples/transfer-state/after-hydration/Example.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<script lang="ts"> | ||
import { onMount } from 'svelte'; | ||
import { notifyHydration } from '@astro-tools/docs-utils/hydration'; | ||
import { Output } from '@astro-tools/docs-utils/components'; | ||
import { getState } from '@astro-tools:transfer-state'; | ||
export let id: string; | ||
let hydrated = false; | ||
let text = 'Waiting for hydration...'; | ||
onMount(() => { | ||
text = getState('uuid-after-hydration'); | ||
hydrated = true; | ||
notifyHydration(id); | ||
}); | ||
</script> | ||
|
||
<Output hydrated={hydrated} text={text} /> |
16 changes: 16 additions & 0 deletions
16
...src/content/docs/state-management/_examples/transfer-state/before-hydration/Example.astro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
--- | ||
import { setState } from '@astro-tools:transfer-state'; | ||
import ExampleComponent from './Example.svelte'; | ||
interface Props { | ||
id: string; | ||
} | ||
const { id } = Astro.props; | ||
setState('uuid', 'fc379108-c24e-47f5-b119-45db86e0e94a'); | ||
--- | ||
<button id="trigger">Click me to hydrate!</button> | ||
<hr /> | ||
<ExampleComponent {id} client:on="click #trigger" /> |
19 changes: 19 additions & 0 deletions
19
...rc/content/docs/state-management/_examples/transfer-state/before-hydration/Example.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<script lang="ts"> | ||
import { onMount } from 'svelte'; | ||
import { notifyHydration } from '@astro-tools/docs-utils/hydration'; | ||
import { Output } from '@astro-tools/docs-utils/components'; | ||
import { getState } from '@astro-tools:transfer-state'; | ||
export let id: string; | ||
let hydrated = false; | ||
onMount(() => { | ||
hydrated = true; | ||
notifyHydration(id); | ||
}); | ||
</script> | ||
|
||
<Output hydrated={hydrated} text={getState('uuid')} /> |
9 changes: 9 additions & 0 deletions
9
apps/docs/src/content/docs/state-management/_examples/transfer-state/setup.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { defineConfig } from 'astro/config'; | ||
|
||
import { transferState } from '@astro-tools/transfer-state'; | ||
|
||
export default defineConfig({ | ||
integrations: [ | ||
transferState(), | ||
], | ||
}); |
Binary file added
BIN
+21.9 KB
...ntent/docs/state-management/_examples/transfer-state/transfer-state-toolbar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
115 changes: 115 additions & 0 deletions
115
apps/docs/src/content/docs/state-management/transfer-state.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
--- | ||
title: Transfer state | ||
description: State integration isolated by request that is transferred from server to client | ||
sidebar: | ||
badge: | ||
text: Featured | ||
variant: tip | ||
--- | ||
import { Code, Tabs, TabItem, Aside, Steps } from '@astrojs/starlight/components'; | ||
|
||
import { Example, ExamplePreview } from '@astro-tools/docs-utils/example'; | ||
|
||
import TransferStateExample from './_examples/transfer-state/before-hydration/Example.astro'; | ||
import TransferStateAfterHydrationExample from './_examples/transfer-state/after-hydration/Example.astro'; | ||
|
||
import setupExampleRaw from './_examples/transfer-state/setup.ts?raw'; | ||
import transferStateExampleRaw from './_examples/transfer-state/before-hydration/Example.astro?raw'; | ||
import transferStateExampleChildRaw from './_examples/transfer-state/before-hydration/Example.svelte?raw'; | ||
import transferStateAfterHydrationExampleRaw from './_examples/transfer-state/after-hydration/Example.astro?raw'; | ||
import transferStateAfterHydrationExampleChildRaw from './_examples/transfer-state/after-hydration/Example.svelte?raw'; | ||
import outputCodeExample from '@astro-tools/docs-utils/components/Output.svelte?raw'; | ||
|
||
The Transfer state integration allows you to manage the state of your application isolated by request and transferred from the server to the client. | ||
|
||
With this, instead of having to use `Astro.locals` for isolation and pass every value to the UI frameworks through properties or custom scripts, you can use the `setState` and `getState` functions to share the state between Astro and any UI framework component (Svelte, SolidJS, React...). | ||
|
||
<Aside type="caution">Adding this integration will disable stream rendering because the state must be available before executing any client script.</Aside> | ||
|
||
## Setup | ||
|
||
For setting up the state management with request isolation and transfer state, include the integration in your Astro project. | ||
|
||
<Steps> | ||
1. Install the library using your preferred package manager: | ||
``` | ||
npm i -D @astro-tools/transfer-state | ||
``` | ||
2. Add the integration to your project configuration: | ||
<Code title="astro.config.mjs" code={setupExampleRaw} lang="typescript" /> | ||
</Steps> | ||
|
||
## Use | ||
|
||
For using the state management, just use `setState` and `getState` methods: | ||
|
||
### setState | ||
Use `setState` with a key to save the value (JSON-like) into the state. Keys can be removed using `null` as value. | ||
|
||
```typescript | ||
import type { MyData } from './my-data'; | ||
|
||
const myData: MyData = { name: 'example' }; | ||
setState('my-data', myData); | ||
``` | ||
|
||
### getState | ||
Use `getState` to get the current value of a key. When there is no value, `null` will be returned. | ||
|
||
```typescript | ||
import type { MyData } from './my-data'; | ||
|
||
const myData = getState<MyData>('my-data'); | ||
``` | ||
|
||
<Aside type="note">The `setState` and `getState` methods will work in client-side without issues. The state will be loaded from the server-side and then kept in memory.</Aside> | ||
|
||
## Debugging | ||
|
||
This integration adds a new option into the Astro Dev Toolbar which allows to easily check the transferred state from the server to the client. Find the icon highlighed in the image below and click it to toggle the state viewer: | ||
![Transfer State Astro Dev Toolbar integration](./_examples/transfer-state/transfer-state-toolbar.png) | ||
|
||
<Aside type="tip">If you don't want to use the Astro Dev Toolbar, the transferred state from the server to the client can be checked in the DOM tree looking for a `script` tag with id `astro-tools-transfer-state`.</Aside> | ||
|
||
## Examples | ||
|
||
The state can be used to render server-side UI framework components, like the one in this example. | ||
|
||
The `Example.svelte` is rendered in server-side using the `uuid` state and transferred to the client. The hydration process keeps the value is it is. | ||
|
||
<Example> | ||
<Tabs> | ||
<TabItem label="Example.astro"> | ||
<Code code={transferStateExampleRaw} lang="astro" /> | ||
</TabItem> | ||
<TabItem label="Example.svelte"> | ||
<Code code={transferStateExampleChildRaw} lang="astro" /> | ||
</TabItem> | ||
<TabItem label="Output.svelte"> | ||
<Code code={outputCodeExample} lang="svelte" /> | ||
</TabItem> | ||
</Tabs> | ||
<ExamplePreview hydration="example"> | ||
<TransferStateExample id="example" /> | ||
</ExamplePreview> | ||
</Example> | ||
|
||
Also, the state value can be recovered at any moment, for example, after hydration or any logic you want. | ||
|
||
<Example> | ||
<Tabs> | ||
<TabItem label="Example.astro"> | ||
<Code code={transferStateAfterHydrationExampleRaw} lang="astro" /> | ||
</TabItem> | ||
<TabItem label="Example.svelte"> | ||
<Code code={transferStateAfterHydrationExampleChildRaw} lang="astro" /> | ||
</TabItem> | ||
<TabItem label="Output.svelte"> | ||
<Code code={outputCodeExample} lang="svelte" /> | ||
</TabItem> | ||
</Tabs> | ||
<ExamplePreview hydration="example-after-hydration"> | ||
<TransferStateAfterHydrationExample id="example-after-hydration" /> | ||
</ExamplePreview> | ||
</Example> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.output { | ||
color: var(--at-color-hydration-off); | ||
transition: color 200ms ease; | ||
} | ||
|
||
.output--hydrated { | ||
color: var(--at-color-hydration-on); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<script lang="ts"> | ||
export let text: string; | ||
export let hydrated = false; | ||
</script> | ||
|
||
<div class="output" class:output--hydrated={hydrated}>{text}</div> | ||
|
||
<style lang="scss"> | ||
@import '@astro-tools/docs-utils/components/Output.scss'; | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
import Square from './Square.svelte'; | ||
import Output from './Output.svelte'; | ||
|
||
export { | ||
Square, | ||
Output, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
{ | ||
"name": "@astro-tools/transfer-state", | ||
"version": "0.0.0", | ||
"description": "A state management integration for having request isolated state transferred from server to client", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/wishrd/astro-tools", | ||
"directory": "packages/transfer-state" | ||
}, | ||
"homepage": "https://astro-tools.pages.dev", | ||
"keywords": [ | ||
"astro", | ||
"withastro", | ||
"transfer", | ||
"state" | ||
], | ||
"author": { | ||
"name": "wishrd" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"sideEffects": false, | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
} | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"dev": "tsup --watch", | ||
"build": "tsup" | ||
}, | ||
"type": "module", | ||
"peerDependencies": { | ||
"astro": "^4.16.17", | ||
"vite": "^5.4.11" | ||
}, | ||
"dependencies": { | ||
"astro-integration-kit": "^0.17.0", | ||
"@alenaksu/json-viewer": "^2.1.2" | ||
}, | ||
"devDependencies": { | ||
"tsup": "^8.3.5", | ||
"vite": "^5.4.11" | ||
} | ||
} |
Oops, something went wrong.