Skip to content

Commit

Permalink
chore(examples): new_defineEntries (#993)
Browse files Browse the repository at this point in the history
Migrating examples:
- [x] 38_cookies
- [x] 39_api
- [x] 35_nesting
  • Loading branch information
dai-shi authored Nov 9, 2024
1 parent 75c9884 commit b883c4a
Show file tree
Hide file tree
Showing 17 changed files with 122 additions and 136 deletions.
2 changes: 1 addition & 1 deletion examples/31_minimal/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StrictMode } from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/client';
import { Root, Slot } from 'waku/minimal/client';

const rootElement = (
<StrictMode>
Expand Down
1 change: 0 additions & 1 deletion examples/31_minimal/waku.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@ export default defineConfig({
import('waku/middleware/context'),
import('waku/middleware/dev-server'),
import('waku/middleware/handler'),
import('waku/middleware/fallback'),
],
});
63 changes: 29 additions & 34 deletions examples/35_nesting/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
import type { ReactNode } from 'react';
import { defineEntries } from 'waku/server';
import { Slot } from 'waku/client';
import { new_defineEntries } from 'waku/minimal/server';
import { Slot } from 'waku/minimal/client';

import App from './components/App';
import InnerApp from './components/InnerApp';
import AppWithoutSsr from './components/AppWithoutSsr';

