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 @@
+
+
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 (
+ <>
+
+ {state.message}
+
+ - /using-data demonstrates how to
+ leverage the
getData()
function
+ and useRouteContext()
to retrieve server data for a route.
+ - /using-store demonstrates how to
+ retrieve server data and maintain it in the global state.
+ - /using-auth demonstrates how to
+ wrap a route in a custom layout component.
+ - /client-only demonstrates how to set
+ up a route for rendering on the client only (disables SSR).
+ - /server-only demonstrates how to set
+ up a route for rendering on the server only (sends no JavaScript).
+ - /streaming demonstrates how to set
+ up a route for SSR in streaming mode.
+
+ >
+ )
+}
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
+
+ {(item, i) =>
+ - {item}
+ }
+
+
+
+
+
+
+ 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
+
+ {(item, i) =>
+ - {item}
+ }
+
+
+
+
+
+
+ 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
+
+ {(item, i) =>
+ - {item}
+ }
+
+
+
+
+
+
+ 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",