diff --git a/packages/fastify-dx-solid/package.json b/packages/fastify-dx-solid/package.json index 273b087..2ecece0 100644 --- a/packages/fastify-dx-solid/package.json +++ b/packages/fastify-dx-solid/package.json @@ -5,15 +5,19 @@ "type": "module", "main": "index.js", "name": "fastify-dx-solid", - "version": "0.0.3", + "version": "0.0.4", "files": [ "virtual/create.jsx", + "virtual/create.tsx", "virtual/root.jsx", + "virtual/root.tsx", "virtual/route.jsx", "virtual/layouts.js", "virtual/layouts/default.jsx", "virtual/context.js", + "virtual/context.ts", "virtual/mount.js", + "virtual/mount.ts", "virtual/core.js", "virtual/routes.js", "index.js", diff --git a/packages/fastify-dx-solid/plugin.cjs b/packages/fastify-dx-solid/plugin.cjs index e39fdf8..9d01124 100644 --- a/packages/fastify-dx-solid/plugin.cjs +++ b/packages/fastify-dx-solid/plugin.cjs @@ -5,19 +5,23 @@ const { fileURLToPath } = require('url') function viteSolidFastifyDX (config = {}) { const prefix = /^\/?dx:/ const routing = Object.assign({ - globPattern: '/pages/**/*.jsx', + globPattern: '/pages/**/*.(jsx|tsx)', paramPattern: /\[(\w+)\]/, }, config) const virtualRoot = resolve(__dirname, 'virtual') const virtualModules = [ 'mount.js', + 'mount.ts', 'resource.js', 'routes.js', 'layouts.js', 'create.jsx', + 'create.tsx', 'root.jsx', + 'root.tsx', 'layouts/', 'context.js', + 'context.ts', 'route.jsx', 'core.js' ] diff --git a/packages/fastify-dx-solid/virtual/context.ts b/packages/fastify-dx-solid/virtual/context.ts new file mode 100644 index 0000000..1e605f5 --- /dev/null +++ b/packages/fastify-dx-solid/virtual/context.ts @@ -0,0 +1,4 @@ +// This file serves as a placeholder +// if no context.js file is provided + +export default () => {} diff --git a/packages/fastify-dx-solid/virtual/create.tsx b/packages/fastify-dx-solid/virtual/create.tsx new file mode 100644 index 0000000..da7abca --- /dev/null +++ b/packages/fastify-dx-solid/virtual/create.tsx @@ -0,0 +1,5 @@ +import Root from '/dx:root.tsx' + +export default function create ({ url, payload }) { + return () => +} diff --git a/packages/fastify-dx-solid/virtual/layouts.js b/packages/fastify-dx-solid/virtual/layouts.js index c1ede64..4253690 100644 --- a/packages/fastify-dx-solid/virtual/layouts.js +++ b/packages/fastify-dx-solid/virtual/layouts.js @@ -1,8 +1,10 @@ import DefaultLayout from '/dx:layouts/default.jsx' -const appLayouts = import.meta.globEager('/layouts/*.jsx') +const appLayouts = import.meta.globEager('/layouts/*.(jsx|tsx)') -appLayouts['/layouts/default.jsx'] ??= DefaultLayout +if (!appLayouts['/layouts/default.jsx'] && !appLayouts['/layouts/default.tsx']) { + appLayouts['/layouts/default.jsx'] = DefaultLayout +} export default Object.fromEntries( Object.keys(appLayouts).map((path) => { diff --git a/packages/fastify-dx-solid/virtual/layouts/default.jsx b/packages/fastify-dx-solid/virtual/layouts/default.jsx index aa43ed5..37c12f2 100644 --- a/packages/fastify-dx-solid/virtual/layouts/default.jsx +++ b/packages/fastify-dx-solid/virtual/layouts/default.jsx @@ -1,8 +1,5 @@ -import { children } from 'solid-js' - export default function Default (props) { - const c = children(() => props.children) return ( -
{c()}
+
{props.children}
) } diff --git a/packages/fastify-dx-solid/virtual/mount.ts b/packages/fastify-dx-solid/virtual/mount.ts new file mode 100644 index 0000000..a16a5f7 --- /dev/null +++ b/packages/fastify-dx-solid/virtual/mount.ts @@ -0,0 +1,48 @@ +import Head from 'unihead/client' +import { render, hydrate } from 'solid-js/web' + +import create from '/dx:create.tsx' +import routesPromise from '/dx:routes.js' + +mount('main') + +async function mount (target) { + if (typeof target === 'string') { + target = document.querySelector(target) + } + const context = await import('/dx:context.js') + const serverRoute = await extendContext(window.route, context) + const head = new Head(window.route.head, window.document) + const resolvedRoutes = await routesPromise + const routeMap = Object.fromEntries( + resolvedRoutes.map((route) => [route.path, route]), + ) + const app = create({ + payload: { + head, + serverRoute, + routes: window.routes, + routeMap, + }, + }) + if (serverRoute.clientOnly) { + render(() => app, target) + } else { + hydrate(() => app, target) + } +} + +async function extendContext (ctx, { + // The route context initialization function + default: setter, + // We destructure state here just to discard it from extra + state, + // Other named exports from context.js + ...extra +}) { + Object.assign(ctx, extra) + if (setter) { + await setter(ctx) + } + return ctx +} diff --git a/packages/fastify-dx-solid/virtual/root.tsx b/packages/fastify-dx-solid/virtual/root.tsx new file mode 100644 index 0000000..a3662b7 --- /dev/null +++ b/packages/fastify-dx-solid/virtual/root.tsx @@ -0,0 +1,28 @@ +import { createMutable } from 'solid-js/store' +import { Router, Routes, Route } from 'solid-app-router' +import DXRoute from '/dx:route.jsx' +import { isServer } from '/dx:core.js' + +export default function Root (props) { + // eslint-disable-next-line solid/reactivity + props.payload.serverRoute.state = isServer + ? props.payload.serverRoute.state + : createMutable(props.payload.serverRoute.state) + // This is so we can serialize state into the hydration payload after SSR is done + return ( + + { + // eslint-disable-next-line solid/prefer-for + props.payload.routes.map(route => + + } />, + ) + } + + ) +} diff --git a/starters/solid-ts/.eslintignore b/starters/solid-ts/.eslintignore new file mode 100644 index 0000000..53c37a1 --- /dev/null +++ b/starters/solid-ts/.eslintignore @@ -0,0 +1 @@ +dist \ No newline at end of file diff --git a/starters/solid-ts/.eslintrc b/starters/solid-ts/.eslintrc new file mode 100644 index 0000000..fd2f9a2 --- /dev/null +++ b/starters/solid-ts/.eslintrc @@ -0,0 +1,19 @@ +{ + parser: '@typescript-eslint/parser', + plugins: ['solid'], + extends: [ + 'eslint:recommended', + 'standard-with-typescript', + 'plugin:solid/typescript' + ], + parserOptions: { + project: './tsconfig.json' + }, + rules: { + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/strict-boolean-expressions': 'off', + 'solid/reactivity': 'off', + 'comma-dangle': ['error', 'always-multiline'], + 'import/no-absolute-path': 'off', + }, +} diff --git a/starters/solid-ts/client/assets/logo.svg b/starters/solid-ts/client/assets/logo.svg new file mode 100644 index 0000000..9f2f2fd --- /dev/null +++ b/starters/solid-ts/client/assets/logo.svg @@ -0,0 +1,84 @@ + +image/svg+xml + + + + + + + + + + + + + + + + diff --git a/starters/solid-ts/client/base.css b/starters/solid-ts/client/base.css new file mode 100644 index 0000000..fde0cfc --- /dev/null +++ b/starters/solid-ts/client/base.css @@ -0,0 +1,56 @@ +:root { + --color-base: #f1f1f1; + --color-highlight: #ff80ff; +} +html { + background: #222; +} +main { + width: 800px; + margin: 0 auto; + padding: 2em; + box-shadow: 5px 5px 30px rgba(0,0,0,0.4); + border-radius: 10px; + background-color: rgba(255, 255, 255, 0.1); + font-family: Avenir, Helvetica, Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: var(--color-base); + margin-top: 60px; + & a { + color: var(--color-highlight); + text-decoration: none; + font-weight: bold; + border-bottom: 1px solid var(--color-highlight); + &:hover { + color: #ffde00; + } + &:active { + color: #eecf00 + } + } + & p { + font-size: 1.2em; + } + & ul { + & li { + &:not(:last-child) { + margin-bottom: 0.5em; + } + break-inside: avoid; + font-size: 1em; + } + } + & code { + color: #ffde00; + font-weight: bold; + font-family: 'Consolas', 'Andale Mono', monospace; + font-size: 0.9em; + } + & img { + width: 14em; + } + & button { + margin: 0 0.5em; + } +} diff --git a/starters/solid-ts/client/context.ts b/starters/solid-ts/client/context.ts new file mode 100644 index 0000000..50c1262 --- /dev/null +++ b/starters/solid-ts/client/context.ts @@ -0,0 +1,57 @@ +import ky from 'ky-universal' + +interface User { + authenticated: boolean | null +} + +interface State { + message: string | null + user: User | null + todoList: string[] | null +} + +// This will eventually be provided by fastify-dx's core package +interface RouteContext { + server?: any + req?: any + reply?: any + actions: object + data: any + state: State +} + +export default (ctx: RouteContext): void => { + if (ctx.server) { + ctx.state.todoList = ctx.server.db.todoList + } +} + +export const $fetch = ky.extend({ + prefixUrl: 'http://localhost:3000', +}) + +export const state = (): State => ({ + message: null, + user: { + authenticated: false, + }, + todoList: null, +}) + +export const actions = { + authenticate (state: State) { + state.user.authenticated = true + }, + async addTodoItem (state: State, item) { + await $fetch.put('api/todo/items', { + json: { item }, + }) + state.todoList.push(item) + }, + async removeTodoItem (state: State, index) { + await $fetch.delete('api/todo/items', { + json: { index }, + }) + state.todoList.splice(index, 1) + }, +} diff --git a/starters/solid-ts/client/index.html b/starters/solid-ts/client/index.html new file mode 100644 index 0000000..4dfd5cc --- /dev/null +++ b/starters/solid-ts/client/index.html @@ -0,0 +1,14 @@ + + + + + + + + + +
+ + + + diff --git a/starters/solid-ts/client/index.ts b/starters/solid-ts/client/index.ts new file mode 100644 index 0000000..c63c141 --- /dev/null +++ b/starters/solid-ts/client/index.ts @@ -0,0 +1,18 @@ +// SSR functions from Solid +import { renderToStream, renderToString } from 'solid-js/web' + +import create from '/dx:create.tsx' +import routes from '/dx:routes.js' +import * as context from '/dx:context.ts' + +export default { + // Solid requires SSR functions to be imported + // from the same module environment where all + // application-level code runs + renderToStream, + renderToString, + // Exports required by Fastify DX itself + create, + routes, + context, +} diff --git a/starters/solid-ts/client/layouts/auth.jsx b/starters/solid-ts/client/layouts/auth.jsx new file mode 100644 index 0000000..acfd092 --- /dev/null +++ b/starters/solid-ts/client/layouts/auth.jsx @@ -0,0 +1,26 @@ +import { children } from 'solid-js' +import { useRouteContext } from '/dx:core.js' + +export default function Auth (props) { + const c = children(() => props.children) + const { actions, state } = useRouteContext() + const authenticate = () => actions.authenticate(state) + return ( +
+ {state.user.authenticated + ? c() + : authenticate()} /> } +
+ ) +} + +function Login (props) { + return ( + <> +

This route needs authentication.

+ + + ) +} \ No newline at end of file diff --git a/starters/solid-ts/client/layouts/default.jsx b/starters/solid-ts/client/layouts/default.jsx new file mode 100644 index 0000000..aa43ed5 --- /dev/null +++ b/starters/solid-ts/client/layouts/default.jsx @@ -0,0 +1,8 @@ +import { children } from 'solid-js' + +export default function Default (props) { + const c = children(() => props.children) + return ( +
{c()}
+ ) +} diff --git a/starters/solid-ts/client/pages/client-only.jsx b/starters/solid-ts/client/pages/client-only.jsx new file mode 100644 index 0000000..ba7e86a --- /dev/null +++ b/starters/solid-ts/client/pages/client-only.jsx @@ -0,0 +1,23 @@ +import { Link } from 'solid-app-router' + +export const clientOnly = true + +export function getMeta () { + return { + title: 'Client Only Page' + } +} + +export default function ClientOnly () { + return ( + <> +

This route is rendered on the client only!

+

+ Go back to the index +

+

+

When this route is rendered on the server, no SSR takes place.

+

See the output of curl http://localhost:3000/client-only.

+ + ) +} diff --git a/starters/solid-ts/client/pages/index.jsx b/starters/solid-ts/client/pages/index.jsx new file mode 100644 index 0000000..447cbbf --- /dev/null +++ b/starters/solid-ts/client/pages/index.jsx @@ -0,0 +1,38 @@ +import logo from '/assets/logo.svg' +import { Link } from 'solid-app-router' +import { isServer, useRouteContext } from '/dx:core.js' + +export function getMeta () { + return { + title: 'Welcome to Fastify DX!' + } +} + +export default function Index () { + const { state } = useRouteContext() + if (isServer) { + // State is automatically hydrated on the client + state.message = 'Welcome to Fastify DX for Solid!' + } + return ( + <> + Fastify DX +

{state.message}

+ + + ) +} diff --git a/starters/solid-ts/client/pages/server-only.jsx b/starters/solid-ts/client/pages/server-only.jsx new file mode 100644 index 0000000..7f33f09 --- /dev/null +++ b/starters/solid-ts/client/pages/server-only.jsx @@ -0,0 +1,23 @@ +import { Link } from 'solid-app-router' + +export const serverOnly = true + +export function getMeta () { + return { + title: 'Server Only Page' + } +} + +export default function ServerOnly () { + return ( + <> +

This route is rendered on the server only!

+

+ Go back to the index +

+

+

When this route is rendered on the server, no JavaScript is sent to the client.

+

See the output of curl http://localhost:3000/server-only.

+ + ) +} diff --git a/starters/solid-ts/client/pages/streaming.jsx b/starters/solid-ts/client/pages/streaming.jsx new file mode 100644 index 0000000..ebe1061 --- /dev/null +++ b/starters/solid-ts/client/pages/streaming.jsx @@ -0,0 +1,38 @@ +import { createResource } from 'solid-js' +import { useRouteContext } from '/dx:core.js' + +export const streaming = true + +export default function Streaming () { + const {state} = useRouteContext() + const [message] = createResource(async () => { + if (state.delayedMessage) { + return state.delayedMessage + } + const message = await afterSeconds({ + message: 'Delayed by Resource API', + seconds: 5, + }) + state.delayedMessage = message + return message + }) + return ( + Waiting for content

}> + +
+ ) +} + +function Message (props) { + return ( +

{props.message}

+ ) +} + +function afterSeconds ({ message, seconds }) { + return new Promise((resolve) => { + setTimeout(() => { + resolve(message) + }, seconds * 1000) + }) +} diff --git a/starters/solid-ts/client/pages/using-auth.jsx b/starters/solid-ts/client/pages/using-auth.jsx new file mode 100644 index 0000000..a54f521 --- /dev/null +++ b/starters/solid-ts/client/pages/using-auth.jsx @@ -0,0 +1,37 @@ +import { Link } from 'solid-app-router' +import { useRouteContext } from '/dx:core.js' + +export const layout = 'auth' + +export function getMeta () { + return { title: 'Todo List — Using Custom Layout' } +} + +export default function UsingCustomLayout (props) { + let input + const {state, actions} = useRouteContext() + const addItem = (value) => { + actions.addTodoItem(state, value) + input.value = '' + } + return ( + <> +

Todo List — Using Custom Layout

+ +
+ + +
+

+ Go back to the index +

+

+

When you navigate away from this route, any additions to the to-do + list are not lost, because they're bound to the global application state.

+ + ) +} diff --git a/starters/solid-ts/client/pages/using-data.jsx b/starters/solid-ts/client/pages/using-data.jsx new file mode 100644 index 0000000..2c40efa --- /dev/null +++ b/starters/solid-ts/client/pages/using-data.jsx @@ -0,0 +1,46 @@ +import { createSignal } from 'solid-js' +import { Link } from 'solid-app-router' +import { useRouteContext } from '/dx:core.js' + +export function getMeta () { + return { title: 'Todo List — Using Data' } +} + +export function getData ({ server }) { + return { + todoList: server.db.todoList + } +} + +export default function UsingData (props) { + let input + const {data} = useRouteContext() + const [todoList, updateTodoList] = createSignal(data.todoList) + const addItem = (value) => { + updateTodoList(list => [...list, value]) + input.value = '' + } + return ( + <> +

Todo List — Using Data

+ +
+ + +
+

+ Go back to the index +

+

+

When you navigate away from this route, any additions to the to-do + list will be lost, because they're bound to this route component only.

+

See the /using-store example to learn + how to use the application global state for it. +

+ + ) +} diff --git a/starters/solid-ts/client/pages/using-store.jsx b/starters/solid-ts/client/pages/using-store.jsx new file mode 100644 index 0000000..3555a29 --- /dev/null +++ b/starters/solid-ts/client/pages/using-store.jsx @@ -0,0 +1,35 @@ +import { Link } from 'solid-app-router' +import { useRouteContext } from '/dx:core.js' + +export function getMeta () { + return { title: 'Todo List — Using Store' } +} + +export default function UsingStore (props) { + let input + const {state, actions} = useRouteContext() + const addItem = (value) => { + actions.addTodoItem(state, value) + input.value = '' + } + return ( + <> +

Todo List — Using Store

+ +
+ + +
+

+ Go back to the index +

+

+

When you navigate away from this route, any additions to the to-do + list are not lost, because they're bound to the global application state.

+ + ) +} diff --git a/starters/solid-ts/client/root.tsx b/starters/solid-ts/client/root.tsx new file mode 100644 index 0000000..28459b5 --- /dev/null +++ b/starters/solid-ts/client/root.tsx @@ -0,0 +1,29 @@ +import 'uno.css' +import { createMutable } from 'solid-js/store' +import { Router, Routes, Route } from 'solid-app-router' +import DXRoute from '/dx:route.jsx' +import { isServer } from '/dx:core.js' + +export default function Root (props) { + // eslint-disable-next-line solid/reactivity + props.payload.serverRoute.state = isServer + ? props.payload.serverRoute.state + : createMutable(props.payload.serverRoute.state) + // This is so we can serialize state into the hydration payload after SSR is done + return ( + + { + // eslint-disable-next-line solid/prefer-for + props.payload.routes.map(route => + + } />, + ) + } + + ) +} diff --git a/starters/solid-ts/package.json b/starters/solid-ts/package.json new file mode 100644 index 0000000..e9c240f --- /dev/null +++ b/starters/solid-ts/package.json @@ -0,0 +1,45 @@ +{ + "type": "module", + "scripts": { + "dev": "tsx server.ts --dev", + "build": "npm run build:client && npm run build:server", + "serve": "tsx server.ts", + "devinstall": "zx ../../devinstall.mjs -- tsx server.ts --dev", + "build:client": "vite build --outDir dist/client --ssrManifest", + "build:server": "vite build --outDir dist/server --ssr /index.ts", + "lint": "eslint . --ext .ts,.tsx --fix" + }, + "dependencies": { + "fastify-dx-solid": "^0.0.4", + "tsx": "^3.7.1", + "fastify-vite": "^3.0.0-beta.23", + "ky-universal": "^0.10.1", + "ky": "^0.31.0" + }, + "devDependencies": { + "@babel/eslint-parser": "^7.16.0", + "babel-preset-solid": "^1.4.4", + "@typescript-eslint/eslint-plugin": "^5.30.5", + "@typescript-eslint/parser": "^5.30.5", + "eslint": "^8.19.0", + "eslint-config-standard-with-typescript": "^22.0.0", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^6.0.0", + "eslint-plugin-solid": "^0.4.7", + "postcss-preset-env": "^7.7.1", + "unocss": "^0.37.4", + "vite-plugin-solid": "^2.2.6" + }, + "devInstall": { + "local": { + "fastify-dx-solid": "^0.0.1-pre" + }, + "external": { + "tsx": "^3.7.1", + "fastify-vite": "^3.0.0-beta.23", + "ky-universal": "^0.10.1", + "ky": "^0.31.0" + } + } +} \ No newline at end of file diff --git a/starters/solid-ts/postcss.config.cjs b/starters/solid-ts/postcss.config.cjs new file mode 100644 index 0000000..8b78078 --- /dev/null +++ b/starters/solid-ts/postcss.config.cjs @@ -0,0 +1,9 @@ +const postcssPresetEnv = require('postcss-preset-env') + +module.exports = { + plugins: [ + postcssPresetEnv({ + stage: 1, + }), + ] +} diff --git a/starters/solid-ts/server.d.ts b/starters/solid-ts/server.d.ts new file mode 100644 index 0000000..bd3b6a2 --- /dev/null +++ b/starters/solid-ts/server.d.ts @@ -0,0 +1,6 @@ +declare module 'fastify' { + export interface FastifyInstance { + vite: object + db: object + } +} diff --git a/starters/solid-ts/server.ts b/starters/solid-ts/server.ts new file mode 100644 index 0000000..ff49dac --- /dev/null +++ b/starters/solid-ts/server.ts @@ -0,0 +1,32 @@ +import Fastify from 'fastify' +import FastifyVite from 'fastify-vite' +import FastifyDXSolid from 'fastify-dx-solid' + +const server = Fastify() + +server.decorate('db', { + todoList: [ + 'Do laundry', + 'Respond to emails', + 'Write report', + ], +}) + +server.put('/api/todo/items', (req, reply) => { + server.db.todoList.push(req.body.item) + reply.send({ ok: true }) +}) + +server.delete('/api/todo/items', (req, reply) => { + server.db.todoList.splice(req.body.index, 1) + reply.send({ ok: true }) +}) + +await server.register(FastifyVite, { + root: import.meta.url, + renderer: FastifyDXSolid, +}) + +await server.vite.ready() + +await server.listen(3000) diff --git a/starters/solid-ts/tsconfig.json b/starters/solid-ts/tsconfig.json new file mode 100644 index 0000000..de018f6 --- /dev/null +++ b/starters/solid-ts/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "strictNullChecks": true + }, + "include": [ + "**/*.ts", + "**/*.tsx" + ], + "files": [ + "server.d.ts" + ] +} \ No newline at end of file diff --git a/starters/solid-ts/vite.config.js b/starters/solid-ts/vite.config.js new file mode 100644 index 0000000..107b3f8 --- /dev/null +++ b/starters/solid-ts/vite.config.js @@ -0,0 +1,21 @@ +import { join, dirname } from 'path' +import { fileURLToPath } from 'url' + +import viteSolid from 'vite-plugin-solid' +import viteSolidFastifyDX from 'fastify-dx-solid/plugin' +import unocss from 'unocss/vite' + +const path = fileURLToPath(import.meta.url) +const root = join(dirname(path), 'client') + +const plugins = [ + viteSolid({ ssr: true }), + viteSolidFastifyDX(), + unocss() +] + +const ssr = { + noExternal: ['solid-app-router'], +} + +export default { root, plugins, ssr } diff --git a/starters/solid/client/layouts/default.jsx b/starters/solid/client/layouts/default.jsx index aa43ed5..37c12f2 100644 --- a/starters/solid/client/layouts/default.jsx +++ b/starters/solid/client/layouts/default.jsx @@ -1,8 +1,5 @@ -import { children } from 'solid-js' - export default function Default (props) { - const c = children(() => props.children) return ( -
{c()}
+
{props.children}
) } diff --git a/starters/solid/package.json b/starters/solid/package.json index 2be31aa..c333d83 100644 --- a/starters/solid/package.json +++ b/starters/solid/package.json @@ -4,13 +4,13 @@ "dev": "node server.js --dev", "build": "npm run build:client && npm run build:server", "serve": "node server.js", - "devinstall": "zx ../../devinstall.mjs solid -- node server.js --dev", + "devinstall": "zx ../../devinstall.mjs -- node server.js --dev", "build:client": "vite build --outDir dist/client --ssrManifest", "build:server": "vite build --outDir dist/server --ssr /index.js", "lint": "eslint . --ext .js,.jsx --fix" }, "dependencies": { - "fastify-dx-solid": "^0.0.2", + "fastify-dx-solid": "^0.0.4", "fastify-vite": "^3.0.0-beta.23", "ky-universal": "^0.10.1", "ky": "^0.31.0" @@ -30,7 +30,7 @@ }, "devInstall": { "local": { - "fastify-dx-solid": "^0.0.1-pre" + "fastify-dx-solid": "^0.0.4" }, "external": { "fastify-vite": "^3.0.0-beta.23",