Compare commits
35 commits
Author | SHA1 | Date | |
---|---|---|---|
c1b24a1d5f | |||
6494a3bbed | |||
08bcc85c93 | |||
62862b560f | |||
4c4730e812 | |||
439248e2e5 | |||
1565eb5a58 | |||
f01a3d8eea | |||
9512de21b5 | |||
b33251008f | |||
5098a15bca | |||
aa994c4793 | |||
![]() |
3600df5279 | ||
![]() |
9107b00a6f | ||
![]() |
6be7424e07 | ||
![]() |
0c636da9c6 | ||
![]() |
5f3f504d35 | ||
![]() |
a4700f1f6a | ||
![]() |
acef5b6ba6 | ||
![]() |
988fc65530 | ||
![]() |
7bc4956f91 | ||
![]() |
17ea41c47b | ||
![]() |
41af5c530b | ||
![]() |
424e9e4494 | ||
![]() |
41e02ccf96 | ||
![]() |
71a0e27c61 | ||
![]() |
632e433add | ||
![]() |
4b29419ed3 | ||
![]() |
e66111e5b9 | ||
![]() |
35e2620939 | ||
![]() |
cc26eb6bb5 | ||
![]() |
1956bee325 | ||
![]() |
08dde913c5 | ||
![]() |
6f86eb4495 | ||
![]() |
94664e8c49 |
10 changed files with 3523 additions and 5884 deletions
11
.build.yml
Normal file
11
.build.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
image: alpine/edge
|
||||
secrets:
|
||||
- bbfcb6dc-7c4a-42ee-a11a-022f0339a133
|
||||
environment:
|
||||
REPO: astro-resume
|
||||
GH_USER: ayoayco
|
||||
tasks:
|
||||
- push-mirror: |
|
||||
cd ~/"${REPO}"
|
||||
git config --global credential.helper store
|
||||
git push --mirror "https://github.com/${GH_USER}/${REPO}"
|
120
README.md
120
README.md
|
@ -1,13 +1,18 @@
|
|||
> [!NOTE]
|
||||
> This project moved to [SourceHut](https://git.sr.ht/~ayoayco/astro-resume).
|
||||
|
||||
# Astro Resume
|
||||
|
||||
[](https://www.npmjs.com/package/@ayco/astro-resume)
|
||||
[](https://www.npmjs.com/package/@ayco/astro-resume)
|
||||
[](https://www.npmjs.com/package/@ayco/astro-resume)
|
||||
|
||||
Utilities for serializing data from server for use in the client.
|
||||
|
||||
1. `Serialize` - Astro component that takes `id` and `data`
|
||||
1. `deserialize(id: string)` - a function for use in the client that takes an `id` string and returns the `data` object
|
||||
1. `deserialize()` - a function for use in the client that takes an `id` string and returns the `data` object
|
||||
|
||||
## Installation & Examples
|
||||
|
||||
### Install via npm
|
||||
## Install via npm
|
||||
|
||||
On your [Astro](https://astro.build) project:
|
||||
|
||||
|
@ -15,7 +20,7 @@ On your [Astro](https://astro.build) project:
|
|||
npm i @ayco/astro-resume
|
||||
```
|
||||
|
||||
### Usage
|
||||
## Usage
|
||||
|
||||
Serializing and deserializing basic primitive data
|
||||
|
||||
|
@ -31,14 +36,14 @@ const data = {
|
|||
<Serialize id="my-data" data={data} />
|
||||
|
||||
<script>
|
||||
import {deserialize} from '@ayco/astro-resume';
|
||||
const data = deserialize('my-data');
|
||||
console.log(data) // {hello: 'world'}
|
||||
import {deserialize} from '@ayco/astro-resume';
|
||||
const data = deserialize('my-data');
|
||||
console.log(data) // {hello: 'world'}
|
||||
</script>
|
||||
|
||||
```
|
||||
|
||||
### Type Safety
|
||||
## Type Safety
|
||||
|
||||
You can define a type for the data and use it in the client script.
|
||||
|
||||
|
@ -57,21 +62,21 @@ export type Data = typeof data;
|
|||
<Serialize id="my-data" data={data} />
|
||||
|
||||
<script>
|
||||
import {deserialize} from '@ayco/astro-resume';
|
||||
import {deserialize} from '@ayco/astro-resume';
|
||||
|
||||
/**
|
||||
* reuse the type in the client
|
||||
* assuming this component's name is `ThisComponent.astro`
|
||||
*/
|
||||
import type {Data} from './ThisComponent.astro';
|
||||
/**
|
||||
* reuse the type in the client
|
||||
* assuming this component's name is `ThisComponent.astro`
|
||||
*/
|
||||
import type {Data} from './ThisComponent.astro';
|
||||
|
||||
const data = deserialize<Data>('my-data');
|
||||
const data = deserialize<Data>('my-data');
|
||||
|
||||
console.log(data) // {hello: 'world', isOkay: true}
|
||||
console.log(data) // {hello: 'world', isOkay: true}
|
||||
</script>
|
||||
```
|
||||
|
||||
### Passing all Astro.props to client
|
||||
## Passing all Astro.props to client
|
||||
|
||||
If you need to make all the component props to the client script:
|
||||
|
||||
|
@ -87,27 +92,69 @@ export interface Props {
|
|||
<Serialize id="preferences" data={{...Astro.props}} />
|
||||
|
||||
<script>
|
||||
import {deserialize} from '@ayco/astro-resume';
|
||||
import type {Props} from './ThisComponent.astro';
|
||||
const {hello, isOkay} = deserialize<Props>('preferences');
|
||||
console.log(hello, isOkay);
|
||||
import {deserialize} from '@ayco/astro-resume';
|
||||
import type {Props} from './ThisComponent.astro';
|
||||
const {hello, isOkay} = deserialize<Props>('preferences');
|
||||
console.log(hello, isOkay);
|
||||
</script>
|
||||
```
|
||||
|
||||
### Using a custom serializer and parser
|
||||
## Serialize server data once, access everywhere
|
||||
|
||||
If you want to opt for more complex data, you can bring your custom serializer/parser.
|
||||
If you have shared data that needs to be initialized from the server and accessed in several places on the client-side, you can use `Serialize` once and `deserialize` in any number of Astro components as long as they are in the same page.
|
||||
|
||||
In this example, an appConfig object is built and serialized in index.astro and accessed in child Astro components.
|
||||
|
||||
In index.astro:
|
||||
```astro
|
||||
import Serialize from "@ayco/astro-resume";
|
||||
|
||||
const appConfig = {
|
||||
someClientSideKey: '1234hello',
|
||||
}
|
||||
export type AppConfig = typeof appConfig;
|
||||
---
|
||||
|
||||
<Serialize id="app-config" data={appConfig} />
|
||||
<Child />
|
||||
```
|
||||
|
||||
In Child.astro:
|
||||
```astro
|
||||
<h1>I'm a child. I have access to the appConfig in index!</h1>
|
||||
<GrandChild />
|
||||
<script>
|
||||
import {deserialize} from '@ayco/astro-resume';
|
||||
import type {AppConfig} from '..pages/index.astro';
|
||||
const data = deserialize<AppConfig>('app-config');
|
||||
|
||||
// ... do something with the app config
|
||||
</script>
|
||||
```
|
||||
|
||||
In GrandChild.astro:
|
||||
```astro
|
||||
<h1>I'm a grand child. I also have access to the appConfig in index!</h1>
|
||||
<script>
|
||||
import {deserialize} from '@ayco/astro-resume';
|
||||
import type {AppConfig} from '..pages/index.astro';
|
||||
const data = deserialize<AppConfig>('app-config');
|
||||
|
||||
// ... do something with the app config
|
||||
</script>
|
||||
```
|
||||
|
||||
## Using a custom serializer and parser
|
||||
|
||||
You can bring your own custom serializer/parser if you want to opt for more complex data handling.
|
||||
|
||||
Here's an example of serializing data that `JSON.stringify` cannot (e.g., Date or BigInt) using Rich Harris' [`devalue`](https://github.com/Rich-Harris/devalue):
|
||||
|
||||
```astro
|
||||
---
|
||||
import {stringify} from 'devalue';
|
||||
import Serialize from "../Serialize.astro";
|
||||
import Serialize from "@ayco/astro-resume";
|
||||
const data = {
|
||||
name: 'John Doe',
|
||||
isOkay: true,
|
||||
mood: null,
|
||||
now: new Date(),
|
||||
age: BigInt('3218378192378')
|
||||
}
|
||||
|
@ -117,20 +164,20 @@ export type Data = typeof data;
|
|||
<Serialize data={data} id="my-data" use={stringify} />
|
||||
|
||||
<script>
|
||||
import { parse } from 'devalue';
|
||||
import { deserialize } from '../deserialize';
|
||||
import type { Data } from './index.astro';
|
||||
import {parse} from 'devalue';
|
||||
import {deserialize} from '@ayco/astro-resume';
|
||||
import type {Data} from './index.astro';
|
||||
|
||||
const data = deserialize<Data>('my-data', parse);
|
||||
console.log(typeof data.age); // 'bigint'
|
||||
console.log(data.now instanceof Date); // true
|
||||
const {age, now} = deserialize<Data>('my-data', parse);
|
||||
console.log(typeof age); // 'bigint'
|
||||
console.log(now instanceof Date); // true
|
||||
</script>
|
||||
```
|
||||
|
||||
### Errors & Warning in `deserialize()`
|
||||
## Errors & Warning in `deserialize()`
|
||||
|
||||
The `deserialize()` function may give you the following:
|
||||
1. **ERR: No match found** - there are no `JSON` scripts with the given ID
|
||||
1. **ERR: No match found** - there are no `JSON` scripts with the given ID
|
||||
1. **WARNING: Multiple matches for <id>** - there were multiple `JSON` scripts found with the same ID
|
||||
|
||||
## About
|
||||
|
@ -158,4 +205,3 @@ See the [TODO tracker](https://todo.sr.ht/~ayoayco/astro-resume) for planned wor
|
|||
## Reporting Issues
|
||||
|
||||
To report issues or request features, send a plain text email to [~ayoayco/astro-resume@todo.sr.ht](mailto:~ayoayco/astro-resume@todo.sr.ht) or file a ticket via [SourceHut](https://todo.sr.ht/~ayoayco/astro-resume)
|
||||
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
|
||||
import node from "@astrojs/node";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
output: "server",
|
||||
adapter: node({
|
||||
mode: "standalone"
|
||||
})
|
||||
});
|
5794
package-lock.json
generated
5794
package-lock.json
generated
File diff suppressed because it is too large
Load diff
21
package.json
21
package.json
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"name": "@ayco/astro-resume",
|
||||
"author": "Ayo Ayco",
|
||||
"homepage": "https://sr.ht/~ayoayco/astro-resume",
|
||||
"homepage": "https://ayco.io/sh/astro-resume",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.sr.ht/~ayoayco/astro-resume"
|
||||
},
|
||||
"type": "module",
|
||||
"version": "0.3.1",
|
||||
"version": "0.4.3",
|
||||
"keywords": [
|
||||
"astro-component",
|
||||
"css",
|
||||
|
@ -23,11 +27,14 @@
|
|||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
"astro": "astro",
|
||||
"publish:patch": "npm version patch && npm publish --access public",
|
||||
"publish:minor": "npm version minor && npm publish --access public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^5.3.0",
|
||||
"astro": "^2.8.4",
|
||||
"devalue": "^4.3.2"
|
||||
"devDependencies": {
|
||||
"devalue": "^5.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "^5"
|
||||
}
|
||||
}
|
||||
|
|
3370
pnpm-lock.yaml
Normal file
3370
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
|
@ -21,7 +21,15 @@ let serializedData = '{}'
|
|||
try {
|
||||
serializedData = use ? use(data) : JSON.stringify(data);
|
||||
} catch(err) {
|
||||
throw Error(err)
|
||||
/**
|
||||
* ERR: data is unserializable
|
||||
* - You might need a custom serializer/parser for complex data
|
||||
* - Usage examples in 👉 https://git.sr.ht/~ayoayco/astro-resume#astro-resume
|
||||
*/
|
||||
throw Error(`astro-resume ERR: Data unserializable
|
||||
- You might need a custom serializer/parser for complex data
|
||||
- Usage examples in 👉 https://git.sr.ht/~ayoayco/astro-resume#astro-resume
|
||||
`, err)
|
||||
}
|
||||
---
|
||||
|
||||
|
|
|
@ -4,35 +4,13 @@
|
|||
* @param parser Custom parser to be used
|
||||
* @returns The deserialized JSON data
|
||||
* @see Usage examples in 👉 https://git.sr.ht/~ayoayco/astro-resume#astro-resume
|
||||
* @example
|
||||
*
|
||||
* To make all `Astro.props` available in your client script:
|
||||
*
|
||||
* ```astro
|
||||
* ---
|
||||
* import Serialize from "@ayco/astro-resume";
|
||||
* export interface Props {
|
||||
* hello: string;
|
||||
* isOkay: boolean;
|
||||
* }
|
||||
* ---
|
||||
*
|
||||
* <Serialize id="preferences" data={{...Astro.props}} />
|
||||
*
|
||||
* <script>
|
||||
* import {deserialize} from '@ayco/astro-resume';
|
||||
* import type {Props} from './ThisComponent.astro';
|
||||
* const {hello, isOkay} = deserialize<Props>('preferences');
|
||||
* console.log(hello, isOkay);
|
||||
* </script>
|
||||
* ```
|
||||
**/
|
||||
**/
|
||||
export function deserialize<T = any>(id: string, parser?: (serialized: string)=>any): T {
|
||||
const elements = document.querySelectorAll<HTMLScriptElement>(`script#${id}[type="application/json"]`);
|
||||
|
||||
if (elements?.length > 0) {
|
||||
if (elements?.length > 1)
|
||||
console.warn(`WARNING: Multiple matches for "${id}". There are ${elements?.length} matches found for ID: "${id}". The function will parse the first match found.`)
|
||||
console.warn(`astro-resume WARN: Multiple matches for "${id}". The function will parse the first one.`)
|
||||
|
||||
const element = elements[0];
|
||||
|
||||
|
@ -42,7 +20,7 @@ export function deserialize<T = any>(id: string, parser?: (serialized: string)=>
|
|||
: JSON.parse(element.textContent)
|
||||
}
|
||||
|
||||
throw Error(`ERR: No match found.
|
||||
throw Error(`astro-resume ERR: No match found.
|
||||
"deserialize('${id}')" did not find any data.
|
||||
Check that the following are correct:
|
||||
- The Serialize component is used with correct props
|
||||
|
|
1
src/env.d.ts
vendored
1
src/env.d.ts
vendored
|
@ -1 +1,2 @@
|
|||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
import { stringify } from 'devalue';
|
||||
import Serialize from "../Serialize.astro";
|
||||
import { stringify } from "devalue";
|
||||
const data = {
|
||||
name: 'John Doe',
|
||||
isOkay: true,
|
||||
mood: null,
|
||||
now: new Date(),
|
||||
age: BigInt('3218378192378')
|
||||
}
|
||||
nameStr: "John Doe",
|
||||
isOkayBool: true,
|
||||
moodNull: null,
|
||||
nowDate: new Date(),
|
||||
ageBigInt: BigInt("3218378192378"),
|
||||
};
|
||||
export type Data = typeof data;
|
||||
---
|
||||
|
||||
|
@ -15,13 +15,30 @@ export type Data = typeof data;
|
|||
<Serialize data={data} id="my-data" use={stringify} />
|
||||
|
||||
<script>
|
||||
import { deserialize } from '../deserialize';
|
||||
import { parse, stringify } from 'devalue';
|
||||
import type { Data } from './index.astro';
|
||||
import { deserialize } from "../deserialize";
|
||||
import { parse } from "devalue";
|
||||
import type { Data } from "./index.astro";
|
||||
|
||||
const data = deserialize<Data>('my-data', parse);
|
||||
console.log(data);
|
||||
console.log(typeof data.age);
|
||||
console.log(data.now instanceof Date);
|
||||
document.getElementById("render-here").innerHTML = stringify(data)
|
||||
const data = deserialize<Data>("my-data", parse);
|
||||
console.log(data);
|
||||
|
||||
Object.keys(data).forEach((key) =>
|
||||
console.log(key, data[key], typeof data[key])
|
||||
);
|
||||
|
||||
// render table to render-here
|
||||
const table = document.createElement("table");
|
||||
const tbody = document.createElement("tbody");
|
||||
table.appendChild(tbody);
|
||||
Object.keys(data).forEach((key) => {
|
||||
const tr = document.createElement("tr");
|
||||
const tdKey = document.createElement("td");
|
||||
const tdValue = document.createElement("td");
|
||||
tdKey.textContent = key;
|
||||
tdValue.textContent = data[key];
|
||||
tr.appendChild(tdKey);
|
||||
tr.appendChild(tdValue);
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
document.getElementById("render-here").appendChild(table);
|
||||
</script>
|
||||
|
|
Loading…
Reference in a new issue