@flight-framework/cli 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flight-framework/cli",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "Command-line interface for Flight Framework",
5
5
  "keywords": [
6
6
  "flight",
@@ -1,7 +1,12 @@
1
+ import { useRouter } from './context/RouterContext';
2
+
1
3
  export default function App() {
4
+ const { path } = useRouter();
5
+
2
6
  return (
3
7
  <main>
4
- <h1>Flight ✈️</h1>
8
+ <h1>Welcome to Flight</h1>
9
+ <p>Current path: {path}</p>
5
10
  <p>Edit <code>src/App.tsx</code> to get started.</p>
6
11
  </main>
7
12
  );
@@ -0,0 +1,63 @@
1
+ import { createContext, useState, useEffect, useContext, type ReactNode } from 'react';
2
+
3
+ interface RouterContextValue {
4
+ path: string;
5
+ navigate: (to: string) => void;
6
+ }
7
+
8
+ /**
9
+ * Router Context for SSR-safe path sharing
10
+ * - Server: receives URL from request
11
+ * - Client: syncs with browser location
12
+ */
13
+ const RouterContext = createContext<RouterContextValue>({
14
+ path: '/',
15
+ navigate: () => { },
16
+ });
17
+
18
+ export function useRouter() {
19
+ return useContext(RouterContext);
20
+ }
21
+
22
+ interface RouterProviderProps {
23
+ children: ReactNode;
24
+ initialPath?: string;
25
+ }
26
+
27
+ /**
28
+ * Router Provider - wraps app to provide current path
29
+ *
30
+ * Usage:
31
+ * - Server: <RouterProvider initialPath={url}><App /></RouterProvider>
32
+ * - Client: <RouterProvider><App /></RouterProvider>
33
+ */
34
+ export function RouterProvider({ children, initialPath = '/' }: RouterProviderProps) {
35
+ const isClient = typeof window !== 'undefined';
36
+
37
+ const [path, setPath] = useState(
38
+ isClient ? window.location.pathname : initialPath
39
+ );
40
+
41
+ const navigate = (to: string) => {
42
+ if (isClient) {
43
+ window.history.pushState({}, '', to);
44
+ setPath(to);
45
+ }
46
+ };
47
+
48
+ useEffect(() => {
49
+ if (!isClient) return;
50
+
51
+ const handlePopState = () => setPath(window.location.pathname);
52
+ window.addEventListener('popstate', handlePopState);
53
+ return () => window.removeEventListener('popstate', handlePopState);
54
+ }, [isClient]);
55
+
56
+ return (
57
+ <RouterContext.Provider value={{ path, navigate }}>
58
+ {children}
59
+ </RouterContext.Provider>
60
+ );
61
+ }
62
+
63
+ export default RouterProvider;
@@ -1,11 +1,19 @@
1
1
  import { hydrateRoot, createRoot } from 'react-dom/client';
2
+ import { RouterProvider } from './context/RouterContext';
2
3
  import App from './App';
3
4
  import './styles/global.css';
4
5
 
5
6
  const root = document.getElementById('root')!;
6
7
 
8
+ const app = (
9
+ <RouterProvider>
10
+ <App />
11
+ </RouterProvider>
12
+ );
13
+
14
+ // Hydrate SSR content or render client-only
7
15
  if (root.innerHTML.trim()) {
8
- hydrateRoot(root, <App />);
16
+ hydrateRoot(root, app);
9
17
  } else {
10
- createRoot(root).render(<App />);
18
+ createRoot(root).render(app);
11
19
  }
@@ -1,6 +1,17 @@
1
1
  import { renderToString } from 'react-dom/server';
2
+ import { RouterProvider } from './context/RouterContext';
2
3
  import App from './App';
3
4
 
4
- export function render(_url: string): string {
5
- return renderToString(<App />);
5
+ /**
6
+ * Server-side render function
7
+ * Called by Flight for each page request
8
+ *
9
+ * @param url - Request URL path (e.g., '/about', '/products/123')
10
+ */
11
+ export function render(url: string): string {
12
+ return renderToString(
13
+ <RouterProvider initialPath={url}>
14
+ <App />
15
+ </RouterProvider>
16
+ );
6
17
  }