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,97 +1,97 @@
1
- # 09 · Imports & Modules
2
-
3
- Browser code imports work in two "flavors": **browser modules** served by the dev server, and **npm packages**. Everything goes through the same transform pipeline (JSX → `h()`, import rewriting).
4
-
5
- ## How imports are resolved
6
-
7
- | Specifier | Becomes / behavior | Notes |
8
- |------------|-------------------|-------|
9
- | `./Component.js` or `../lib/utils` | stays relative | The dev server loads files by path |
10
- | `/components/Navbar.js` | absolute in browser → maps to your project root | Works from anywhere |
11
- | `@/lib/db` | rewritten to `/lib/db` | Handy when deeply nested |
12
- | `mongoose` | rewritten to `/_modules/mongoose` | Bare npm package |
13
- | `lodash-es` | rewritten to `/_modules/lodash-es` | Exports field respected |
14
- | `node:fs`, `data:`, `file:`, `http://…` | left untouched | Skipped by the rewriter |
15
-
16
- The rewriter runs on **entire modules** (so multi-line `import { … } from 'pkg'` is handled correctly). It rewrites:
17
-
18
- - `import X from '…'` and `export … from '…'`
19
- - side-effect `import '…'`
20
- - dynamic `import('…')`
21
-
22
- ## In your pages/components
23
-
24
- Pages and components run in the browser (ES modules). You can import shared components, utilities, or anything you ship.
25
-
26
- ```js
27
- // app/dashboard/page.js
28
- import Navbar from '/components/Navbar.js';
29
- import { format } from '@/lib/format.js';
30
- import Button from './Button.js'; // co-located
31
-
32
- export default function Dashboard() {
33
- return (
34
- <div>
35
- <Navbar />
36
- <Button label={format('hello')} />
37
- </div>
38
- );
39
- }
40
- ```
41
-
42
- **No imports of React/hooks are needed.** `h`, `Fragment`, `useState`, etc. are global.
43
-
44
- ## npm packages
45
-
46
- 1. Install first:
47
-
48
- ```bash
49
- npm install lodash-es
50
- ```
51
-
52
- 2. Import normally:
53
-
54
- ```js
55
- import { pick } from 'lodash-es';
56
-
57
- const user = pick(obj, ['id', 'name']);
58
- ```
59
-
60
- The dev server resolves `lodash-es` to `/_modules/lodash-es`. Internally it looks into `node_modules/` and honors the `exports`/`browser`/`module`/`main` fields (see `scripts/lib/module-resolver.js`). If a module can't be found, the server returns a 404 and the browser throws — `npm install` fixes it.
61
-
62
- ## In API routes (server side)
63
-
64
- API routes are **Node.js code** (`api/*.js` or `.mjs`). Use Node's resolution:
65
-
66
- ```js
67
- // api/users.js
68
- const { NextResponse } = require('../_framework/next-response');
69
- const { connect } = require('../lib/db'); // server utility
70
- const User = require('../models/User');
71
-
72
- module.exports = {
73
- GET: async () => {
74
- await connect();
75
- return NextResponse.json(await User.find());
76
- },
77
- };
78
- ```
79
-
80
- Bare `mongoose` in API routes is the usual `require('mongoose')` (no `/_modules` rewrite needed).
81
-
82
- ## Loading strategy
83
-
84
- - `/_modules/*` is **on-the-fly**. The dev server reads the module file, runs the same transform pipeline (JSX transform only affects files inside your app tree; modules usually don't contain JSX), and serves it as ES module text.
85
- - Transforms for your own files (`app/`, `components/`) are **mtime-cached** to make hot reload snappy.
86
- - Framework internals (`/_framework/*`) are served as-is (no JSX rewrite).
87
-
88
- ## Tips
89
-
90
- - Use **absolute** (`/…`) for imports from the root, or `@/` for ergonomic deep imports.
91
- - Keep imports **explicit** with `.js` extensions when referencing local files in browser code (works fine in this system).
92
- - Dynamic `import()` is rewritten in browser code (`import('lodash-es')` → `import('/_modules/lodash-es')`) and also works natively in Node (`.mjs` context).
93
- - Avoid mixing `require` into browser code — it's never injected. Stick to `import/export`.
94
-
95
- ## Continue
96
-
97
- → [Database & Models](./10-database-and-models.md)
1
+ # 09 · Imports & Modules
2
+
3
+ Browser code imports work in two "flavors": **browser modules** served by the dev server, and **npm packages**. Everything goes through the same transform pipeline (JSX → `h()`, import rewriting).
4
+
5
+ ## How imports are resolved
6
+
7
+ | Specifier | Becomes / behavior | Notes |
8
+ |------------|-------------------|-------|
9
+ | `./Component.js` or `../lib/utils` | stays relative | The dev server loads files by path |
10
+ | `/components/Navbar.js` | absolute in browser → maps to your project root | Works from anywhere |
11
+ | `@/lib/db` | rewritten to `/lib/db` | Handy when deeply nested |
12
+ | `mongoose` | rewritten to `/_modules/mongoose` | Bare npm package |
13
+ | `lodash-es` | rewritten to `/_modules/lodash-es` | Exports field respected |
14
+ | `node:fs`, `data:`, `file:`, `http://…` | left untouched | Skipped by the rewriter |
15
+
16
+ The rewriter runs on **entire modules** (so multi-line `import { … } from 'pkg'` is handled correctly). It rewrites:
17
+
18
+ - `import X from '…'` and `export … from '…'`
19
+ - side-effect `import '…'`
20
+ - dynamic `import('…')`
21
+
22
+ ## In your pages/components
23
+
24
+ Pages and components run in the browser (ES modules). You can import shared components, utilities, or anything you ship.
25
+
26
+ ```js
27
+ // app/dashboard/page.js
28
+ import Navbar from '/components/Navbar.js';
29
+ import { format } from '@/lib/format.js';
30
+ import Button from './Button.js'; // co-located
31
+
32
+ export default function Dashboard() {
33
+ return (
34
+ <div>
35
+ <Navbar />
36
+ <Button label={format('hello')} />
37
+ </div>
38
+ );
39
+ }
40
+ ```
41
+
42
+ **No imports of React/hooks are needed.** `h`, `Fragment`, `useState`, etc. are global.
43
+
44
+ ## npm packages
45
+
46
+ 1. Install first:
47
+
48
+ ```bash
49
+ npm install lodash-es
50
+ ```
51
+
52
+ 2. Import normally:
53
+
54
+ ```js
55
+ import { pick } from 'lodash-es';
56
+
57
+ const user = pick(obj, ['id', 'name']);
58
+ ```
59
+
60
+ The dev server resolves `lodash-es` to `/_modules/lodash-es`. Internally it looks into `node_modules/` and honors the `exports`/`browser`/`module`/`main` fields (see `scripts/lib/module-resolver.js`). If a module can't be found, the server returns a 404 and the browser throws — `npm install` fixes it.
61
+
62
+ ## In API routes (server side)
63
+
64
+ API routes are **Node.js code** (`api/*.js` or `.mjs`). Use Node's resolution:
65
+
66
+ ```js
67
+ // api/users.js
68
+ const { NextResponse } = require('../_framework/next-response');
69
+ const { connect } = require('../lib/db'); // server utility
70
+ const User = require('../models/User');
71
+
72
+ module.exports = {
73
+ GET: async () => {
74
+ await connect();
75
+ return NextResponse.json(await User.find());
76
+ },
77
+ };
78
+ ```
79
+
80
+ Bare `mongoose` in API routes is the usual `require('mongoose')` (no `/_modules` rewrite needed).
81
+
82
+ ## Loading strategy
83
+
84
+ - `/_modules/*` is **on-the-fly**. The dev server reads the module file, runs the same transform pipeline (JSX transform only affects files inside your app tree; modules usually don't contain JSX), and serves it as ES module text.
85
+ - Transforms for your own files (`app/`, `components/`) are **mtime-cached** to make hot reload snappy.
86
+ - Framework internals (`/_framework/*`) are served as-is (no JSX rewrite).
87
+
88
+ ## Tips
89
+
90
+ - Use **absolute** (`/…`) for imports from the root, or `@/` for ergonomic deep imports.
91
+ - Keep imports **explicit** with `.js` extensions when referencing local files in browser code (works fine in this system).
92
+ - Dynamic `import()` is rewritten in browser code (`import('lodash-es')` → `import('/_modules/lodash-es')`) and also works natively in Node (`.mjs` context).
93
+ - Avoid mixing `require` into browser code — it's never injected. Stick to `import/export`.
94
+
95
+ ## Continue
96
+
97
+ → [Database & Models](./10-database-and-models.md)
@@ -1,154 +1,154 @@
1
- # 10 · Database & Models
2
-
3
- Since API routes run in **real Node.js**, you can connect to databases, send emails, and touch secrets. Do **not** put secrets or DB connections in browser code.
4
-
5
- ## Where DB code lives
6
-
7
- Put utilities and models under `lib/` and `models/`. Import them from API routes using CommonJS:
8
-
9
- ```text
10
- api/users.js → talks to HTTP
11
- lib/db.js → connects to MongoDB
12
- models/User.js → schema + model
13
- ```
14
-
15
- ## MongoDB + Mongoose (working example)
16
-
17
- ### 1. Install
18
-
19
- ```bash
20
- npm install mongoose
21
- ```
22
-
23
- ### 2. `lib/db.js`
24
-
25
- ```js
26
- // lib/db.js
27
- const mongoose = require('mongoose');
28
-
29
- const URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/azizjs';
30
-
31
- let conn = null;
32
-
33
- async function connectDB() {
34
- if (conn) return conn;
35
- conn = await mongoose.connect(URI, { maxPoolSize: 10 });
36
- console.log('✅ MongoDB connected');
37
- return conn;
38
- }
39
-
40
- module.exports = { connectDB };
41
- ```
42
-
43
- ### 3. `models/User.js`
44
-
45
- ```js
46
- // models/User.js
47
- const mongoose = require('mongoose');
48
-
49
- const UserSchema = new mongoose.Schema({
50
- name: String,
51
- email: String,
52
- createdAt: { type: Date, default: Date.now },
53
- });
54
-
55
- const User = mongoose.models.User || mongoose.model('User', UserSchema);
56
- module.exports = User;
57
- ```
58
-
59
- ### 4. `api/users.js`
60
-
61
- ```js
62
- // api/users.js
63
- const { NextResponse } = require('../_framework/next-response');
64
- const { connectDB } = require('../lib/db');
65
- const User = require('../models/User');
66
-
67
- module.exports = {
68
- GET: async () => {
69
- await connectDB();
70
- const users = await User.find().select('-__v').lean();
71
- return NextResponse.json(users);
72
- },
73
-
74
- POST: async (request) => {
75
- const body = await request.json();
76
- await connectDB();
77
- const user = await User.create(body);
78
- return NextResponse.json(user, { status: 201 });
79
- },
80
- };
81
- ```
82
-
83
- ### 5. `api/users/[id].js`
84
-
85
- ```js
86
- // api/users/[id].js
87
- const { NextResponse } = require('../_framework/next-response');
88
- const { connectDB } = require('../lib/db');
89
- const User = require('../models/User');
90
-
91
- module.exports = {
92
- GET: async (request) => {
93
- await connectDB();
94
- const user = await User.findById(request.params.id);
95
- if (!user) return NextResponse.json({ error: 'Not found' }, { status: 404 });
96
- return NextResponse.json(user);
97
- },
98
-
99
- PUT: async (request) => {
100
- const body = await request.json();
101
- await connectDB();
102
- const user = await User.findByIdAndUpdate(request.params.id, body, { new: true });
103
- if (!user) return NextResponse.json({ error: 'Not found' }, { status: 404 });
104
- return NextResponse.json(user);
105
- },
106
-
107
- DELETE: async (request) => {
108
- await connectDB();
109
- const user = await User.findByIdAndDelete(request.params.id);
110
- if (!user) return NextResponse.json({ error: 'Not found' }, { status: 404 });
111
- return NextResponse.json({ ok: true });
112
- },
113
- };
114
- ```
115
-
116
- ## Fetching from the browser
117
-
118
- Use `api` or `useFetch`:
119
-
120
- ```js
121
- // declarative
122
- const { data, loading, error } = useFetch('/api/users');
123
-
124
- // imperative
125
- async function addUser() {
126
- await api.post('/api/users', { name: 'Aziz', email: 'aziz@example.com' });
127
- }
128
- ```
129
-
130
- ## Other databases
131
-
132
- You don't need to change anything. Use native drivers:
133
-
134
- ```js
135
- // lib/pg.js
136
- const { Pool } = require('pg');
137
- const pool = new Pool({ connectionString: process.env.DATABASE_URL });
138
- module.exports = { query: (text, params) => pool.query(text, params) };
139
- ```
140
-
141
- ## Hot reload & caching
142
-
143
- Editing `lib/db.js` or `models/User.js` triggers server reload — the dev server purges project `require.cache` entries (excluding `node_modules`). Active DB connections may persist; keep your connection logic idempotent (`conn = null` singleton) as above.
144
-
145
- ## Tips
146
-
147
- - **Never** store DB credentials in browser files. Use environment variables (`.env`) and read them in API routes (`process.env.MONGODB_URI`). A future improvement could load `.env`, but today it's manual.
148
- - **Return lean objects** (`.lean()`) to cut JSON overhead.
149
- - **Validate input** — throw `Error` with `err.status = 400` on bad payloads.
150
- - **Use transactions** for multi-step operations.
151
-
152
- ## Continue
153
-
154
- → [Authentication](./11-authentication.md)
1
+ # 10 · Database & Models
2
+
3
+ Since API routes run in **real Node.js**, you can connect to databases, send emails, and touch secrets. Do **not** put secrets or DB connections in browser code.
4
+
5
+ ## Where DB code lives
6
+
7
+ Put utilities and models under `lib/` and `models/`. Import them from API routes using CommonJS:
8
+
9
+ ```text
10
+ api/users.js → talks to HTTP
11
+ lib/db.js → connects to MongoDB
12
+ models/User.js → schema + model
13
+ ```
14
+
15
+ ## MongoDB + Mongoose (working example)
16
+
17
+ ### 1. Install
18
+
19
+ ```bash
20
+ npm install mongoose
21
+ ```
22
+
23
+ ### 2. `lib/db.js`
24
+
25
+ ```js
26
+ // lib/db.js
27
+ const mongoose = require('mongoose');
28
+
29
+ const URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/azizjs';
30
+
31
+ let conn = null;
32
+
33
+ async function connectDB() {
34
+ if (conn) return conn;
35
+ conn = await mongoose.connect(URI, { maxPoolSize: 10 });
36
+ console.log('✅ MongoDB connected');
37
+ return conn;
38
+ }
39
+
40
+ module.exports = { connectDB };
41
+ ```
42
+
43
+ ### 3. `models/User.js`
44
+
45
+ ```js
46
+ // models/User.js
47
+ const mongoose = require('mongoose');
48
+
49
+ const UserSchema = new mongoose.Schema({
50
+ name: String,
51
+ email: String,
52
+ createdAt: { type: Date, default: Date.now },
53
+ });
54
+
55
+ const User = mongoose.models.User || mongoose.model('User', UserSchema);
56
+ module.exports = User;
57
+ ```
58
+
59
+ ### 4. `api/users.js`
60
+
61
+ ```js
62
+ // api/users.js
63
+ const { NextResponse } = require('../_framework/next-response');
64
+ const { connectDB } = require('../lib/db');
65
+ const User = require('../models/User');
66
+
67
+ module.exports = {
68
+ GET: async () => {
69
+ await connectDB();
70
+ const users = await User.find().select('-__v').lean();
71
+ return NextResponse.json(users);
72
+ },
73
+
74
+ POST: async (request) => {
75
+ const body = await request.json();
76
+ await connectDB();
77
+ const user = await User.create(body);
78
+ return NextResponse.json(user, { status: 201 });
79
+ },
80
+ };
81
+ ```
82
+
83
+ ### 5. `api/users/[id].js`
84
+
85
+ ```js
86
+ // api/users/[id].js
87
+ const { NextResponse } = require('../_framework/next-response');
88
+ const { connectDB } = require('../lib/db');
89
+ const User = require('../models/User');
90
+
91
+ module.exports = {
92
+ GET: async (request) => {
93
+ await connectDB();
94
+ const user = await User.findById(request.params.id);
95
+ if (!user) return NextResponse.json({ error: 'Not found' }, { status: 404 });
96
+ return NextResponse.json(user);
97
+ },
98
+
99
+ PUT: async (request) => {
100
+ const body = await request.json();
101
+ await connectDB();
102
+ const user = await User.findByIdAndUpdate(request.params.id, body, { new: true });
103
+ if (!user) return NextResponse.json({ error: 'Not found' }, { status: 404 });
104
+ return NextResponse.json(user);
105
+ },
106
+
107
+ DELETE: async (request) => {
108
+ await connectDB();
109
+ const user = await User.findByIdAndDelete(request.params.id);
110
+ if (!user) return NextResponse.json({ error: 'Not found' }, { status: 404 });
111
+ return NextResponse.json({ ok: true });
112
+ },
113
+ };
114
+ ```
115
+
116
+ ## Fetching from the browser
117
+
118
+ Use `api` or `useFetch`:
119
+
120
+ ```js
121
+ // declarative
122
+ const { data, loading, error } = useFetch('/api/users');
123
+
124
+ // imperative
125
+ async function addUser() {
126
+ await api.post('/api/users', { name: 'Aziz', email: 'aziz@example.com' });
127
+ }
128
+ ```
129
+
130
+ ## Other databases
131
+
132
+ You don't need to change anything. Use native drivers:
133
+
134
+ ```js
135
+ // lib/pg.js
136
+ const { Pool } = require('pg');
137
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL });
138
+ module.exports = { query: (text, params) => pool.query(text, params) };
139
+ ```
140
+
141
+ ## Hot reload & caching
142
+
143
+ Editing `lib/db.js` or `models/User.js` triggers server reload — the dev server purges project `require.cache` entries (excluding `node_modules`). Active DB connections may persist; keep your connection logic idempotent (`conn = null` singleton) as above.
144
+
145
+ ## Tips
146
+
147
+ - **Never** store DB credentials in browser files. Use environment variables (`.env`) and read them in API routes (`process.env.MONGODB_URI`). A future improvement could load `.env`, but today it's manual.
148
+ - **Return lean objects** (`.lean()`) to cut JSON overhead.
149
+ - **Validate input** — throw `Error` with `err.status = 400` on bad payloads.
150
+ - **Use transactions** for multi-step operations.
151
+
152
+ ## Continue
153
+
154
+ → [Authentication](./11-authentication.md)