odac 1.0.0 → 1.1.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/.github/workflows/auto-pr-description.yml +3 -1
- package/CHANGELOG.md +127 -0
- package/README.md +39 -36
- package/bin/odac.js +1 -31
- package/client/odac.js +871 -994
- package/docs/backend/01-overview/03-development-server.md +7 -7
- package/docs/backend/02-structure/01-typical-project-layout.md +1 -0
- package/docs/backend/03-config/00-configuration-overview.md +9 -0
- package/docs/backend/03-config/01-database-connection.md +1 -1
- package/docs/backend/04-routing/02-controller-less-view-routes.md +9 -3
- package/docs/backend/04-routing/09-websocket.md +29 -0
- package/docs/backend/05-controllers/02-your-trusty-odac-assistant.md +2 -0
- package/docs/backend/05-controllers/03-controller-classes.md +27 -41
- 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/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/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 +8 -1
- package/docs/backend/10-authentication/04-odac-register-forms.md +46 -46
- package/docs/backend/10-authentication/05-session-management.md +1 -1
- package/docs/backend/10-authentication/06-odac-login-forms.md +48 -48
- 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 +16 -124
- package/eslint.config.mjs +5 -47
- package/package.json +9 -4
- package/src/Auth.js +362 -104
- package/src/Config.js +7 -2
- package/src/Database.js +188 -0
- package/src/Ipc.js +330 -0
- package/src/Mail.js +408 -37
- package/src/Odac.js +65 -9
- package/src/Request.js +70 -48
- package/src/Route/Cron.js +4 -1
- package/src/Route/Internal.js +214 -11
- package/src/Route/Middleware.js +7 -2
- package/src/Route.js +106 -26
- package/src/Server.js +80 -11
- package/src/Storage.js +165 -0
- package/src/Validator.js +94 -2
- package/src/View/Form.js +193 -17
- package/src/View.js +46 -1
- package/src/WebSocket.js +18 -3
- package/template/config.json +1 -1
- package/template/route/www.js +12 -10
- package/test/core/{Candy.test.js → Odac.test.js} +2 -2
- 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
|
@@ -35,6 +35,8 @@ jobs:
|
|
|
35
35
|
|
|
36
36
|
- name: Update PR Title and Body
|
|
37
37
|
uses: actions/github-script@v7
|
|
38
|
+
env:
|
|
39
|
+
PR_BODY: ${{ steps.generate_body.outputs.body }}
|
|
38
40
|
with:
|
|
39
41
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
40
42
|
script: |
|
|
@@ -43,5 +45,5 @@ jobs:
|
|
|
43
45
|
repo: context.repo.repo,
|
|
44
46
|
pull_number: context.issue.number,
|
|
45
47
|
title: 'Sync `dev` to `main`',
|
|
46
|
-
body:
|
|
48
|
+
body: process.env.PR_BODY
|
|
47
49
|
});
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,130 @@
|
|
|
1
|
+
### Fix
|
|
2
|
+
|
|
3
|
+
- Resolve WebSocket handshake error by echoing subprotocol header
|
|
4
|
+
|
|
5
|
+
### Refactor
|
|
6
|
+
|
|
7
|
+
- Unified WebSocket architecture and fixed race conditions
|
|
8
|
+
|
|
9
|
+
### deps
|
|
10
|
+
|
|
11
|
+
- update mysql2 dependency to ^3.16.0
|
|
12
|
+
|
|
13
|
+
### ⚙️ Engine Tuning
|
|
14
|
+
|
|
15
|
+
- Add type checks for page assignments and a null check for the `authPage` method's `authFile` parameter.
|
|
16
|
+
- extract and trim validation rule names for clearer inverse rule processing.
|
|
17
|
+
- extract HTML stripping logic into a private helper method and apply it to text content generation.
|
|
18
|
+
- migrate custom `odac:field` tag to `odac:input` with updated parsing logic and regex patterns.
|
|
19
|
+
- migrate session locking from in-memory object to `Odac.Storage` for persistence.
|
|
20
|
+
- Move form message clearing logic to the beginning of form submission.
|
|
21
|
+
- move middleware execution to occur after URL parameter processing.
|
|
22
|
+
- pass PR body to github-script action via environment variable
|
|
23
|
+
- Remove duplicate data-error-email attribute assignment.
|
|
24
|
+
- rename `requestMagicLink` method to `magic` in Auth and update its usages and documentation
|
|
25
|
+
- Rename authentication token and session cookie keys from 'candy' to 'odac'.
|
|
26
|
+
- rename internal `Odac` class to `_odac`
|
|
27
|
+
- Rename Mysql to Database and implement connection pooling
|
|
28
|
+
- Update default magic link table name from 'magic_links' to 'odac_magic'.
|
|
29
|
+
- Use `crypto.randomBytes` for client and session ID generation instead of MD5 hashing.
|
|
30
|
+
- use `node:crypto.randomBytes` for generating unique IDs instead of `Date.now()` and `Math.random()`
|
|
31
|
+
- use file descriptor for mail template reading to ensure resource closure
|
|
32
|
+
|
|
33
|
+
### ✨ What's New
|
|
34
|
+
|
|
35
|
+
- add `_odac/form` POST route with CSRF token validation
|
|
36
|
+
- Add `!disposable` validation rule to block temporary email providers by fetching and caching a daily updated blocklist.
|
|
37
|
+
- Add console error for missing controller files
|
|
38
|
+
- Add custom template rendering engine with caching to Mail service and enhance magic link email options.
|
|
39
|
+
- Add magic link rate limiting, expired link cleanup, and open redirect protection for magic link redirects.
|
|
40
|
+
- add passwordless auto-registration for magic links, improve URL query decoding, and disable token validation for the magic link verification route.
|
|
41
|
+
- Add request language property from Accept-Language header, defaulting to 'en'.
|
|
42
|
+
- Add session cooldown for magic link requests and return explicit errors for rate limits, updating documentation.
|
|
43
|
+
- Allow direct page route definition when a file is provided.
|
|
44
|
+
- Allow specifying and using a redirect URL for magic link authentication.
|
|
45
|
+
- emit 'ping' event when receiving a WebSocket PING frame
|
|
46
|
+
- Enable passing variables directly in view configuration objects for page routes and update documentation.
|
|
47
|
+
- Enable sending plain text and raw HTML emails without templates in the mail service.
|
|
48
|
+
- HTML Mail delivery via direct ODAC Mail Server
|
|
49
|
+
- Ignore database table not found errors when looking up users by email.
|
|
50
|
+
- Implement and document auto-clearing of form inputs on successful submission, controllable via a `clear` attribute.
|
|
51
|
+
- Implement backend-to-frontend data sharing via `Odac.share` and…
|
|
52
|
+
- implement built-in IPC system with Memory and Redis drivers
|
|
53
|
+
- Implement dynamic session garbage collection with simple and batch cleaning modes based on session count.
|
|
54
|
+
- Implement graceful shutdown for primary and worker processes in the cluster.
|
|
55
|
+
- Implement magic login functionality
|
|
56
|
+
- Implement magic login functionality with new routes, internal handlers, and form processing, while removing a generic form route.
|
|
57
|
+
- Implement passwordless signup by auto-registering new users during magic link verification and adding `node:crypto` for random password generation.
|
|
58
|
+
- Implement server actions for forms, allowing `Controller.method` as the action and dispatching internally via a generic endpoint.
|
|
59
|
+
- introduce `Odac.DB.nanoid()` helper, centralize its implementation, and update authentication ID generation strategy documentation.
|
|
60
|
+
- Introduce Nano IDs for primary keys and cookie identifiers, streamlining user insertion logic.
|
|
61
|
+
- introduce service classes in a dedicated directory with naming collision handling and refine route authentication logic.
|
|
62
|
+
- Introduce Storage module to encapsulate LMDB operations and session garbage collection.
|
|
63
|
+
- Migrate session management from in-memory to LMDB, enable server clustering, and add session garbage collection.
|
|
64
|
+
- Modernize db layer with magic api and migrations
|
|
65
|
+
- Modernize db layer with magic api and migrations
|
|
66
|
+
- Render form success and error messages as HTML using a new `textToHtml` utility.
|
|
67
|
+
- Return generic success message for user not found when auto-register is enabled to prevent enumeration.
|
|
68
|
+
- Server Clustering & Persistent Session Management
|
|
69
|
+
- support string-based WebSocket controller paths and update documentation
|
|
70
|
+
- Update route loading to execute function-exported route definitions with Odac.
|
|
71
|
+
- Update session private key hashing algorithm from MD5 to SHA256.
|
|
72
|
+
|
|
73
|
+
### 📚 Documentation
|
|
74
|
+
|
|
75
|
+
- Add magic links documentation.
|
|
76
|
+
- Fix typo in controller classes documentation
|
|
77
|
+
- overhaul README to detail new Node.js framework features, advanced capabilities, updated quick start instructions, and license.
|
|
78
|
+
- remove redundant html code block tag
|
|
79
|
+
- remove server documentation index.
|
|
80
|
+
- Replace old database connection and MySQL guides with new getting started, query basics, advanced queries, and migrations documentation.
|
|
81
|
+
- Standardize framework name capitalization from Odac to ODAC across documentation.
|
|
82
|
+
- Update database interaction examples from `Odac.Mysql` to `Odac.DB`.
|
|
83
|
+
- update database query examples to include `.select()` and variable assignments.
|
|
84
|
+
|
|
85
|
+
### 🛠️ Fixes & Improvements
|
|
86
|
+
|
|
87
|
+
- Add error handling for cache file access to ensure validation update proceeds.
|
|
88
|
+
- Add explicit response termination for middleware and redirects, and pass page file path to request.
|
|
89
|
+
- Adjust session key counting range
|
|
90
|
+
- Consume all magic link tokens for an email instead of just the used one to prevent reuse.
|
|
91
|
+
- Correct `odac` special variable path resolution by removing `/src` instead of `/framework/src`.
|
|
92
|
+
- Enable `MiddlewareChain` to automatically use auth handlers when created via `Route.auth.use`.
|
|
93
|
+
- Ensure all HTML tags are recursively stripped when converting HTML to plain text.
|
|
94
|
+
- Ignore `data:` and `vbscript:` pseudo-protocols when processing anchor hrefs.
|
|
95
|
+
- Implement form token rotation on successful form submission without redirect and update client-side form with the new token.
|
|
96
|
+
- Initialize cron interval only in the primary cluster process.
|
|
97
|
+
- Introduce `setSession` method for client ID initialization and optimize internal session and cookie storage.
|
|
98
|
+
- log errors when ensuring the magic link table exists instead of ignoring them
|
|
99
|
+
- Log Odac Auth errors when ensuring token table exists instead of ignoring them.
|
|
100
|
+
- Prevent navigation to `data:` and `vbscript:` URLs.
|
|
101
|
+
- re-register form submit handler when its `data-odac-form` attribute changes to ensure correct event capture.
|
|
102
|
+
- recursively strip nested script and style tags when sanitizing HTML
|
|
103
|
+
- Relax sameSite cookie policy to Lax and refactor redirect handling.
|
|
104
|
+
- remove all socket listeners when closing or disconnecting the WebSocket.
|
|
105
|
+
- Remove early exit from token hash check loop to mitigate timing attacks.
|
|
106
|
+
- return non-function default connection properties directly instead of attempting to bind them
|
|
107
|
+
- return registration error on unique check failure.
|
|
108
|
+
- Robustly extract multipart boundary from request body.
|
|
109
|
+
- serve static files via `createReadStream` and pipe streamable content to response.
|
|
110
|
+
- Validate error route cache handler is a function in Request abort method.
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
Powered by [⚡ ODAC](https://odac.run)
|
|
117
|
+
|
|
118
|
+
### 🛠️ Fixes & Improvements
|
|
119
|
+
|
|
120
|
+
- Simplify project initialization by removing directory emptiness validation and extraneous comments.
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
Powered by [⚡ ODAC](https://odac.run)
|
|
127
|
+
|
|
1
128
|
### Framework
|
|
2
129
|
|
|
3
130
|
- HTML Email
|
package/README.md
CHANGED
|
@@ -1,57 +1,60 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="https://odac.run/assets/img/github/header.png?v=1" alt="Odac Header">
|
|
3
|
-
</p>
|
|
4
1
|
|
|
5
|
-
# ⚡
|
|
2
|
+
# ⚡ ODAC.JS
|
|
6
3
|
|
|
7
|
-
**
|
|
4
|
+
**ODAC** is a lightweight, high-performance Node.js framework designed to build modern, scalable web applications with ease. It allows developers to focus on building features rather than configuring boilerplate, offering a complete toolkit for web development.
|
|
8
5
|
|
|
9
6
|
## ✨ Key Features
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
|
|
8
|
+
* 🚀 **Developer Friendly:** Simple setup and intuitive API design let you start building immediately.
|
|
9
|
+
* 🔗 **Powerful Routing:** Create clean, custom URLs and manage infinite pages with a flexible routing system.
|
|
10
|
+
* ✨ **Seamless SPA Experience:** Automatic AJAX handling for forms and page transitions eliminates the need for complex client-side code.
|
|
11
|
+
* 🛡️ **Built-in Security:** Automatic CSRF protection and secure default headers keep your application safe.
|
|
12
|
+
* 🔐 **Authentication:** Ready-to-use session management, password hashing, and authentication helpers.
|
|
13
|
+
* 🗄️ **Database Agnostic:** Integrated support for major databases (PostgreSQL, MySQL, SQLite) and Redis via Knex.js.
|
|
14
|
+
* 🌍 **i18n Support:** Native multi-language support to help you reach a global audience.
|
|
15
|
+
* ⏰ **Task Scheduling:** Built-in Cron job system for handling background tasks and recurring operations.
|
|
16
|
+
|
|
17
|
+
## 🛠️ Advanced Capabilities
|
|
18
|
+
|
|
19
|
+
### ⚡ Cluster-Ready IPC
|
|
20
|
+
Built for scale from day one, ODAC includes a powerful Inter-Process Communication (IPC) system.
|
|
21
|
+
* **Unified API:** Use the same `get`, `set`, `publish`, and `subscribe` methods regardless of the underlying driver.
|
|
22
|
+
* **Zero-Config Clustering:** The default `memory` driver automatically syncs data between Node.js cluster workers without external dependencies.
|
|
23
|
+
* **Redis Support:** Switch to the `redis` driver with a single config change to scale horizontally across multiple servers.
|
|
24
|
+
|
|
25
|
+
### 🔌 Native WebSocket Support
|
|
26
|
+
Real-time features are a first-class citizen in ODAC.
|
|
27
|
+
* **Integrated Server:** No need for third-party libraries; ODAC features a lightweight, native WebSocket implementation.
|
|
28
|
+
* **Room System:** Easily manage user groups with built-in `join`, `leave`, and `broadcast` to room functionality.
|
|
29
|
+
* **Route Integration:** define WebSocket endpoints directly in your router alongside HTTP routes.
|
|
30
|
+
|
|
31
|
+
### 🎨 Powerful Templating
|
|
32
|
+
ODAC's view engine combines the power of JavaScript with intuitive HTML tags.
|
|
33
|
+
* **Logic Tags:** Use `<odac:if>`, `<odac:for>`, and `<odac:else>` for clean control flow.
|
|
34
|
+
* **Async Support:** Fully asynchronous rendering allows fetching data directly within your views using `await`.
|
|
35
|
+
* **Safety:** Automatic escaping prevents XSS while allowing raw HTML output when explicitly requested.
|
|
28
36
|
|
|
29
37
|
## 🚀 Quick Start
|
|
30
38
|
|
|
31
|
-
|
|
39
|
+
Get your new ODAC project up and running in seconds using our CLI.
|
|
32
40
|
|
|
33
|
-
|
|
41
|
+
### Create a new project
|
|
34
42
|
|
|
35
43
|
```bash
|
|
36
|
-
|
|
44
|
+
npx odac init my-app
|
|
37
45
|
```
|
|
38
46
|
|
|
39
|
-
|
|
47
|
+
### Start development
|
|
40
48
|
|
|
41
|
-
```
|
|
42
|
-
|
|
49
|
+
```bash
|
|
50
|
+
cd my-app
|
|
51
|
+
npm run dev
|
|
43
52
|
```
|
|
44
53
|
|
|
45
|
-
This command:
|
|
46
|
-
|
|
47
|
-
- Installs Node.js (v18+) if missing
|
|
48
|
-
- Installs Odac globally via npm
|
|
49
|
-
- Prepares your system for development or deployment
|
|
50
|
-
|
|
51
54
|
## 📚 Documentation
|
|
52
55
|
|
|
53
|
-
For
|
|
56
|
+
For detailed guides, API references, and examples, visit our [official documentation](https://docs.odac.run).
|
|
54
57
|
|
|
55
58
|
## 📄 License
|
|
56
59
|
|
|
57
|
-
This project is licensed under the
|
|
60
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
package/bin/odac.js
CHANGED
|
@@ -20,31 +20,14 @@ async function run() {
|
|
|
20
20
|
const projectName = args[0] || '.'
|
|
21
21
|
const targetDir = path.resolve(process.cwd(), projectName)
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
if (fs.existsSync(targetDir)) {
|
|
25
|
-
const files = fs.readdirSync(targetDir)
|
|
26
|
-
const isNotEmpty = files.some(file =>
|
|
27
|
-
!['.git', '.DS_Store', '.gitignore', '.idea', '.vscode'].includes(file)
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
if (isNotEmpty) {
|
|
31
|
-
console.error(`❌ Error: Directory "${projectName === '.' ? 'Current directory' : projectName}" is not empty.`)
|
|
32
|
-
console.error(' Please run in an empty directory or specify a new project name.')
|
|
33
|
-
process.exit(1)
|
|
34
|
-
}
|
|
35
|
-
} else {
|
|
36
|
-
fs.mkdirSync(targetDir, { recursive: true })
|
|
37
|
-
}
|
|
23
|
+
if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true })
|
|
38
24
|
|
|
39
|
-
// 4. Copy Template
|
|
40
25
|
console.log(`🚀 Initializing new Odac project in: ${targetDir}`)
|
|
41
26
|
const templateDir = path.resolve(__dirname, '../template')
|
|
42
27
|
|
|
43
28
|
try {
|
|
44
|
-
// Recursive copy
|
|
45
29
|
fs.cpSync(templateDir, targetDir, { recursive: true })
|
|
46
30
|
|
|
47
|
-
// Update package.json
|
|
48
31
|
const pkgPath = path.join(targetDir, 'package.json')
|
|
49
32
|
const frameworkPkg = require('../package.json')
|
|
50
33
|
|
|
@@ -52,7 +35,6 @@ async function run() {
|
|
|
52
35
|
pkg.name = projectName === '.' ? path.basename(targetDir) : projectName
|
|
53
36
|
pkg.version = '0.0.1'
|
|
54
37
|
|
|
55
|
-
// Inject framework dependency
|
|
56
38
|
if (!pkg.dependencies) pkg.dependencies = {}
|
|
57
39
|
pkg.dependencies[frameworkPkg.name] = `^${frameworkPkg.version}`
|
|
58
40
|
|
|
@@ -70,24 +52,12 @@ async function run() {
|
|
|
70
52
|
}
|
|
71
53
|
|
|
72
54
|
console.log('\n✨ Project initialized successfully!')
|
|
73
|
-
console.log('\n🚀 Starting server...')
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
execSync('npm run dev', {
|
|
77
|
-
stdio: 'inherit',
|
|
78
|
-
cwd: targetDir
|
|
79
|
-
})
|
|
80
|
-
} catch (err) {
|
|
81
|
-
// User probably cancelled with Ctrl+C
|
|
82
|
-
console.log('\n👋 Server stopped.')
|
|
83
|
-
}
|
|
84
55
|
|
|
85
56
|
} catch (error) {
|
|
86
57
|
console.error('❌ Error initializing project:', error.message)
|
|
87
58
|
}
|
|
88
59
|
|
|
89
60
|
} else if (command === 'dev') {
|
|
90
|
-
// Start the framework
|
|
91
61
|
require('../index.js')
|
|
92
62
|
} else {
|
|
93
63
|
console.log('Usage:')
|