Skip to content

Commit

Permalink
more progress
Browse files Browse the repository at this point in the history
  • Loading branch information
kentcdodds committed Apr 3, 2024
1 parent 0ded9f4 commit ff89326
Show file tree
Hide file tree
Showing 770 changed files with 6,037 additions and 1,602 deletions.
8 changes: 2 additions & 6 deletions exercises/01.init/01.problem.static/server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ closeWithGrace(async ({ signal, err }) => {
if (err) console.error('Shutting down server due to error', err)
else console.log('Shutting down server due to signal', signal)

await new Promise((resolve, reject) => {
server.close(err => {
if (err) reject(err)
else resolve()
})
})
await new Promise(resolve => server.close(resolve))
process.exit()
})
8 changes: 2 additions & 6 deletions exercises/01.init/01.solution.static/server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ closeWithGrace(async ({ signal, err }) => {
if (err) console.error('Shutting down server due to error', err)
else console.log('Shutting down server due to signal', signal)

await new Promise((resolve, reject) => {
server.close(err => {
if (err) reject(err)
else resolve()
})
})
await new Promise(resolve => server.close(resolve))
process.exit()
})
8 changes: 2 additions & 6 deletions exercises/02.server-components/01.problem.rsc/server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ closeWithGrace(async ({ signal, err }) => {
if (err) console.error('Shutting down server due to error', err)
else console.log('Shutting down server due to signal', signal)

await new Promise((resolve, reject) => {
server.close(err => {
if (err) reject(err)
else resolve()
})
})
await new Promise(resolve => server.close(resolve))
process.exit()
})
8 changes: 2 additions & 6 deletions exercises/02.server-components/01.solution.rsc/server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ closeWithGrace(async ({ signal, err }) => {
if (err) console.error('Shutting down server due to error', err)
else console.log('Shutting down server due to signal', signal)

await new Promise((resolve, reject) => {
server.close(err => {
if (err) reject(err)
else resolve()
})
})
await new Promise(resolve => server.close(resolve))
process.exit()
})
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ closeWithGrace(async ({ signal, err }) => {
if (err) console.error('Shutting down server due to error', err)
else console.log('Shutting down server due to signal', signal)

await new Promise((resolve, reject) => {
server.close(err => {
if (err) reject(err)
else resolve()
})
})
await new Promise(resolve => server.close(resolve))
process.exit()
})
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ closeWithGrace(async ({ signal, err }) => {
if (err) console.error('Shutting down server due to error', err)
else console.log('Shutting down server due to signal', signal)

await new Promise((resolve, reject) => {
server.close(err => {
if (err) reject(err)
else resolve()
})
})
await new Promise(resolve => server.close(resolve))
process.exit()
})
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ closeWithGrace(async ({ signal, err }) => {
if (err) console.error('Shutting down server due to error', err)
else console.log('Shutting down server due to signal', signal)

await new Promise((resolve, reject) => {
server.close(err => {
if (err) reject(err)
else resolve()
})
})
await new Promise(resolve => server.close(resolve))
process.exit()
})
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ closeWithGrace(async ({ signal, err }) => {
if (err) console.error('Shutting down server due to error', err)
else console.log('Shutting down server due to signal', signal)

await new Promise((resolve, reject) => {
server.close(err => {
if (err) reject(err)
else resolve()
})
})
await new Promise(resolve => server.close(resolve))
process.exit()
})
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ closeWithGrace(async ({ signal, err }) => {
if (err) console.error('Shutting down server due to error', err)
else console.log('Shutting down server due to signal', signal)

await new Promise((resolve, reject) => {
server.close(err => {
if (err) reject(err)
else resolve()
})
})
await new Promise(resolve => server.close(resolve))
process.exit()
})
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ closeWithGrace(async ({ signal, err }) => {
if (err) console.error('Shutting down server due to error', err)
else console.log('Shutting down server due to signal', signal)

await new Promise((resolve, reject) => {
server.close(err => {
if (err) reject(err)
else resolve()
})
})
await new Promise(resolve => server.close(resolve))
process.exit()
})

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Node.js Loader
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "exercises__sep__03.client-components__sep__01.problem.client",
"name": "exercises__sep__03.client-components__sep__01.problem.loader",
"version": "1.0.0",
"type": "module",
"private": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"react": "https://esm.sh/[email protected]?pin=v126&dev",
"react-dom": "https://esm.sh/[email protected]?pin=v126&dev",
"react-dom/client": "https://esm.sh/[email protected]/client?pin=v126&dev",
"react-server-dom-esm/client": "https://esm.sh/@kentcdodds/[email protected]/client?pin=v126&dev"
"react-server-dom-esm/client": "https://esm.sh/@kentcdodds/[email protected]/client?pin=v126&dev",
"react-error-boundary": "https://esm.sh/[email protected]?pin=126&dev"
}
}
</script>
Expand Down
65 changes: 65 additions & 0 deletions exercises/03.client-components/01.problem.loader/server/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import closeWithGrace from 'close-with-grace'
import compress from 'compression'
import express from 'express'
import { createElement as h } from 'react'
import { renderToPipeableStream } from 'react-server-dom-esm/server'
import { App } from '../src/app.js'
import { shipDataStorage } from './async-storage.js'

