Skip to content

Commit f4d6982

Browse files
feat(vitrify): add pinia colada plugin
1 parent 8a8b007 commit f4d6982

File tree

10 files changed

+1139
-952
lines changed

10 files changed

+1139
-952
lines changed

.changeset/afraid-peas-drop.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'vitrify': minor
3+
---
4+
5+
feat(vitrify): add pinia colada plugin

packages/create-vitrify/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@
2727
"dependencies": {
2828
"@vitrify/tools": "workspace:*",
2929
"handlebars": "^4.7.8",
30-
"@inquirer/prompts": "^7.5.0",
30+
"@inquirer/prompts": "^7.5.1",
3131
"latest-version": "^9.0.0",
3232
"minimist": "^1.2.8"
3333
},
3434
"devDependencies": {
3535
"@types/minimist": "^1.2.5",
36-
"@types/node": "^22.15.3",
36+
"@types/node": "^22.15.21",
3737
"typescript": "^5.8.3",
38-
"vite": "^6.3.4",
38+
"vite": "^6.3.5",
3939
"vue": "^3.5.13"
4040
},
4141
"files": [

packages/tools/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@
4949
"registry": "https://registry.npmjs.org/"
5050
},
5151
"devDependencies": {
52-
"@types/node": "^22.15.3",
52+
"@types/node": "^22.15.21",
5353
"typescript": "^5.8.3",
54-
"vite": "^6.3.4"
54+
"vite": "^6.3.5"
5555
},
5656
"dependencies": {
5757
"handlebars": "^4.7.8"

packages/vitrify/package.json

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,62 +58,67 @@
5858
"dependencies": {
5959
"@fastify/middie": "^9.0.3",
6060
"@fastify/one-line-logger": "^2.0.2",
61-
"@fastify/static": "^8.1.1",
62-
"@unocss/core": "^66.0.0",
63-
"@unocss/preset-uno": "^66.0.0",
64-
"@unocss/preset-web-fonts": "66.1.0-beta.13",
65-
"@unocss/preset-wind": "^66.0.0",
66-
"@vitejs/plugin-vue": "^5.2.3",
61+
"@fastify/static": "^8.2.0",
62+
"@unocss/core": "^66.1.2",
63+
"@unocss/preset-uno": "^66.1.2",
64+
"@unocss/preset-web-fonts": "66.1.2",
65+
"@unocss/preset-wind": "^66.1.2",
66+
"@vitejs/plugin-vue": "^5.2.4",
6767
"ajv": "^8.17.1",
6868
"animated-unocss": "^0.0.6",
6969
"cac": "^6.7.14",
7070
"chalk": "^5.4.1",
7171
"cross-env": "^7.0.3",
7272
"devalue": "^5.1.1",
73-
"esbuild": "^0.25.3",
74-
"fastify": "^5.3.2",
73+
"esbuild": "^0.25.4",
74+
"fastify": "^5.3.3",
7575
"glob": "^11.0.2",
76-
"happy-dom": "^17.4.6",
76+
"happy-dom": "^17.4.7",
7777
"is-port-reachable": "^4.0.0",
7878
"magic-string": "^0.30.17",
7979
"merge-deep": "^3.0.3",
8080
"readline": "^1.3.0",
8181
"rollup-plugin-visualizer": "^5.14.0",
82+
"sass": "1.89.0",
8283
"stringify-object": "^5.0.0",
8384
"ts-node": "^10.9.2",
84-
"unocss": "^66.0.0",
85+
"unocss": "^66.1.2",
8586
"unplugin-vue-components": "^28.5.0",
86-
"vite": "^6.3.4",
87+
"vite": "^6.3.5",
8788
"vite-plugin-pwa": "^1.0.0",
8889
"vitefu": "^1.0.6",
89-
"vitest": "^3.1.2",
90+
"vitest": "^3.1.4",
9091
"workbox-window": "^7.3.0"
9192
},
9293
"devDependencies": {
9394
"@iconify-json/mdi": "^1.2.3",
94-
"@quasar/extras": "^1.16.17",
95+
"@pinia/colada": "^0.16.1",
96+
"@quasar/extras": "^1.17.0",
9597
"@quasar/quasar-ui-qmarkdown": "^2.0.5",
9698
"@quasar/quasar-ui-qmediaplayer": "^2.0.0-beta.0",
9799
"@types/connect": "^3.4.38",
98100
"@types/glob": "^8.1.0",
99101
"@types/merge-deep": "^3.0.3",
100-
"@types/node": "^22.15.3",
102+
"@types/node": "^22.15.21",
103+
"@types/stringify-object": "^4.0.5",
101104
"@types/ws": "^8.18.1",
102-
"@unocss/preset-icons": "^66.0.0",
103-
"@vue/runtime-core": "^3.5.13",
104-
"beasties": "^0.3.3",
105+
"@unocss/preset-icons": "^66.1.2",
106+
"@vue/runtime-core": "^3.5.14",
107+
"beasties": "^0.3.4",
105108
"css": "^3.0.0",
106109
"css-to-tailwind-translator": "^1.2.8",
107110
"pinia": "^3.0.2",
108111
"quasar": "^2.18.1",
109-
"rollup": "^4.40.1",
112+
"rollup": "^4.41.0",
110113
"typescript": "^5.8.3",
111114
"vue": "^3.5.13",
112115
"vue-router": "^4.5.1"
113116
},
114117
"peerDependencies": {
115-
"@fastify/static": "^8.1.1",
116-
"fastify": "^5.3.2",
118+
"@fastify/static": "^8.2.0",
119+
"@pinia/colada": "^0.16.1",
120+
"fastify": "^5.3.3",
121+
"pinia": "^3.0.2",
117122
"quasar": "^2.18.1",
118123
"vue": "^3.5.13",
119124
"vue-router": "^4.5.1"

packages/vitrify/src/node/frameworks/vue/fastify-ssr-plugin.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -211,24 +211,40 @@ const renderHtml = async (options: {
211211
app
212212
} = await options.render(options.url, options.manifest, ssrContext)
213213

214-
console.log(ssrContextOnRendered)
215214
if (ssrContextOnRendered?.length) {
216215
for (const ssrFunction of ssrContextOnRendered) {
217-
ssrFunction()
216+
await ssrFunction()
218217
}
219218
}
220219

221220
if (onRendered?.length) {
222221
for (const ssrFunction of onRendered) {
223-
ssrFunction({ app, ssrContext })
222+
await ssrFunction({ app, ssrContext })
224223
}
225224
}
226225

227226
// if (!ssrContext.initialState) ssrContext.initialState = {}
228227
ssrContext.initialState.provide = options.provide
229228

230-
console.log('afterOnRendered')
231-
console.log(ssrContext.initialState)
229+
const ssrContextInitialStateStringified: Record<
230+
keyof SSRContext['initialState'],
231+
string
232+
> = {}
233+
for (const key in ssrContext.initialState) {
234+
if (key === 'provide') {
235+
ssrContextInitialStateStringified[key] = JSON.stringify(
236+
ssrContext.initialState.provide
237+
)
238+
} else if (key === 'piniaColada') {
239+
ssrContextInitialStateStringified[key] = JSON.stringify(
240+
ssrContext.initialState.piniaColada
241+
)
242+
} else {
243+
ssrContextInitialStateStringified[key] = stringify(
244+
ssrContext.initialState[key]
245+
)
246+
}
247+
}
232248

233249
const initialStateScript = `
234250
<script>
@@ -244,7 +260,7 @@ const renderHtml = async (options: {
244260

245261
if (onTemplateRendered?.length) {
246262
for (const ssrFunction of onTemplateRendered) {
247-
html = ssrFunction({ html, ssrContext })
263+
html = await ssrFunction({ html, ssrContext })
248264
}
249265
}
250266

packages/vitrify/src/node/index.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import type {
2727
OnRenderedHook,
2828
OnBootHook,
2929
OnSetupFile,
30-
OnCreateAppHook,
30+
onAppCreatedHook,
3131
OnTemplateRenderedHook
3232
} from './vitrify-config.js'
3333
import type { VitrifyContext } from './bin/run.js'
@@ -64,7 +64,7 @@ const manualChunkNames = [
6464
]
6565

6666
const moduleChunks = {
67-
vue: ['vue', '@vue', 'vue-router'],
67+
vue: ['vue', '@vue', 'vue-router', 'pinia', '@pinia/colada', '@vue/devtools'],
6868
quasar: ['quasar'],
6969
atQuasar: ['@quasar']
7070
}
@@ -282,7 +282,7 @@ export const baseConfig = async ({
282282
let onRenderedHooks: OnRenderedHook[]
283283
let onTemplateRenderedHooks: OnTemplateRenderedHook[]
284284
let onMountedHooks: OnMountedHook[]
285-
let onCreateAppHooks: OnCreateAppHook[]
285+
let onAppCreatedHooks: onAppCreatedHook[]
286286
let onSetupFiles: OnSetupFile[]
287287
let globalCss: string[] = []
288288
let staticImports: StaticImports
@@ -363,7 +363,7 @@ export const baseConfig = async ({
363363
onTemplateRenderedHooks =
364364
config.vitrify?.hooks?.onTemplateRendered || []
365365
onMountedHooks = config.vitrify?.hooks?.onMounted || []
366-
onCreateAppHooks = config.vitrify?.hooks?.onCreateApp || []
366+
onAppCreatedHooks = config.vitrify?.hooks?.onAppCreated || []
367367
onSetupFiles = config?.vitrify?.hooks?.onSetup || []
368368
globalCss = config.vitrify?.globalCss || []
369369
staticImports = config.vitrify?.staticImports || {}
@@ -404,7 +404,7 @@ export const baseConfig = async ({
404404
export const onTemplateRendered = [${onTemplateRenderedHooks
405405
.map((fn) => `${String(fn)}`)
406406
.join(', ')}]
407-
export const onCreateApp = [${onCreateAppHooks
407+
export const onAppCreated = [${onAppCreatedHooks
408408
.map((fn) => `${String(fn)}`)
409409
.join(', ')}]
410410
export const onSetup = []

packages/vitrify/src/node/plugins/pinia/index.ts

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,94 @@
1-
import type { OnCreateAppHook, OnRenderedHook } from '../../vitrify-config.js'
2-
import { VitrifyPlugin } from '../index.js'
1+
import type { onAppCreatedHook, OnRenderedHook } from '../../vitrify-config.js'
2+
import type { VitrifyPlugin } from '../index.js'
33

4-
export type PiniaPluginOptions = unknown
4+
export type PiniaPluginOptions = {
5+
// Initialize Pinia Colada
6+
colada?: boolean
7+
}
58

6-
const piniaOnCreateApp: OnCreateAppHook = async ({
9+
const piniaonAppCreated: onAppCreatedHook = async ({
710
app,
11+
ctx,
812
initialState,
913
ssrContext
1014
}) => {
1115
const { createPinia } = await import('pinia')
1216
const pinia = createPinia()
17+
ctx.pinia = pinia
1318
app.use(pinia)
1419

15-
// SSR
20+
// SSR Client
1621
if (initialState?.pinia) pinia.state.value = initialState.pinia
22+
// SSR Server
1723
if (ssrContext) ssrContext.pinia = pinia
1824
}
1925

2026
const piniaOnRenderedHook: OnRenderedHook = ({ app, ssrContext }) => {
21-
// SSR
22-
if (ssrContext?.initialState) {
27+
// SSR Server
28+
if (ssrContext?.initialState && ssrContext.pinia) {
2329
ssrContext.initialState.pinia = ssrContext.pinia.state.value
2430
}
2531
}
2632

33+
const piniaColadaonAppCreated: onAppCreatedHook = async ({
34+
app,
35+
ctx,
36+
initialState
37+
}) => {
38+
if (ctx?.pinia) {
39+
const { PiniaColada, useQueryCache, hydrateQueryCache } = await import(
40+
'@pinia/colada'
41+
)
42+
43+
app.use(PiniaColada)
44+
45+
// SSR Client
46+
if (initialState?.piniaColada) {
47+
hydrateQueryCache(useQueryCache(ctx.pinia), initialState.piniaColada)
48+
}
49+
}
50+
}
51+
52+
const piniaColadaOnRenderedHook: OnRenderedHook = async ({
53+
app,
54+
ssrContext
55+
}) => {
56+
// SSR Server
57+
if (ssrContext?.initialState && ssrContext.pinia) {
58+
const { useQueryCache, serializeQueryCache } = await import('@pinia/colada')
59+
60+
// Delete to prevent Non-POJO error
61+
if (ssrContext.initialState.pinia?._pc_query) {
62+
delete ssrContext.initialState.pinia._pc_query
63+
}
64+
ssrContext.initialState.piniaColada = serializeQueryCache(
65+
useQueryCache(ssrContext.pinia)
66+
)
67+
}
68+
}
69+
2770
export const PiniaPlugin: VitrifyPlugin<PiniaPluginOptions> = async ({
2871
ssr = false,
2972
pwa = false,
30-
options
73+
options = {}
3174
}) => {
75+
const onAppCreated = [piniaonAppCreated]
76+
const onRendered = [piniaOnRenderedHook]
77+
if (options.colada) {
78+
onAppCreated.push(piniaColadaonAppCreated)
79+
onRendered.push(piniaColadaOnRenderedHook)
80+
}
81+
3282
return {
3383
plugins: [],
3484
config: {
3585
vitrify: {
86+
ssr: {
87+
serverModules: ['@pinia/colada']
88+
},
3689
hooks: {
37-
onCreateApp: [piniaOnCreateApp],
38-
onRendered: [piniaOnRenderedHook]
90+
onAppCreated,
91+
onRendered
3992
}
4093
}
4194
}

packages/vitrify/src/node/vitrify-config.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ export type SSRContext = {
2525
}
2626
res: FastifyReply | Record<string, unknown>
2727
provide: Record<string, unknown>
28-
initialState: Record<string, unknown>
28+
initialState: {
29+
provide?: Record<string, unknown>
30+
pinia?: Record<string, unknown>
31+
piniaColada?: Record<string, _UseQueryEntryNodeValueSerialized>
32+
[key: string]: unknown
33+
}
2934
pinia?: Pinia
3035
// Quasar internals
3136
_modules: Set<unknown>

0 commit comments

Comments
 (0)