export default defineEntries(
// renderEntries
async (rscPath) => {
const params = new URLSearchParams(rscPath || 'App=Waku&InnerApp=0');
const result: Record<string, ReactNode> = {};
if (params.has('App')) {
result.App = <App name={params.get('App')!} />;
export default new_defineEntries({
unstable_handleRequest: async (input, { renderRsc, renderHtml }) => {
if (input.type === 'component') {
const params = new URLSearchParams(
input.rscPath || 'App=Waku&InnerApp=0',
);
const result: Record<string, ReactNode> = {};
if (params.has('App')) {
result.App = <App name={params.get('App')!} />;
}
if (params.has('InnerApp')) {
result.InnerApp = <InnerApp count={Number(params.get('InnerApp'))} />;
}
if (params.has('AppWithoutSsr')) {
result.AppWithoutSsr = <AppWithoutSsr />;
}
return renderRsc(result);
}
if (params.has('InnerApp')) {
result.InnerApp = <InnerApp count={Number(params.get('InnerApp'))} />;
if (input.type === 'custom' && input.pathname === '/') {
return renderHtml(
{ App: <App name="Waku" />, InnerApp: <InnerApp count={0} /> },
<Slot id="App" />,
'',
);
}
if (params.has('AppWithoutSsr')) {
result.AppWithoutSsr = <AppWithoutSsr />;
}
return result;
},
// getBuildConfig
async () => [
unstable_getBuildConfig: async () => [
{
pathname: '/',
pathSpec: [],
entries: [
{ rscPath: '' },
{ rscPath: 'InnerApp=1', skipPrefetch: true },
Expand All @@ -36,23 +45,9 @@ export default defineEntries(
],
},
{
pathname: '/no-ssr',
pathSpec: [{ type: 'literal', name: '/no-ssr' }],
entries: [{ rscPath: 'AppWithoutSsr' }],
isStatic: true,
},
],
// getSsrConfig
async (pathname) => {
switch (pathname) {
case '/':
return {
rscPath: '',
html: <Slot id="App" />,
};
case '/no-ssr':
return null;
default:
return null;
}
},
);
});
2 changes: 1 addition & 1 deletion examples/35_nesting/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StrictMode } from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/client';
import { Root, Slot } from 'waku/minimal/client';

const pathname = window.location.pathname;

Expand Down
11 changes: 11 additions & 0 deletions examples/35_nesting/waku.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// This is a temporary file while experimenting new_defineEntries

import { defineConfig } from 'waku/config';

export default defineConfig({
middleware: () => [
import('waku/middleware/context'),
import('waku/middleware/dev-server'),
import('waku/middleware/handler'),
],
});
9 changes: 4 additions & 5 deletions examples/38_cookies/src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Suspense, cache } from 'react';
import { unstable_getCustomContext as getCustomContext } from 'waku/server';
import { getContextData } from 'waku/middleware/context';
import { getHonoContext } from 'waku/unstable_hono';

import { Counter } from './Counter';
Expand All @@ -13,14 +13,13 @@ const InternalAsyncComponent = async () => {
if (val1 !== val2) {
throw new Error('Cache not working');
}
// console.log(getCustomContext()); // fails when it's sent to the browser
console.log('waku context', Object.keys(getCustomContext()));
console.log('waku context', Object.keys(getContextData()));
console.log('hono context', Object.keys(getHonoContext()));
return null;
};

const App = ({ name, items }: { name: string; items: unknown[] }) => {
const context = getCustomContext<{ count: number }>();
const data = getContextData() as { count?: number };
return (
<html>
<head>
Expand All @@ -32,7 +31,7 @@ const App = ({ name, items }: { name: string; items: unknown[] }) => {
>
<h1>Hello {name}!!</h1>
<h3>This is a server component.</h3>
<p>Cookie count: {context.count}</p>
<p>Cookie count: {data.count || 0}</p>
<Counter />
<p>Item count: {items.length}</p>
<Suspense>
Expand Down
51 changes: 22 additions & 29 deletions examples/38_cookies/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import fsPromises from 'node:fs/promises';
import {
defineEntries,
unstable_getCustomContext as getCustomContext,
} from 'waku/server';
import { Slot } from 'waku/client';
import { new_defineEntries } from 'waku/minimal/server';
import { Slot } from 'waku/minimal/client';
import { getContextData } from 'waku/middleware/context';

import App from './components/App';

export default defineEntries(
// renderEntries
async (rscPath) => {
const context = getCustomContext<{ count: number }>();
++context.count;
export default new_defineEntries({
unstable_handleRequest: async (input, { renderRsc, renderHtml }) => {
const data = getContextData() as { count?: number };
data.count = (data.count || 0) + 1;
const items = JSON.parse(
await fsPromises.readFile(
path.join(
Expand All @@ -23,24 +20,20 @@ export default defineEntries(
'utf8',
),
);
return {
App: <App name={rscPath || 'Waku'} items={items} />,
};
},
// getBuildConfig
async () => [
{ pathname: '/', entries: [{ rscPath: '' }], context: { count: 0 } },
],
// getSsrConfig
async (pathname) => {
switch (pathname) {
case '/':
return {
rscPath: '',
html: <Slot id="App" />,
};
default:
return null;
if (input.type === 'component') {
return renderRsc({
App: <App name={input.rscPath || 'Waku'} items={items} />,
});
}
if (input.type === 'custom' && input.pathname === '/') {
return renderHtml(
{ App: <App name={'Waku'} items={items} /> },
<Slot id="App" />,
'',
);
}
},
);
unstable_getBuildConfig: async () => [
{ pathSpec: [], entries: [{ rscPath: '' }] },
],
});
2 changes: 1 addition & 1 deletion examples/38_cookies/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StrictMode } from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/client';
import { Root, Slot } from 'waku/minimal/client';

const rootElement = (
<StrictMode>
Expand Down
4 changes: 2 additions & 2 deletions examples/38_cookies/src/middleware/cookie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const COOKIE_OPTS = {};
const cookieMiddleware: Middleware = () => {
return async (ctx, next) => {
const cookies = cookie.parse(ctx.req.headers.cookie || '');
ctx.context.count = Number(cookies.count) || 0;
ctx.data.count = Number(cookies.count) || 0;
await next();
ctx.res.headers ||= {};
let origSetCookie = ctx.res.headers['set-cookie'] || ([] as string[]);
Expand All @@ -17,7 +17,7 @@ const cookieMiddleware: Middleware = () => {
}
ctx.res.headers['set-cookie'] = [
...origSetCookie,
cookie.serialize('count', String(ctx.context.count), COOKIE_OPTS),
cookie.serialize('count', String(ctx.data.count), COOKIE_OPTS),
];
};
};
Expand Down
10 changes: 5 additions & 5 deletions examples/38_cookies/waku.config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/** @type {import('waku/config').Config} */
export default {
import { defineConfig } from 'waku/config';

export default defineConfig({
middleware: () => [
import('waku/middleware/context'),
import('./src/middleware/cookie.js'),
import('waku/middleware/dev-server'),
import('waku/middleware/rsc'),
import('waku/middleware/ssr'),
import('waku/middleware/handler'),
],
};
});
48 changes: 26 additions & 22 deletions examples/39_api/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
import { defineEntries } from 'waku/server';
import { Slot } from 'waku/client';
import { new_defineEntries } from 'waku/minimal/server';
import { Slot } from 'waku/minimal/client';

import App from './components/App';

export default defineEntries(
// renderEntries
async (rscPath) => {
return {
App: <App name={rscPath || 'Waku'} />,
};
},
// getBuildConfig
async () => [{ pathname: '/', entries: [{ rscPath: '' }] }],
// getSsrConfig
async (pathname) => {
switch (pathname) {
case '/':
return {
rscPath: '',
html: <Slot id="App" />,
};
default:
return null;
const stringToStream = (str: string): ReadableStream => {
const encoder = new TextEncoder();
return new ReadableStream({
start(controller) {
controller.enqueue(encoder.encode(str));
controller.close();
},
});
};

export default new_defineEntries({
unstable_handleRequest: async (input, { renderRsc, renderHtml }) => {
if (input.type === 'component') {
return renderRsc({ App: <App name={input.rscPath || 'Waku'} /> });
}
if (input.type === 'custom' && input.pathname === '/') {
return renderHtml({ App: <App name="Waku" /> }, <Slot id="App" />, '');
}
if (input.type === 'custom' && input.pathname === '/api/hello') {
return stringToStream('world');
}
},
);
unstable_getBuildConfig: async () => [
{ pathSpec: [], entries: [{ rscPath: '' }] },
],
});
2 changes: 1 addition & 1 deletion examples/39_api/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StrictMode } from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { Root, Slot } from 'waku/client';
import { Root, Slot } from 'waku/minimal/client';

const rootElement = (
<StrictMode>
Expand Down
24 changes: 0 additions & 24 deletions examples/39_api/src/middleware/api.ts

This file was deleted.

13 changes: 7 additions & 6 deletions examples/39_api/waku.config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/** @type {import('waku/config').Config} */
export default {
// This is a temporary file while experimenting new_defineEntries

import { defineConfig } from 'waku/config';

export default defineConfig({
middleware: () => [
import('waku/middleware/context'),
import('./src/middleware/api.js'),
import('waku/middleware/dev-server'),
import('waku/middleware/rsc'),
import('waku/middleware/ssr'),
import('waku/middleware/handler'),
],
};
});
4 changes: 2 additions & 2 deletions packages/waku/src/lib/hono/ctx.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type { Context, Env } from 'hono';

// This can't be relative import
import { getContext } from 'waku/middleware/context';
import { getContextData } from 'waku/middleware/context';

// Internal context key
const HONO_CONTEXT = '__hono_context';

export const getHonoContext = <E extends Env = Env>() => {
const c = getContext().data[HONO_CONTEXT];
const c = getContextData()[HONO_CONTEXT];
if (!c) {
throw new Error('Hono context is not available');
}
Expand Down
Loading

0 comments on commit b883c4a

Please sign in to comment.