odac 1.0.1 → 1.2.0
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/.agent/rules/coding.md +27 -0
- package/.agent/rules/memory.md +33 -0
- package/.agent/rules/project.md +30 -0
- package/.agent/rules/workflow.md +16 -0
- package/.github/workflows/auto-pr-description.yml +3 -1
- package/.github/workflows/release.yml +42 -1
- package/.github/workflows/test-coverage.yml +6 -5
- package/.github/workflows/test-publish.yml +36 -0
- package/.husky/pre-commit +10 -0
- package/.husky/pre-push +13 -0
- package/.releaserc.js +3 -3
- package/CHANGELOG.md +184 -0
- package/README.md +53 -34
- package/bin/odac.js +181 -49
- package/client/odac.js +878 -995
- package/docs/backend/01-overview/03-development-server.md +39 -46
- package/docs/backend/02-structure/01-typical-project-layout.md +59 -25
- package/docs/backend/03-config/00-configuration-overview.md +15 -6
- package/docs/backend/03-config/01-database-connection.md +3 -3
- package/docs/backend/03-config/02-static-route-mapping-optional.md +1 -1
- package/docs/backend/03-config/03-request-timeout.md +1 -1
- package/docs/backend/03-config/04-environment-variables.md +4 -4
- package/docs/backend/03-config/05-early-hints.md +2 -2
- package/docs/backend/04-routing/02-controller-less-view-routes.md +9 -3
- package/docs/backend/04-routing/03-api-and-data-routes.md +18 -0
- package/docs/backend/04-routing/07-cron-jobs.md +17 -1
- package/docs/backend/04-routing/09-websocket.md +29 -0
- package/docs/backend/05-controllers/01-how-to-build-a-controller.md +48 -3
- package/docs/backend/05-controllers/02-your-trusty-odac-assistant.md +2 -0
- package/docs/backend/05-controllers/03-controller-classes.md +61 -55
- package/docs/backend/05-forms/01-custom-forms.md +103 -95
- package/docs/backend/05-forms/02-automatic-database-insert.md +21 -21
- package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +17 -0
- package/docs/backend/07-views/02-rendering-a-view.md +1 -1
- package/docs/backend/07-views/03-variables.md +5 -5
- package/docs/backend/07-views/04-request-data.md +1 -1
- package/docs/backend/07-views/08-backend-javascript.md +1 -1
- package/docs/backend/07-views/10-styling-and-tailwind.md +93 -0
- package/docs/backend/08-database/01-getting-started.md +100 -0
- package/docs/backend/08-database/02-basics.md +136 -0
- package/docs/backend/08-database/03-advanced.md +84 -0
- package/docs/backend/08-database/04-migrations.md +48 -0
- package/docs/backend/09-validation/01-the-validator-service.md +1 -0
- package/docs/backend/10-authentication/03-register.md +9 -2
- package/docs/backend/10-authentication/04-odac-register-forms.md +48 -48
- package/docs/backend/10-authentication/05-session-management.md +16 -2
- package/docs/backend/10-authentication/06-odac-login-forms.md +50 -50
- package/docs/backend/10-authentication/07-magic-links.md +134 -0
- package/docs/backend/11-mail/01-the-mail-service.md +118 -28
- package/docs/backend/12-streaming/01-streaming-overview.md +2 -2
- package/docs/backend/13-utilities/01-odac-var.md +7 -7
- package/docs/backend/13-utilities/02-ipc.md +73 -0
- package/docs/frontend/01-overview/01-introduction.md +5 -1
- package/docs/frontend/02-ajax-navigation/01-quick-start.md +1 -1
- package/docs/index.json +21 -125
- package/eslint.config.mjs +5 -47
- package/jest.config.js +1 -1
- package/package.json +16 -7
- package/src/Auth.js +414 -121
- package/src/Config.js +12 -7
- package/src/Database.js +188 -0
- package/src/Env.js +3 -1
- package/src/Ipc.js +337 -0
- package/src/Lang.js +9 -2
- package/src/Mail.js +408 -37
- package/src/Odac.js +105 -40
- package/src/Request.js +71 -49
- package/src/Route/Cron.js +62 -18
- package/src/Route/Internal.js +215 -12
- package/src/Route/Middleware.js +7 -2
- package/src/Route.js +372 -109
- package/src/Server.js +118 -12
- package/src/Storage.js +169 -0
- package/src/Token.js +6 -4
- package/src/Validator.js +95 -3
- package/src/Var.js +22 -6
- package/src/View/EarlyHints.js +43 -33
- package/src/View/Form.js +210 -28
- package/src/View.js +108 -7
- package/src/WebSocket.js +18 -3
- package/template/odac.json +5 -0
- package/template/package.json +3 -1
- package/template/route/www.js +12 -10
- package/template/view/content/home.html +3 -3
- package/template/view/head/main.html +2 -2
- package/test/Client.test.js +168 -0
- package/test/Config.test.js +112 -0
- package/test/Lang.test.js +92 -0
- package/test/Odac.test.js +86 -0
- package/test/{framework/middleware.test.js → Route/Middleware.test.js} +2 -2
- package/test/{framework/Route.test.js → Route.test.js} +1 -1
- package/test/{framework/View → View}/EarlyHints.test.js +1 -1
- package/test/{framework/WebSocket.test.js → WebSocket.test.js} +2 -2
- package/test/scripts/check-coverage.js +4 -4
- package/docs/backend/08-database/01-database-connection.md +0 -99
- package/docs/backend/08-database/02-using-mysql.md +0 -322
- package/src/Mysql.js +0 -575
- package/template/config.json +0 -5
- package/test/cli/Cli.test.js +0 -36
- package/test/core/Candy.test.js +0 -234
- package/test/core/Commands.test.js +0 -538
- package/test/core/Config.test.js +0 -1432
- package/test/core/Lang.test.js +0 -250
- package/test/core/Process.test.js +0 -156
- package/test/server/Api.test.js +0 -647
- package/test/server/DNS.test.js +0 -2050
- package/test/server/DNS.test.js.bak +0 -2084
- package/test/server/Hub.test.js +0 -497
- package/test/server/Log.test.js +0 -73
- package/test/server/Mail.account.test_.js +0 -460
- package/test/server/Mail.init.test_.js +0 -411
- package/test/server/Mail.test_.js +0 -1340
- package/test/server/SSL.test_.js +0 -1491
- package/test/server/Server.test.js +0 -765
- package/test/server/Service.test_.js +0 -1127
- package/test/server/Subdomain.test.js +0 -440
- package/test/server/Web/Firewall.test.js +0 -175
- package/test/server/Web/Proxy.test.js +0 -397
- package/test/server/Web.test.js +0 -1494
- package/test/server/__mocks__/acme-client.js +0 -17
- package/test/server/__mocks__/bcrypt.js +0 -50
- package/test/server/__mocks__/child_process.js +0 -389
- package/test/server/__mocks__/crypto.js +0 -432
- package/test/server/__mocks__/fs.js +0 -450
- package/test/server/__mocks__/globalOdac.js +0 -227
- package/test/server/__mocks__/http.js +0 -575
- package/test/server/__mocks__/https.js +0 -272
- package/test/server/__mocks__/index.js +0 -249
- package/test/server/__mocks__/mail/server.js +0 -100
- package/test/server/__mocks__/mail/smtp.js +0 -31
- package/test/server/__mocks__/mailparser.js +0 -81
- package/test/server/__mocks__/net.js +0 -369
- package/test/server/__mocks__/node-forge.js +0 -328
- package/test/server/__mocks__/os.js +0 -320
- package/test/server/__mocks__/path.js +0 -291
- package/test/server/__mocks__/selfsigned.js +0 -8
- package/test/server/__mocks__/server/src/mail/server.js +0 -100
- package/test/server/__mocks__/server/src/mail/smtp.js +0 -31
- package/test/server/__mocks__/smtp-server.js +0 -106
- package/test/server/__mocks__/sqlite3.js +0 -394
- package/test/server/__mocks__/testFactories.js +0 -299
- package/test/server/__mocks__/testHelpers.js +0 -363
- package/test/server/__mocks__/tls.js +0 -229
|
@@ -1,79 +1,72 @@
|
|
|
1
|
-
## 🚀
|
|
1
|
+
## 🚀 CLI Commands & Deployment
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
ODAC comes with a powerful CLI to manage your project's lifecycle, from development to production.
|
|
4
4
|
|
|
5
|
-
###
|
|
5
|
+
### Development Mode (`dev`)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Start the development server with **hot-reloading** and **automatic Tailwind CSS compilation**:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
# Using npm script
|
|
11
|
-
npm
|
|
11
|
+
npm run dev
|
|
12
12
|
|
|
13
|
-
# Using
|
|
14
|
-
odac
|
|
13
|
+
# Using ODAC directly
|
|
14
|
+
npx odac dev
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
**What it does:**
|
|
18
|
+
- Starts the Node.js server (default port `1071`).
|
|
19
|
+
- **Zero-Config Tailwind:** Automatically watches and compiles your classes.
|
|
20
|
+
- **Watch Mode:** Recompiles CSS instantly when you change files.
|
|
18
21
|
|
|
19
|
-
###
|
|
22
|
+
### Production Build (`build`)
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
Prepare your application for production deployment. This command compiles and modifies your assets for optimal performance.
|
|
22
25
|
|
|
23
26
|
```bash
|
|
24
|
-
# Using npm script
|
|
25
|
-
npm
|
|
27
|
+
# Using npm script
|
|
28
|
+
npm run build
|
|
26
29
|
|
|
27
|
-
# Using
|
|
28
|
-
odac
|
|
30
|
+
# Using ODAC directly
|
|
31
|
+
npx odac build
|
|
29
32
|
```
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
**What it does:**
|
|
35
|
+
- **Compiles CSS:** Generates the final `public/assets/css/app.css`.
|
|
36
|
+
- **Minification:** Compresses the CSS to reduce file size.
|
|
37
|
+
- **One-off Run:** Runs once and exits. Does not start a server.
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
### Production Server (`start`)
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
- **Quick iteration** without server setup
|
|
39
|
-
- **Debugging** your application logic
|
|
40
|
-
- **Testing on localhost** (127.0.0.1)
|
|
41
|
-
|
|
42
|
-
**Important**: The development server does NOT provide DNS, SSL, or other production services.
|
|
43
|
-
|
|
44
|
-
For production deployment with full Odac server features, create your website using:
|
|
41
|
+
Start the application in **production mode**. This is the command you should run on your server or hosting platform.
|
|
45
42
|
|
|
46
43
|
```bash
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
# Using npm script
|
|
45
|
+
npm start
|
|
49
46
|
|
|
50
|
-
|
|
47
|
+
# Using ODAC directly
|
|
48
|
+
npx odac start
|
|
49
|
+
```
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
- **
|
|
56
|
-
- **Production optimizations** and security
|
|
51
|
+
**What it does:**
|
|
52
|
+
- Sets `NODE_ENV=production`.
|
|
53
|
+
- Starts the Node.js server.
|
|
54
|
+
- **No Overhead:** Does not run Tailwind watchers or dev tools. Simplicity and performance focused.
|
|
57
55
|
|
|
58
56
|
### Package.json Scripts
|
|
59
57
|
|
|
60
|
-
When you create a new
|
|
58
|
+
When you create a new ODAC project, your `package.json` comes pre-configured with these scripts:
|
|
61
59
|
|
|
62
60
|
```json
|
|
63
61
|
{
|
|
64
62
|
"scripts": {
|
|
65
|
-
"
|
|
66
|
-
"
|
|
63
|
+
"dev": "odac dev",
|
|
64
|
+
"build": "odac build",
|
|
65
|
+
"start": "odac start"
|
|
67
66
|
}
|
|
68
67
|
}
|
|
69
68
|
```
|
|
70
69
|
|
|
71
|
-
- `npm
|
|
72
|
-
- `npm
|
|
73
|
-
|
|
74
|
-
### Tips
|
|
75
|
-
|
|
76
|
-
- The development server automatically detects changes in your code
|
|
77
|
-
- Use `Ctrl+C` to stop the development server
|
|
78
|
-
- The server will show helpful error messages in the console
|
|
79
|
-
- All Odac framework features are available in development mode
|
|
70
|
+
- `npm run dev` - Your daily development command.
|
|
71
|
+
- `npm run build` - Run this before deploying (e.g., in CI/CD).
|
|
72
|
+
- `npm start` - The command that runs your live website.
|
|
@@ -2,36 +2,70 @@
|
|
|
2
2
|
|
|
3
3
|
Let's take a look at a typical project layout:
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
```
|
|
6
|
+
project/
|
|
7
|
+
├── class/ # Business logic classes (request-scoped)
|
|
8
|
+
│ ├── Payment.js
|
|
9
|
+
│ └── User.js
|
|
10
|
+
├── controller/ # HTTP request handlers
|
|
11
|
+
│ ├── api/ # API endpoint controllers
|
|
12
|
+
│ │ ├── auth.js
|
|
13
|
+
│ │ └── users.js
|
|
14
|
+
│ └── page/ # HTML page controllers
|
|
15
|
+
│ ├── about.js
|
|
16
|
+
│ └── home.js
|
|
17
|
+
├── middleware/ # Route middleware functions
|
|
18
|
+
│ └── auth.js
|
|
19
|
+
├── public/ # Static assets (directly accessible)
|
|
20
|
+
│ └── assets/
|
|
21
|
+
│ ├── css/
|
|
22
|
+
│ │ └── app.css # Auto-generated by Tailwind
|
|
23
|
+
│ ├── img/
|
|
24
|
+
│ └── js/
|
|
25
|
+
├── route/ # Route definitions (subdomain-based)
|
|
26
|
+
│ ├── api.js # Routes for api.example.com
|
|
27
|
+
│ └── www.js # Routes for www.example.com
|
|
28
|
+
├── storage/ # App storage (logs, cache, uploads)
|
|
29
|
+
│ └── .cache/
|
|
30
|
+
├── view/ # HTML templates
|
|
31
|
+
│ ├── content/
|
|
32
|
+
│ ├── css/ # (Optional) Custom Tailwind entry points
|
|
33
|
+
│ ├── footer/
|
|
34
|
+
│ ├── header/
|
|
35
|
+
│ └── skeleton/
|
|
36
|
+
├── .env # Environment variables (secrets, API keys)
|
|
37
|
+
├── odac.json # App configuration
|
|
38
|
+
└── package.json # Project metadata & npm scripts
|
|
39
|
+
```
|
|
21
40
|
|
|
22
|
-
|
|
23
|
-
# Start development server (default port 1071)
|
|
24
|
-
npm start
|
|
41
|
+
### 📁 Directory Breakdown
|
|
25
42
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
43
|
+
| Directory | Purpose |
|
|
44
|
+
|-----------|---------|
|
|
45
|
+
| `class/` | Request-scoped service classes for business logic |
|
|
46
|
+
| `controller/` | HTTP handlers that process requests and return responses |
|
|
47
|
+
| `middleware/` | Functions that run before controllers (auth, logging, etc.) |
|
|
48
|
+
| `route/` | Route definitions, one file per subdomain |
|
|
49
|
+
| `view/` | HTML templates and partials |
|
|
50
|
+
| `public/` | Static files served directly to browsers |
|
|
51
|
+
| `storage/` | Runtime data (cache, logs, file uploads) |
|
|
29
52
|
|
|
30
|
-
|
|
53
|
+
### CLI Commands
|
|
54
|
+
|
|
55
|
+
Your `package.json` includes scripts to manage your project lifecycle:
|
|
31
56
|
|
|
32
57
|
```bash
|
|
33
|
-
#
|
|
34
|
-
|
|
58
|
+
# STAGE 1: DEVELOPMENT
|
|
59
|
+
# Starts dev server with hot-reload & automatic Tailwind CSS
|
|
60
|
+
npm run dev
|
|
61
|
+
|
|
62
|
+
# STAGE 2: BUILD
|
|
63
|
+
# Compiles and optimizes assets (CSS) for production
|
|
64
|
+
npm run build
|
|
65
|
+
|
|
66
|
+
# STAGE 3: PRODUCTION
|
|
67
|
+
# Starts the optimized server
|
|
68
|
+
npm start
|
|
35
69
|
```
|
|
36
70
|
|
|
37
71
|
**Note**: For production websites with DNS and SSL, use `odac web create` to register with Odac server.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
## ⚙️ Configuration Overview
|
|
2
2
|
|
|
3
|
-
Odac uses a simple and flexible configuration system based on `
|
|
3
|
+
Odac uses a simple and flexible configuration system based on `odac.json` and optional `.env` files. You can choose the approach that best fits your needs.
|
|
4
4
|
|
|
5
5
|
### Configuration Files
|
|
6
6
|
|
|
7
|
-
####
|
|
7
|
+
#### odac.json (Required)
|
|
8
8
|
The main configuration file located in your website's root directory. This file contains all your application settings in JSON format.
|
|
9
9
|
|
|
10
10
|
```json
|
|
@@ -46,7 +46,7 @@ Perfect for development or non-sensitive settings:
|
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
#### 2. Environment Variables (Secure)
|
|
49
|
-
Use `${VARIABLE}` syntax in `
|
|
49
|
+
Use `${VARIABLE}` syntax in `odac.json` to reference `.env` values:
|
|
50
50
|
|
|
51
51
|
```json
|
|
52
52
|
{
|
|
@@ -101,7 +101,7 @@ const nodeEnv = process.env.NODE_ENV
|
|
|
101
101
|
### Best Practices
|
|
102
102
|
|
|
103
103
|
**Development:**
|
|
104
|
-
- Use direct values in `
|
|
104
|
+
- Use direct values in `odac.json` for quick setup
|
|
105
105
|
- Keep development credentials simple
|
|
106
106
|
|
|
107
107
|
**Production:**
|
|
@@ -111,7 +111,7 @@ const nodeEnv = process.env.NODE_ENV
|
|
|
111
111
|
- Copy `.env.example` to `.env` and fill in production values
|
|
112
112
|
|
|
113
113
|
**Version Control:**
|
|
114
|
-
- Commit `
|
|
114
|
+
- Commit `odac.json` with `${VARIABLE}` placeholders
|
|
115
115
|
- Commit `.env.example` with dummy values
|
|
116
116
|
- Never commit `.env` with real credentials
|
|
117
117
|
|
|
@@ -161,13 +161,22 @@ const nodeEnv = process.env.NODE_ENV
|
|
|
161
161
|
}
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
+
**Debug Mode:**
|
|
165
|
+
Enable verbose logging for development. This helps in troubleshooting by inspecting detailed logs for system actions like sending emails (e.g., SMTP connection details, server responses). Default is `false`.
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"debug": true
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
164
173
|
Early Hints is a performance optimization feature that works automatically without any configuration. The server sends preliminary HTTP headers to the browser before the final response, allowing browsers to start preloading critical resources (CSS, JavaScript, fonts) earlier. This is completely zero-config - it detects resources from your HTML automatically and sends hints on subsequent requests.
|
|
165
174
|
|
|
166
175
|
See individual documentation sections for detailed configuration options.
|
|
167
176
|
|
|
168
177
|
### Example Setup
|
|
169
178
|
|
|
170
|
-
**
|
|
179
|
+
**odac.json** (committed to git):
|
|
171
180
|
```json
|
|
172
181
|
{
|
|
173
182
|
"request": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
## 🔌 Database Connection
|
|
2
2
|
|
|
3
|
-
When you add a `mysql` object to your `
|
|
3
|
+
When you add a `mysql` object to your `odac.json`, the system will automatically connect to your MySQL database. No separate connection setup is needed in your code.
|
|
4
4
|
|
|
5
5
|
### Basic Configuration
|
|
6
6
|
|
|
@@ -15,13 +15,13 @@ When you add a `mysql` object to your `config.json`, the system will automatical
|
|
|
15
15
|
}
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Once this is configured, you can directly use `Odac.
|
|
18
|
+
Once this is configured, you can directly use `Odac.DB` commands to run queries.
|
|
19
19
|
|
|
20
20
|
### Using Environment Variables
|
|
21
21
|
|
|
22
22
|
For better security, especially in production, you can use environment variables for sensitive information:
|
|
23
23
|
|
|
24
|
-
**
|
|
24
|
+
**odac.json:**
|
|
25
25
|
```json
|
|
26
26
|
{
|
|
27
27
|
"mysql": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
## 🗺️ Static Route Mapping (Optional)
|
|
2
2
|
|
|
3
|
-
Normally, all publicly served files should be in your `public` folder. However, if you need to expose a specific file from somewhere else on your server, you can use the optional `route` object in your `
|
|
3
|
+
Normally, all publicly served files should be in your `public` folder. However, if you need to expose a specific file from somewhere else on your server, you can use the optional `route` object in your `odac.json`. This creates a direct mapping from a URL path to that file.
|
|
4
4
|
|
|
5
5
|
```json
|
|
6
6
|
"route": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
## ⏱️ Request Timeout
|
|
2
2
|
|
|
3
|
-
You can configure the global timeout for incoming requests by adding a `request` object to your `
|
|
3
|
+
You can configure the global timeout for incoming requests by adding a `request` object to your `odac.json`.
|
|
4
4
|
|
|
5
5
|
```json
|
|
6
6
|
"request": {
|
|
@@ -4,7 +4,7 @@ Odac supports environment variables through `.env` files, making it easy to mana
|
|
|
4
4
|
|
|
5
5
|
### Creating a .env File
|
|
6
6
|
|
|
7
|
-
Create a `.env` file in your website's root directory (same location as `
|
|
7
|
+
Create a `.env` file in your website's root directory (same location as `odac.json`):
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
# .env
|
|
@@ -37,7 +37,7 @@ FEATURE_BETA=true
|
|
|
37
37
|
MAINTENANCE_MODE=false
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
### Using in
|
|
40
|
+
### Using in odac.json
|
|
41
41
|
|
|
42
42
|
Reference environment variables using `${VARIABLE_NAME}` syntax:
|
|
43
43
|
|
|
@@ -91,7 +91,7 @@ module.exports = function() {
|
|
|
91
91
|
}
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
#### 3. From Odac.Config (if defined in
|
|
94
|
+
#### 3. From Odac.Config (if defined in odac.json)
|
|
95
95
|
|
|
96
96
|
```javascript
|
|
97
97
|
module.exports = function() {
|
|
@@ -222,6 +222,6 @@ MAIL_FROM='noreply@example.com'
|
|
|
222
222
|
|
|
223
223
|
- Environment variables are loaded when the application starts
|
|
224
224
|
- Changes to `.env` require restarting the application
|
|
225
|
-
- The `.env` file is **optional** - you can use direct values in `
|
|
225
|
+
- The `.env` file is **optional** - you can use direct values in `odac.json` if preferred
|
|
226
226
|
- Variables defined in `.env` are available throughout your entire application
|
|
227
227
|
- If a variable is not found, `Odac.env()` returns the default value or `undefined`
|
|
@@ -54,7 +54,7 @@ Same flow - hints are sent from the manifest immediately.
|
|
|
54
54
|
|
|
55
55
|
## Configuration (Optional)
|
|
56
56
|
|
|
57
|
-
While Early Hints works automatically, you can customize it in `
|
|
57
|
+
While Early Hints works automatically, you can customize it in `odac.json`:
|
|
58
58
|
|
|
59
59
|
```json
|
|
60
60
|
{
|
|
@@ -329,7 +329,7 @@ Reduce `maxResources` in config:
|
|
|
329
329
|
|
|
330
330
|
## Disabling Early Hints
|
|
331
331
|
|
|
332
|
-
Removing the `earlyHints` configuration section from your `
|
|
332
|
+
Removing the `earlyHints` configuration section from your `odac.json` is equivalent to using the default settings, which has the feature enabled. To truly disable Early Hints, you must explicitly set `enabled: false` in your configuration:
|
|
333
333
|
|
|
334
334
|
```json
|
|
335
335
|
{
|
|
@@ -3,18 +3,24 @@
|
|
|
3
3
|
For simple pages that don't require complex logic in a controller, you can render a view directly from your route file by passing a view configuration object as the second parameter.
|
|
4
4
|
|
|
5
5
|
#### `page(path, { ... })`
|
|
6
|
-
This defines a page and immediately tells it which view components to render.
|
|
6
|
+
This defines a page and immediately tells it which view components to render. You can also pass variables directly in the object, which will be available in your views.
|
|
7
7
|
|
|
8
8
|
```javascript
|
|
9
9
|
Odac.Route.page("/users", {
|
|
10
|
+
// View Configuration
|
|
10
11
|
skeleton: "dashboard",
|
|
11
12
|
header: "dashboard.main",
|
|
12
13
|
sidebar: "dashboard.main",
|
|
13
14
|
footer: "dashboard.main",
|
|
14
|
-
content: "users"
|
|
15
|
+
content: "users",
|
|
16
|
+
|
|
17
|
+
// Page Variables
|
|
18
|
+
title: "User Management",
|
|
19
|
+
description: "Manage your platform users here"
|
|
15
20
|
});
|
|
16
21
|
```
|
|
17
|
-
|
|
22
|
+
|
|
23
|
+
This example tells Odac to render the `/users` page using the `dashboard` skeleton. Additionally, `title` and `description` are set as variables and can be accessed in your views using `<odac var="title" />`.
|
|
18
24
|
|
|
19
25
|
**Page Identifier:** When using view objects, the page identifier (accessible via `Odac.page()` in frontend) is automatically set to the `content` or `all` value. In this example, the page identifier would be `"users"`, allowing you to run page-specific JavaScript:
|
|
20
26
|
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
## 📦 API and Data Routes
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
#### Class-Based Route Definition (Recommended)
|
|
5
|
+
|
|
6
|
+
You can route requests to specific methods within a Controller Class using the `ClassName@methodName` syntax. This allows you to group related logic in a single file clearly.
|
|
7
|
+
|
|
8
|
+
```javascript
|
|
9
|
+
// Calls the 'index' method of the class exported in controller/User.js
|
|
10
|
+
Odac.Route.get('/users', 'User@index');
|
|
11
|
+
|
|
12
|
+
// Calls the 'store' method of the class exported in controller/User.js
|
|
13
|
+
Odac.Route.post('/users', 'User@store');
|
|
14
|
+
|
|
15
|
+
// You can also use dot notation for controllers in subdirectories
|
|
16
|
+
// controller/Admin/Dashboard.js -> Admin.Dashboard
|
|
17
|
+
Odac.Route.get('/admin', 'Admin.Dashboard@index');
|
|
18
|
+
```
|
|
19
|
+
|
|
3
20
|
#### `get(path, controller, options)`
|
|
4
21
|
Defines a route that responds to `GET` requests. This is ideal for API endpoints that return data (like JSON).
|
|
5
22
|
|
|
@@ -18,3 +35,4 @@ Defines a route that responds to `POST` requests, typically used for form submis
|
|
|
18
35
|
// A form that posts data to /login
|
|
19
36
|
Odac.Route.post('/login', 'auth.login');
|
|
20
37
|
```
|
|
38
|
+
|
|
@@ -79,6 +79,9 @@ Odac.Route.cron('task')
|
|
|
79
79
|
// Day (1-31)
|
|
80
80
|
.day(15) // On the 15th of the month
|
|
81
81
|
|
|
82
|
+
// At Specific Time (HH:MM)
|
|
83
|
+
.at('14:30') // At 14:30 (Shorthand for .hour(14).minute(30))
|
|
84
|
+
|
|
82
85
|
// Week day (0-6, 0=Sunday)
|
|
83
86
|
.weekDay(1) // On Monday
|
|
84
87
|
|
|
@@ -114,6 +117,18 @@ Odac.Route.cron('periodic')
|
|
|
114
117
|
|
|
115
118
|
// Every N years
|
|
116
119
|
.everyYear(1) // Every year
|
|
120
|
+
|
|
121
|
+
## Raw Cron Expression
|
|
122
|
+
You can use standard UNIX cron expressions (Minute Hour Day Month WeekDay) using the `.raw()` method.
|
|
123
|
+
Supported formats for each field: `*`, `*/n` (interval), `n` (exact match).
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
// Run every 15 minutes
|
|
127
|
+
Odac.Route.cron('quarter-task').raw('*\/15 * * * *')
|
|
128
|
+
|
|
129
|
+
// Run at 14:30 on Mondays
|
|
130
|
+
Odac.Route.cron('weekly-meeting').raw('30 14 * * 1')
|
|
131
|
+
```
|
|
117
132
|
```
|
|
118
133
|
|
|
119
134
|
## Combination Usage
|
|
@@ -146,4 +161,5 @@ Odac.Route.cron('monthly-cleanup')
|
|
|
146
161
|
- If the same job is defined multiple times, the last definition takes precedence
|
|
147
162
|
- Controller files are re-required on each execution
|
|
148
163
|
- Inline functions are stored in memory and executed directly
|
|
149
|
-
- If a job fails, it stops but the system continues
|
|
164
|
+
- If a job fails, it stops but the system continues
|
|
165
|
+
- **CRITICAL:** Missing conditions act as wildcards (`*`). If you specify `.hour(14)` but omit `.minute()`, the task will run **every minute** between 14:00 and 14:59. Always specify smaller units (minute) to pin execution to a single point in time. Use `.at('14:00')` to safely set both hour and minute.
|
|
@@ -45,6 +45,35 @@ web/
|
|
|
45
45
|
│ └── websocket.js # WebSocket routes (recommended)
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
### Using Controllers
|
|
49
|
+
|
|
50
|
+
You can also specify a connector file as a string. Odac will look for the file in `controller/ws/`.
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
// route/websocket.js
|
|
54
|
+
Odac.Route.ws('/chat', 'ChatController')
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**File Structure:**
|
|
58
|
+
```
|
|
59
|
+
web/
|
|
60
|
+
├── controller/
|
|
61
|
+
│ └── ws/
|
|
62
|
+
│ └── ChatController.js
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Controller File:**
|
|
66
|
+
```javascript
|
|
67
|
+
// controller/ws/ChatController.js
|
|
68
|
+
module.exports = Odac => {
|
|
69
|
+
Odac.ws.send({type: 'welcome'})
|
|
70
|
+
|
|
71
|
+
Odac.ws.on('message', data => {
|
|
72
|
+
// ...
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
48
77
|
## WebSocket Client API (Odac.ws)
|
|
49
78
|
|
|
50
79
|
The WebSocket client is accessible via `Odac.ws` in your handler, providing a consistent API pattern with HTTP routes.
|
|
@@ -1,8 +1,52 @@
|
|
|
1
1
|
## 🏗️ How to Build a Controller
|
|
2
2
|
|
|
3
|
-
A controller is just a JavaScript module that exports a function. This function automatically gets the magical `Odac` context object we talked about in the overview.
|
|
3
|
+
A controller is just a JavaScript module that exports a function or a Class. This function automatically gets the magical `Odac` context object we talked about in the overview.
|
|
4
4
|
|
|
5
|
-
####
|
|
5
|
+
#### Class-Based Controllers (Professional & Recommended)
|
|
6
|
+
|
|
7
|
+
For professional applications, we **strongly recommend** using Class-Based Controllers. This approach allows you to group related actions (like all User-related or Product-related logic) into a single file in the `controller/` directory, keeping your project organized.
|
|
8
|
+
|
|
9
|
+
**Example: `controller/User.js`**
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
class User {
|
|
13
|
+
// Access this via 'User@index'
|
|
14
|
+
index(Odac) {
|
|
15
|
+
return Odac.View.make('user.list', {
|
|
16
|
+
title: 'User List'
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Access this via 'User@show'
|
|
21
|
+
show(Odac) {
|
|
22
|
+
const id = Odac.Request.input('id')
|
|
23
|
+
// Fetch user logic...
|
|
24
|
+
return Odac.return({ id: id, name: 'John Doe' })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Access this via 'User@store'
|
|
28
|
+
store(Odac) {
|
|
29
|
+
// Save user logic...
|
|
30
|
+
return Odac.return({ success: true })
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = User
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
When using this structure, you define your routes using the `ControllerName@MethodName` syntax:
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
Odac.Route.get('/users', 'User@index')
|
|
41
|
+
Odac.Route.get('/users/{id}', 'User@show')
|
|
42
|
+
Odac.Route.post('/users', 'User@store')
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The framework automatically instantiates your Controller class and calls the specified method with the `Odac` instance passed as an argument.
|
|
46
|
+
|
|
47
|
+
#### specific Function Controllers (Basic)
|
|
48
|
+
|
|
49
|
+
For very simple or single-purpose routes, you can export a single function.
|
|
6
50
|
|
|
7
51
|
Check out this basic example from `controller/page/index.js`:
|
|
8
52
|
|
|
@@ -14,4 +58,5 @@ module.exports = function (Odac) {
|
|
|
14
58
|
}
|
|
15
59
|
```
|
|
16
60
|
|
|
17
|
-
This
|
|
61
|
+
This simple function is responsible for handling the homepage route (`/`). When it runs, it just sends a simple string back to the user's browser.
|
|
62
|
+
|
|
@@ -14,6 +14,8 @@ Remember the `Odac` object? It's your best friend inside a controller. It's pass
|
|
|
14
14
|
|
|
15
15
|
* `Odac.return(data)`: Send back a response.
|
|
16
16
|
* `Odac.direct(url)`: Redirect the user to a new page.
|
|
17
|
+
* `Odac.set(key, value)`: Pass variables to your View template.
|
|
18
|
+
* `Odac.share(key, value)`: Share data directly with frontend JavaScript (`odac.data()`).
|
|
17
19
|
* `Odac.cookie(key, value)`: Set a browser cookie.
|
|
18
20
|
* `Odac.validator()`: Check user input easily.
|
|
19
21
|
* `Odac.setInterval(callback, delay)`: Schedule repeating tasks (auto-cleanup).
|