create-aziz-app 3.1.1 → 3.1.3

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.
Files changed (33) hide show
  1. package/README.md +658 -207
  2. package/bin/create-aziz-app.js +302 -351
  3. package/package.json +1 -1
  4. package/template/README.md +14 -279
  5. package/template/_framework/api.js +219 -219
  6. package/template/_framework/boot.js +33 -33
  7. package/template/_framework/hooks.js +367 -291
  8. package/template/_framework/next-response.js +128 -128
  9. package/template/_framework/route-match.js +145 -145
  10. package/template/_framework/router.js +465 -259
  11. package/template/_framework/runtime.js +264 -264
  12. package/template/app/layout.js +3 -5
  13. package/template/app/page.js +9 -32
  14. package/template/docs/01-getting-started.md +151 -151
  15. package/template/docs/02-project-structure.md +109 -109
  16. package/template/docs/03-pages-and-layouts.md +140 -140
  17. package/template/docs/04-routing.md +120 -120
  18. package/template/docs/05-hooks.md +169 -169
  19. package/template/docs/06-api-routes.md +210 -210
  20. package/template/docs/07-api-client.md +151 -151
  21. package/template/docs/08-styling.md +94 -94
  22. package/template/docs/09-imports-and-modules.md +97 -97
  23. package/template/docs/10-database-and-models.md +154 -154
  24. package/template/docs/11-authentication.md +171 -171
  25. package/template/docs/12-production-and-deployment.md +121 -121
  26. package/template/docs/13-internals.md +179 -179
  27. package/template/docs/README.md +67 -67
  28. package/template/index.html +20 -20
  29. package/template/package.json +16 -16
  30. package/template/scripts/dev-server.js +493 -381
  31. package/template/scripts/lib/api-router.js +525 -525
  32. package/template/scripts/lib/js-transform.js +213 -141
  33. package/template/scripts/lib/module-resolver.js +132 -132