const PORT = process.env.PORT || 3000

const app = express()
app.use(compress())
// this is here so the workshop app knows when the server has started
app.head('/', (req, res) => res.status(200).end())

app.use(express.static('public', { index: false }))
app.use('/js/src', express.static('src'))

// This just cleans up the URL if the search ever gets cleared... Not important
// for RSCs... Just ... I just can't help myself. I like URLs clean.
app.use((req, res, next) => {
if (req.query.search === '') {
const searchParams = new URLSearchParams(req.search)
searchParams.delete('search')
const location = [req.path, searchParams.toString()]
.filter(Boolean)
.join('?')
return res.redirect(302, location)
} else {
next()
}
})

app.get('/rsc/:shipId?', async function (req, res) {
try {
const shipId = req.params.shipId || null
const search = req.query.search || ''
const data = { shipId, search }
shipDataStorage.run(data, () => {
const { pipe } = renderToPipeableStream(h(App))
pipe(res)
})
} catch (error) {
console.error(error)
res.status(500).json({ error: error.message })
}
})

app.get('/:shipId?', async function (req, res) {
res.set('Content-type', 'text/html')
return res.sendFile('index.html', { root: 'public' })
})

const server = app.listen(PORT, () => {
console.log(`🚀 We have liftoff!`)
console.log(`http://localhost:${PORT}`)
})

closeWithGrace(async ({ signal, err }) => {
if (err) console.error('Shutting down server due to error', err)
else console.log('Shutting down server due to signal', signal)

await new Promise(resolve => server.close(resolve))
process.exit()
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// 🐨 register our custom rsc-loader.js module as a custom loader
// 💰 this isn't a node.js workshop, so here you go
// import { register } from 'node:module'

// register('./rsc-loader.js', import.meta.url)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { resolve, load as reactLoad } from 'react-server-dom-esm/node-loader'

export { resolve }

async function textLoad(url, context, defaultLoad) {
const result = await defaultLoad(url, context, defaultLoad)
if (result.format === 'module') {
if (typeof result.source === 'string') {
return result
}
return {
source: Buffer.from(result.source).toString('utf8'),
format: 'module',
}
}
return result
}

export async function load(url, context, defaultLoad) {
const result = await reactLoad(url, context, (u, c) => {
return textLoad(u, c, defaultLoad)
})
// 🐨 uncomment this so you can observe the changes the loader makes to our
// error-boundary.js module.
// if (url.includes('error-boundary')) {
// console.log(result.source)
// }
return result
}
48 changes: 48 additions & 0 deletions exercises/03.client-components/01.problem.loader/src/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Fragment, Suspense, createElement as h } from 'react'
import { shipDataStorage } from '../server/async-storage.js'
// 🐨 import the ErrorBoundary from the client module
// import { ErrorBoundary } from './error-boundary.js'
import { ShipDetails, ShipFallback } from './ship-details.js'
import { SearchResults, SearchResultsFallback } from './ship-search-results.js'

// 🐨 log the ErrorBoundary to the console so you can see what the server sees
// 💰 console.log(ErrorBoundary.toString())

export function App() {
const { shipId, search } = shipDataStorage.getStore()
return h(
'div',
{ className: 'app' },
h(
'div',
{ className: 'search' },
h(
Fragment,
null,
h(
'form',
{},
h('input', {
name: 'search',
placeholder: 'Filter ships...',
type: 'search',
defaultValue: search,
autoFocus: true,
}),
),
h(
'ul',
null,
h(Suspense, { fallback: h(SearchResultsFallback) }, h(SearchResults)),
),
),
),
h(
'div',
{ className: 'details' },
shipId
? h(Suspense, { fallback: h(ShipFallback) }, h(ShipDetails))
: h('p', null, 'Select a ship from the list to see details'),
),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// 🦉 normally you won't have to add a 'use client' for third party modules that
// are obviously client-only like this, but there's a bug in react-error-boundary
// for now, so we're going to add 'use client' to this module and that will make
// react-error-boundary only available in the client as well.
// https://github.com/bvaughn/react-error-boundary/issues/182

// 🐨 add the 'use client' pragma here

// 🐨 export everything from react-error-boundary
35 changes: 35 additions & 0 deletions exercises/03.client-components/01.problem.loader/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Suspense, createElement as h, startTransition, use } from 'react'
import { createRoot } from 'react-dom/client'
import { createFromFetch } from 'react-server-dom-esm/client'
import { shipFallbackSrc } from './img-utils.js'

const getGlobalLocation = () =>
window.location.pathname + window.location.search

const initialLocation = getGlobalLocation()
const initialContentFetchPromise = fetch(`/rsc${initialLocation}`)
const initialContentPromise = createFromFetch(initialContentFetchPromise)

function Root() {
const content = use(initialContentPromise)
return content
}

startTransition(() => {
createRoot(document.getElementById('root')).render(
h(
'div',
{ className: 'app-wrapper' },
h(
Suspense,
{
fallback: h('img', {
style: { maxWidth: 400 },
src: shipFallbackSrc,
}),
},
h(Root),
),
),
)
})
Loading

0 comments on commit ff89326

Please sign in to comment.