@@ -1,169 +1,169 @@
1
- # 05 · Hooks
2
-
3
- Aziz.js implements the React hooks API. **No imports are needed** — every hook is a global.
4
-
5
- ```js
6
- const [count, setCount] = useState(0); // just works
7
- ```
8
-
9
- ## `useState`
10
-
11
- ```js
12
- const [count, setCount] = useState(0);
13
-
14
- // Functional update (uses the latest value):
15
- setCount(c => c + 1);
16
-
17
- // Re-render only happens if the value actually changed:
18
- setCount(0); // if it's already 0, nothing happens
19
- ```
20
-
21
- Each component instance gets **its own** state, keyed by its position in the tree. Two `<Counter />` siblings never share state, even without keys (keys make it explicit and stable — always pass `key` in lists).
22
-
23
- ## `useReducer`
24
-
25
- ```js
26
- function reducer(state, action) {
27
- switch (action.type) {
28
- case 'inc': return { count: state.count + 1 };
29
- case 'reset': return { count: 0 };
30
- default: return state;
31
- }
32
- }
33
-
34
- const [state, dispatch] = useReducer(reducer, { count: 0 });
35
-
36
- dispatch({ type: 'inc' });
37
- ```
38
-
39
- Signature matches React: `useReducer(reducer, initialState, init?)`.
40
-
41
- ## `useEffect`
42
-
43
- Run side effects after render. Always return a **cleanup** function if you subscribe/touch timers:
44
-
45
- ```js
46
- useEffect(() => {
47
- const id = setInterval(tick, 1000);
48
- return () => clearInterval(id); // cleanup on unmount / dep change
49
- }, []); // [] = run once
50
-
51
- useEffect(() => {
52
- document.title = name;
53
- }, [name]); // rerun when name changes
54
-
55
- useEffect(() => {
56
- // no dep array → runs after EVERY render
57
- });
58
- ```
59
-
60
- Rules:
61
-
62
- - The callback runs **asynchronously** after the DOM update (a microtask), not during render.
63
- - The returned cleanup runs when deps change or the component unmounts.
64
- - **On route change, all effects are cleaned up** — navigating away from a page with a `setInterval` won't leak the timer.
65
-
66
- ## `useMemo` / `useCallback`
67
-
68
- ```js
69
- const expensive = useMemo(() => compute(a, b), [a, b]);
70
- const onClick = useCallback(() => doThing(id), [id]);
71
- ```
72
-
73
- Memoize only when the work is actually expensive — otherwise it's overhead.
74
-
75
- ## `useRef`
76
-
77
- Mutable box that survives re-renders without causing them:
78
-
79
- ```js
80
- const inputRef = useRef(null);
81
-
82
- useEffect(() => { inputRef.current?.focus(); }, []);
83
-
84
- return <input ref={inputRef} />;
85
- ```
86
-
87
- `ref` accepts a **function** (`ref={el => (node = el)}`) or an **object** (`ref={r}`); both receive the real DOM node.
88
-
89
- ## Context
90
-
91
- Share a value through the tree without prop drilling:
92
-
93
- ```js
94
- const ThemeContext = createContext('light');
95
-
96
- function App() {
97
- return (
98
- <ThemeContext.Provider value="dark">
99
- <Toolbar />
100
- </ThemeContext.Provider>
101
- );
102
- }
103
-
104
- function ThemeButton() {
105
- const theme = useContext(ThemeContext); // "dark"
106
- return <span>{theme}</span>;
107
- }
108
- ```
109
-
110
- - `useContext(SomeContext)` returns the nearest provider's value, or the **default** if no provider is above.
111
- - **Nested providers**: the innermost wins for its subtree.
112
- - Providers can be nested and combined with arbitrary wrapping elements — context is resolved during a top-down materialization pass, so a provider's value is visible to everything it renders.
113
-
114
- ## `useLocalStorage`
115
-
116
- State that survives a refresh and syncs across tabs:
117
-
118
- ```js
119
- const [name, setName] = useLocalStorage('name', '');
120
-
121
- setName('Aziz'); // also written to localStorage
122
- ```
123
-
124
- A `storage` event listener keeps other open tabs in sync.
125
-
126
- ## `useFetch` / `useApi`
127
-
128
- Declarative data fetching with built-in loading/error state, abort-on-change, and a manual `refetch`:
129
-
130
- ```js
131
- const { data, loading, error, refetch } = useFetch('/api/users');
132
-
133
- if (loading) return <p>Loading…</p>;
134
- if (error) return <p>Error: {error}</p>;
135
- return <ul>{data.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
136
-
137
- refetch(); // re-run the request
138
- ```
139
-
140
- - `data` is parsed from JSON when the response is JSON (otherwise text).
141
- - In-flight requests are **aborted** if the URL changes or the component unmounts.
142
- - `useApi` is an alias of `useFetch`.
143
-
144
- For imperative calls (POST, retries, custom headers) use the [API Client](./07-api-client.md) instead.
145
-
146
- ## Router hooks
147
-
148
- ```js
149
- const { pathname, push, replace, back, refresh, params } = useRouter();
150
- const { slug } = useParams();
151
- const q = useSearchParams().get('q');
152
- ```
153
-
154
- See [Routing](./04-routing.md).
155
-
156
- ## Global registry
157
-
158
- Available in every page/component without importing:
159
-
160
- ```
161
- useState useEffect useMemo useCallback useRef useReducer
162
- useContext createContext useLocalStorage useFetch useApi
163
- useRouter useParams useSearchParams
164
- navigate Link h Fragment api
165
- ```
166
-
167
- ## Continue
168
-
169
- → [API Routes](./06-api-routes.md)
1
+ # 05 · Hooks
2
+
3
+ Aziz.js implements the React hooks API. **No imports are needed** — every hook is a global.
4
+
5
+ ```js
6
+ const [count, setCount] = useState(0); // just works
7
+ ```
8
+
9
+ ## `useState`
10
+
11
+ ```js
12
+ const [count, setCount] = useState(0);
13
+
14
+ // Functional update (uses the latest value):
15
+ setCount(c => c + 1);
16
+
17
+ // Re-render only happens if the value actually changed:
18
+ setCount(0); // if it's already 0, nothing happens
19
+ ```
20
+
21
+ Each component instance gets **its own** state, keyed by its position in the tree. Two `<Counter />` siblings never share state, even without keys (keys make it explicit and stable — always pass `key` in lists).
22
+
23
+ ## `useReducer`
24
+
25
+ ```js
26
+ function reducer(state, action) {
27
+ switch (action.type) {
28
+ case 'inc': return { count: state.count + 1 };
29
+ case 'reset': return { count: 0 };
30
+ default: return state;
31
+ }
32
+ }
33
+
34
+ const [state, dispatch] = useReducer(reducer, { count: 0 });
35
+
36
+ dispatch({ type: 'inc' });
37
+ ```
38
+
39
+ Signature matches React: `useReducer(reducer, initialState, init?)`.
40
+
41
+ ## `useEffect`
42
+
43
+ Run side effects after render. Always return a **cleanup** function if you subscribe/touch timers:
44
+
45
+ ```js
46
+ useEffect(() => {
47
+ const id = setInterval(tick, 1000);
48
+ return () => clearInterval(id); // cleanup on unmount / dep change
49
+ }, []); // [] = run once
50
+
51
+ useEffect(() => {
52
+ document.title = name;
53
+ }, [name]); // rerun when name changes
54
+
55
+ useEffect(() => {
56
+ // no dep array → runs after EVERY render
57
+ });
58
+ ```
59
+
60
+ Rules:
61
+
62
+ - The callback runs **asynchronously** after the DOM update (a microtask), not during render.
63
+ - The returned cleanup runs when deps change or the component unmounts.
64
+ - **On route change, all effects are cleaned up** — navigating away from a page with a `setInterval` won't leak the timer.
65
+
66
+ ## `useMemo` / `useCallback`
67
+
68
+ ```js
69
+ const expensive = useMemo(() => compute(a, b), [a, b]);
70
+ const onClick = useCallback(() => doThing(id), [id]);
71
+ ```
72
+
73
+ Memoize only when the work is actually expensive — otherwise it's overhead.
74
+
75
+ ## `useRef`
76
+
77
+ Mutable box that survives re-renders without causing them:
78
+
79
+ ```js
80
+ const inputRef = useRef(null);
81
+
82
+ useEffect(() => { inputRef.current?.focus(); }, []);
83
+
84
+ return <input ref={inputRef} />;
85
+ ```
86
+
87
+ `ref` accepts a **function** (`ref={el => (node = el)}`) or an **object** (`ref={r}`); both receive the real DOM node.
88
+
89
+ ## Context
90
+
91
+ Share a value through the tree without prop drilling:
92
+
93
+ ```js
94
+ const ThemeContext = createContext('light');
95
+
96
+ function App() {
97
+ return (
98
+ <ThemeContext.Provider value="dark">
99
+ <Toolbar />
100
+ </ThemeContext.Provider>
101
+ );
102
+ }
103
+
104
+ function ThemeButton() {
105
+ const theme = useContext(ThemeContext); // "dark"
106
+ return <span>{theme}</span>;
107
+ }
108
+ ```
109
+
110
+ - `useContext(SomeContext)` returns the nearest provider's value, or the **default** if no provider is above.
111
+ - **Nested providers**: the innermost wins for its subtree.
112
+ - Providers can be nested and combined with arbitrary wrapping elements — context is resolved during a top-down materialization pass, so a provider's value is visible to everything it renders.
113
+
114
+ ## `useLocalStorage`
115
+
116
+ State that survives a refresh and syncs across tabs:
117
+
118
+ ```js
119
+ const [name, setName] = useLocalStorage('name', '');
120
+
121
+ setName('Aziz'); // also written to localStorage
122
+ ```
123
+
124
+ A `storage` event listener keeps other open tabs in sync.
125
+
126
+ ## `useFetch` / `useApi`
127
+
128
+ Declarative data fetching with built-in loading/error state, abort-on-change, and a manual `refetch`:
129
+
130
+ ```js
131
+ const { data, loading, error, refetch } = useFetch('/api/users');
132
+
133
+ if (loading) return <p>Loading…</p>;
134
+ if (error) return <p>Error: {error}</p>;
135
+ return <ul>{data.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
136
+
137
+ refetch(); // re-run the request
138
+ ```
139
+
140
+ - `data` is parsed from JSON when the response is JSON (otherwise text).
141
+ - In-flight requests are **aborted** if the URL changes or the component unmounts.
142
+ - `useApi` is an alias of `useFetch`.
143
+
144
+ For imperative calls (POST, retries, custom headers) use the [API Client](./07-api-client.md) instead.
145
+
146
+ ## Router hooks
147
+
148
+ ```js
149
+ const { pathname, push, replace, back, refresh, params } = useRouter();
150
+ const { slug } = useParams();
151
+ const q = useSearchParams().get('q');
152
+ ```
153
+
154
+ See [Routing](./04-routing.md).
155
+
156
+ ## Global registry
157
+
158
+ Available in every page/component without importing:
159
+
160
+ ```
161
+ useState useEffect useMemo useCallback useRef useReducer
162
+ useContext createContext useLocalStorage useFetch useApi
163
+ useRouter useParams useSearchParams
164
+ navigate Link h Fragment api
165
+ ```
166
+
167
+ ## Continue
168
+
169
+ → [API Routes](./06-api-routes.md)