odac 1.3.0 → 1.4.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.
Files changed (42) hide show
  1. package/.agent/rules/memory.md +7 -1
  2. package/.github/workflows/release.yml +0 -4
  3. package/AGENTS.md +47 -0
  4. package/CHANGELOG.md +32 -0
  5. package/README.md +1 -1
  6. package/bin/odac.js +169 -6
  7. package/client/odac.js +15 -11
  8. package/docs/ai/README.md +49 -0
  9. package/docs/ai/skills/SKILL.md +39 -0
  10. package/docs/ai/skills/backend/authentication.md +67 -0
  11. package/docs/ai/skills/backend/config.md +32 -0
  12. package/docs/ai/skills/backend/controllers.md +62 -0
  13. package/docs/ai/skills/backend/cron.md +50 -0
  14. package/docs/ai/skills/backend/database.md +21 -0
  15. package/docs/ai/skills/backend/forms.md +19 -0
  16. package/docs/ai/skills/backend/ipc.md +55 -0
  17. package/docs/ai/skills/backend/mail.md +34 -0
  18. package/docs/ai/skills/backend/request_response.md +35 -0
  19. package/docs/ai/skills/backend/routing.md +51 -0
  20. package/docs/ai/skills/backend/storage.md +43 -0
  21. package/docs/ai/skills/backend/streaming.md +34 -0
  22. package/docs/ai/skills/backend/structure.md +57 -0
  23. package/docs/ai/skills/backend/translations.md +42 -0
  24. package/docs/ai/skills/backend/utilities.md +24 -0
  25. package/docs/ai/skills/backend/validation.md +53 -0
  26. package/docs/ai/skills/backend/views.md +61 -0
  27. package/docs/ai/skills/frontend/core.md +66 -0
  28. package/docs/ai/skills/frontend/forms.md +21 -0
  29. package/docs/ai/skills/frontend/navigation.md +20 -0
  30. package/docs/ai/skills/frontend/realtime.md +47 -0
  31. package/docs/backend/10-authentication/01-user-logins-with-authjs.md +2 -0
  32. package/docs/backend/10-authentication/05-session-management.md +25 -3
  33. package/package.json +1 -1
  34. package/src/Auth.js +100 -15
  35. package/src/Route/Internal.js +21 -18
  36. package/src/Route/MimeTypes.js +56 -0
  37. package/src/Route.js +40 -63
  38. package/src/View/Form.js +91 -51
  39. package/src/View.js +8 -3
  40. package/test/Auth.test.js +249 -0
  41. package/test/Client.test.js +29 -0
  42. package/test/View/Form.test.js +37 -0
@@ -39,4 +39,10 @@ trigger: always_on
39
39
  ## Testing & Validation
40
40
  - **Mandatory Test Coverage:** Every new feature, method, or significant logic change MUST be accompanied by a corresponding unit or integration test.
41
41
  - **Verify Correctness:** do not assume code works; prove it with a test that covers both success and failure scenarios (e.g., edge cases, error conditions).
42
- - **Update Existing Tests:** If a feature modifies existing behavior, update the relevant tests to reflect the new logic and ensure they pass.
42
+ - **Update Existing Tests:** If a feature modifies existing behavior, update the relevant tests to reflect the new logic and ensure they pass.
43
+
44
+ ## Client Library (odac.js)
45
+ - **Automatic JSON Parsing:** The `#ajax` method (and by extension `odac.get`) must automatically parse the response if the `Content-Type` header contains `application/json`, even if `dataType` is not explicitly set to `json`.
46
+
47
+ ## Security Logic & Authentication
48
+ - **Enterprise Token Rotation:** The `Auth.js` system utilizes a non-blocking refresh token rotation mechanism for cookies (`odac_x`/`odac_y`). To prevent race conditions during concurrent requests in high-throughput SPAs, rotated tokens are **not** immediately deleted. Instead, their `active` timestamp is set to naturally expire in 60 seconds (Grace Period), and their `date` timestamp is set to the Unix Epoch (`new Date(0)`) as an identifier mark. Never delete rotated tokens immediately.
@@ -41,10 +41,6 @@ jobs:
41
41
  env:
42
42
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
43
43
  run: npx semantic-release
44
-
45
- - name: Publish to npm
46
- run: npm publish --provenance --access public
47
-
48
44
  - name: Get version
49
45
  id: version
50
46
  run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
package/AGENTS.md ADDED
@@ -0,0 +1,47 @@
1
+ # ODAC Agent Instructions
2
+
3
+ You are an AI Agent operating within the **ODAC Framework** repository. This document outlines the core principles, architectural standards, and operational guidelines you MUST follow to maintain the integrity and performance of this enterprise-grade system.
4
+
5
+ ## 1. Project Identity & Philosophy
6
+ - **Name:** ODAC (Always uppercase in strings/docs/logs).
7
+ - **Core Goal:** To provide a robust, zero-config, high-performance Node.js framework for distributed cloud applications.
8
+ - **The "Big 3" Priorities:**
9
+ 1. **Enterprise-Level Security:** Security is foundational. Default to secure, validate all inputs, sanitize all outputs.
10
+ 2. **Zero-Config:** Works out-of-the-box. Convention over configuration.
11
+ 3. **High Performance:** Optimize for throughput and low latency (Sub-millisecond targets).
12
+
13
+ ## 2. Architectural Principles
14
+ - **Asynchronous & Non-Blocking:** Exclusively use non-blocking I/O. Use `fs.promises` instead of sync methods.
15
+ - **Dependency Injection (DI):** Build components with DI for maximum testability.
16
+ - **Single Responsibility Principle (SRP):** Keep classes and functions focused and small.
17
+ - **Memory Management:** Be paranoid about leaks. Clean up listeners, streams, and connections.
18
+ - **O(n log n) Bound:** Prioritize O(1) or O(n log n) algorithms. Justify any O(n²) operations.
19
+
20
+ ## 3. Coding Standards & Integrity
21
+ - **Modern JavaScript:** Use ES6+ features, ES Modules (import/export).
22
+ - **Strictly Prohibited:** **No usage of `var`**. Use `const` (preferred) or `let`.
23
+ - **Fail-Fast Pattern:** Implement early returns for negative cases. Avoid deeply nested `if/else`.
24
+ - **Anti-Spaghetti Rules:**
25
+ - Resolve Promises upfront (e.g., `Promise.all`) before loops.
26
+ - Avoid mixing `await` inside deep logic.
27
+ - Capture mutable state synchronously before async operations.
28
+ - **No Quick/Lazy Fixes:** Implement correctly from the start. Refactor if necessary; no "band-aid" patches.
29
+
30
+ ## 4. Technical Constraints (Strict Compliance)
31
+ - **Session Safety:** `Odac.Request.setSession()` MUST be called before accessing `Odac.Request.session()`.
32
+ - **Structured Logging:** No `console.log`. Use the internal JSON logger with appropriate levels.
33
+ - **Native APIs:** Prefer native Node.js/Browser APIs (like `fetch`) over external libraries to minimize overhead.
34
+ - **Token Rotation:** In `Auth.js`, use the 60-second grace period for rotated tokens. Never delete them immediately.
35
+ - **Ajax Parsing:** `odac.js` must automatically parse JSON responses if headers allow.
36
+
37
+ ## 5. Testing & Documentation
38
+ - **TDD Requirement:** No feature is complete without unit/integration tests covering both success and edge cases.
39
+ - **Documentation:** Every exported member must have JSDoc explaining *Why* it exists, not just *What* it does.
40
+ - **No User Dialogues in Code:** Do not include assistant-user interaction in comments or code files.
41
+
42
+ ## 6. Communication Style
43
+ - **Authoritative & Precise:** Be the expert. Do not explain basic concepts.
44
+ - **Proactive Correction:** If the user suggests a sub-optimal or insecure pattern (e.g., synchronous reads), refuse and implement the correct async version, explaining the trade-off.
45
+
46
+ ---
47
+ *Note: This file is a living document. Updates should be reflected in `memory.md` and subsequent AI interactions.*
package/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  ### ⚙️ Engine Tuning
2
2
 
3
+ - Extract MIME type definitions into a dedicated module.
4
+
5
+ ### ⚡️ Performance Upgrades
6
+
7
+ - prevent redundant database table migration calls by introducing a static cache to track completed migrations.
8
+
9
+ ### ✨ What's New
10
+
11
+ - add comprehensive ODAC Agent instructions and guidelines
12
+ - **auth:** implement enterprise refresh token rotation with grace period and session persistence
13
+ - Automatically parse JSON responses in client-side AJAX requests based on the `Content-Type` header.
14
+ - implement comprehensive AI agent skills system and automated CLI setup
15
+
16
+ ### 🛠️ Fixes & Improvements
17
+
18
+ - add HTML escaping functionality to Form class and corresponding tests
19
+ - **ai:** correct target path for syncing AI skills
20
+ - **auth:** replace magic number with constant for rotated token threshold
21
+ - **auth:** replace magic number with constant for token rotation grace period
22
+ - enhance odac:form parser with nested quotes and dynamic binding support
23
+ - **route:** support nested property paths in actions and resolve App class conflict
24
+ - **view:** ensure odac:for with 'in' attribute parses correctly as javascript
25
+ - **view:** implement clear attribute in odac:form to control auto-clearing
26
+
27
+
28
+
29
+ ---
30
+
31
+ Powered by [⚡ ODAC](https://odac.run)
32
+
33
+ ### ⚙️ Engine Tuning
34
+
3
35
  - Improve disposable domain cache management by relocating the cache path, ensuring directory existence, and standardizing error logging.
4
36
  - Migrate file system operations in Mail and View to use async `fs.promises` for non-blocking I/O, aligning with new memory.md guidelines.
5
37
  - remove unused `WebSocketClient` variable assignments in `WebSocket.test.js`
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  * 🔗 **Powerful Routing:** Create clean, custom URLs and manage infinite pages with a flexible routing system.
11
11
  * ✨ **Seamless SPA Experience:** Automatic AJAX handling for forms and page transitions eliminates the need for complex client-side code.
12
12
  * 🛡️ **Built-in Security:** Automatic CSRF protection and secure default headers keep your application safe.
13
- * 🔐 **Authentication:** Ready-to-use session management, password hashing, and authentication helpers.
13
+ * 🔐 **Authentication:** Ready-to-use session management with enterprise-grade **Refresh Token Rotation**, secure password hashing, and authentication helpers.
14
14
  * 🗄️ **Database Agnostic:** Integrated support for major databases (PostgreSQL, MySQL, SQLite) and Redis via Knex.js.
15
15
  * 🌍 **i18n Support:** Native multi-language support to help you reach a global audience.
16
16
  * ⏰ **Task Scheduling:** Built-in Cron job system for handling background tasks and recurring operations.
package/bin/odac.js CHANGED
@@ -16,6 +16,72 @@ const rl = readline.createInterface({
16
16
 
17
17
  const ask = question => new Promise(resolve => rl.question(question, answer => resolve(answer.trim())))
18
18
 
19
+ /**
20
+ * Interactive selection menu for CLI.
21
+ * @param {string} title Menu title
22
+ * @param {string[]} options List of choice strings
23
+ * @returns {Promise<number>} Selected index
24
+ */
25
+ const select = async (title, options) => {
26
+ if (!process.stdout.isTTY) return 0
27
+
28
+ return new Promise(resolve => {
29
+ let current = 0
30
+ const hideCursor = '\u001B[?25l'
31
+ const showCursor = '\u001B[?25h'
32
+
33
+ // Calculate total lines the title occupies
34
+ const titleLines = title.split('\n')
35
+ const totalLines = titleLines.length + options.length
36
+
37
+ const render = () => {
38
+ // Clear all lines we previously wrote
39
+ titleLines.forEach(line => {
40
+ process.stdout.write('\r\x1b[K' + line + '\n')
41
+ })
42
+ options.forEach((opt, i) => {
43
+ const line = i === current ? `\x1b[36m ❯ ${opt}\x1b[0m` : ` ${opt}`
44
+ process.stdout.write('\r\x1b[K' + line + '\n')
45
+ })
46
+ process.stdout.write(`\x1b[${totalLines}A`) // Move back to the very start
47
+ }
48
+
49
+ process.stdout.write(hideCursor)
50
+ if (!process.stdin.isRaw) {
51
+ process.stdin.setRawMode(true)
52
+ process.stdin.resume()
53
+ }
54
+ readline.emitKeypressEvents(process.stdin)
55
+
56
+ render()
57
+
58
+ const onKey = (str, key) => {
59
+ if (key.name === 'up') {
60
+ current = current > 0 ? current - 1 : options.length - 1
61
+ render()
62
+ } else if (key.name === 'down') {
63
+ current = current < options.length - 1 ? current + 1 : 0
64
+ render()
65
+ } else if (key.name === 'return' || key.name === 'enter') {
66
+ cleanup()
67
+ process.stdout.write(`\x1b[${totalLines}B\n`) // Move down past everything
68
+ resolve(current)
69
+ } else if (key.ctrl && key.name === 'c') {
70
+ cleanup()
71
+ process.exit()
72
+ }
73
+ }
74
+
75
+ const cleanup = () => {
76
+ process.stdin.removeListener('keypress', onKey)
77
+ if (process.stdin.isRaw) process.stdin.setRawMode(false)
78
+ process.stdout.write(showCursor)
79
+ }
80
+
81
+ process.stdin.on('keypress', onKey)
82
+ })
83
+ }
84
+
19
85
  /**
20
86
  * Resolves Tailwind CSS paths and ensures required directories/files exist.
21
87
  * Supports multiple CSS entry points from 'view/css'.
@@ -73,6 +139,94 @@ function getTailwindConfigs() {
73
139
  return configs
74
140
  }
75
141
 
142
+ /**
143
+ * Manages the AI Agent skills synchronization.
144
+ * @param {string} targetDir The directory to sync skills into.
145
+ */
146
+ async function manageSkills(targetDir = process.cwd()) {
147
+ const aiSourceDir = path.resolve(__dirname, '../docs/ai')
148
+
149
+ if (!fs.existsSync(aiSourceDir)) {
150
+ console.error('❌ AI components not found in framework.')
151
+ return
152
+ }
153
+
154
+ const options = [
155
+ 'Antigravity / Cascade (.agent/skills)',
156
+ 'Claude / Projects (.claude/skills)',
157
+ 'Continue (.continue/skills)',
158
+ 'Cursor (.cursor/skills)',
159
+ 'Kilo Code (.kilocode/skills)',
160
+ 'Kiro CLI (.kiro/skills)',
161
+ 'Qwen Code (.qwen/skills)',
162
+ 'Windsurf (.windsurf/skills)',
163
+ 'Custom Path',
164
+ 'Skip / Cancel'
165
+ ]
166
+
167
+ const choiceIndex = await select('\n🤖 \x1b[36mODAC AI Agent Skills Manager\x1b[0m\nSelect your AI Agent / IDE for setup:', options)
168
+
169
+ let targetSubDir = ''
170
+ let copySkillsOnly = true
171
+
172
+ const SKIP_INDEX = 9
173
+ const CUSTOM_INDEX = 8
174
+
175
+ if (choiceIndex === SKIP_INDEX) return // Skip / Cancel
176
+
177
+ switch (choiceIndex) {
178
+ case 0:
179
+ targetSubDir = '.agent/skills'
180
+ break
181
+ case 1:
182
+ targetSubDir = '.claude/skills'
183
+ break
184
+ case 2:
185
+ targetSubDir = '.continue/skills'
186
+ break
187
+ case 3:
188
+ targetSubDir = '.cursor/skills'
189
+ break
190
+ case 4:
191
+ targetSubDir = '.kilocode/skills'
192
+ break
193
+ case 5:
194
+ targetSubDir = '.kiro/skills'
195
+ break
196
+ case 6:
197
+ targetSubDir = '.qwen/skills'
198
+ break
199
+ case 7:
200
+ targetSubDir = '.windsurf/skills'
201
+ break
202
+ case CUSTOM_INDEX:
203
+ targetSubDir = await ask('Enter custom path: ')
204
+ copySkillsOnly = false
205
+ break
206
+ default:
207
+ return
208
+ }
209
+
210
+ const targetBase = path.resolve(targetDir, targetSubDir)
211
+ const targetPath = targetBase
212
+
213
+ try {
214
+ fs.mkdirSync(targetPath, {recursive: true})
215
+
216
+ if (copySkillsOnly) {
217
+ const skillsSource = path.join(aiSourceDir, 'skills')
218
+ fs.cpSync(skillsSource, targetPath, {recursive: true})
219
+ } else {
220
+ fs.cpSync(aiSourceDir, targetPath, {recursive: true})
221
+ }
222
+
223
+ console.log(`\n✨ AI skills successfully synced to: \x1b[32m${targetSubDir}\x1b[0m`)
224
+ console.log('Your AI Agent now has full knowledge of the ODAC Framework. 🚀')
225
+ } catch (err) {
226
+ console.error('❌ Failed to sync AI skills:', err.message)
227
+ }
228
+ }
229
+
76
230
  async function run() {
77
231
  if (command === 'init') {
78
232
  const projectName = args[0] || '.'
@@ -110,10 +264,21 @@ async function run() {
110
264
  }
111
265
 
112
266
  console.log('\n✨ Project initialized successfully!')
267
+
268
+ // Interactive AI Skills setup
269
+ if (process.stdout.isTTY) {
270
+ const setupAIIndex = await select('\n🤖 Should we setup AI Agent skills for your IDE?', ['Yes', 'No'])
271
+ if (setupAIIndex === 0) {
272
+ await manageSkills(targetDir)
273
+ } else {
274
+ console.log('\n💡 \x1b[33mTip:\x1b[0m You can always run \x1b[36mnpx odac skills\x1b[0m later.')
275
+ }
276
+ }
113
277
  } catch (error) {
114
278
  console.error('❌ Error initializing project:', error.message)
115
279
  }
116
280
  } else if (command === 'dev') {
281
+ // ... existing dev logic ...
117
282
  if (cluster.isPrimary) {
118
283
  const configs = getTailwindConfigs()
119
284
  const tails = []
@@ -134,20 +299,16 @@ async function run() {
134
299
 
135
300
  tailwindProcess = spawn(cmd, args, {
136
301
  stdio: ['pipe', 'ignore', 'pipe'],
137
- shell: !useLocal, // Valid for npm/npx compatibility if local not found
302
+ shell: !useLocal,
138
303
  cwd: process.cwd()
139
304
  })
140
305
 
141
- // Filter stderr: suppress status noise, forward only real errors
142
306
  tailwindProcess.stderr.on('data', chunk => {
143
307
  const raw = chunk.toString()
144
308
  const lines = raw.split('\n')
145
309
  for (const line of lines) {
146
- // Strip ANSI escape codes to ensure reliable filtering
147
310
  const clean = line.replace(/\x1B\[[0-9;]*[JKmsu]/g, '').trim()
148
-
149
311
  if (!clean || clean.startsWith('Done in') || clean.startsWith('≈')) continue
150
-
151
312
  process.stderr.write(`\x1b[31m[ODAC Style Error]\x1b[0m ${line}\n`)
152
313
  }
153
314
  })
@@ -166,7 +327,6 @@ async function run() {
166
327
 
167
328
  startWatcher()
168
329
 
169
- // Push a wrapper compatible with the cleanup function
170
330
  tails.push({
171
331
  kill: () => {
172
332
  if (tailwindProcess) tailwindProcess.kill()
@@ -214,6 +374,8 @@ async function run() {
214
374
  } else if (command === 'start') {
215
375
  process.env.NODE_ENV = 'production'
216
376
  require('../index.js')
377
+ } else if (command === 'skills') {
378
+ await manageSkills()
217
379
  } else {
218
380
  console.log('Usage:')
219
381
  console.log(' npx odac init (Interactive mode)')
@@ -221,6 +383,7 @@ async function run() {
221
383
  console.log(' npx odac dev (Development mode)')
222
384
  console.log(' npx odac build (Production build)')
223
385
  console.log(' npx odac start (Start server)')
386
+ console.log(' npx odac skills (Sync AI Agent skills)')
224
387
  }
225
388
 
226
389
  rl.close()
package/client/odac.js CHANGED
@@ -142,13 +142,18 @@ if (typeof window !== 'undefined') {
142
142
  xhr.onload = () => {
143
143
  if (xhr.status >= 200 && xhr.status < 300) {
144
144
  let responseData = xhr.responseText
145
- if (dataType === 'json') {
145
+ const contentTypeHeader = xhr.getResponseHeader('Content-Type')
146
+ const isJson = dataType === 'json' || (contentTypeHeader && contentTypeHeader.includes('application/json'))
147
+
148
+ if (isJson) {
146
149
  try {
147
150
  responseData = JSON.parse(responseData)
148
151
  } catch (e) {
149
- console.error('JSON parse error:', e)
150
- error(xhr, 'parseerror', e)
151
- return
152
+ if (dataType === 'json') {
153
+ console.error('JSON parse error:', e)
154
+ error(xhr, 'parseerror', e)
155
+ return
156
+ }
152
157
  }
153
158
  }
154
159
 
@@ -596,7 +601,7 @@ if (typeof window !== 'undefined') {
596
601
  }
597
602
  },
598
603
  xhr: () => {
599
- var xhr = new window.XMLHttpRequest()
604
+ const xhr = new window.XMLHttpRequest()
600
605
  xhr.upload.addEventListener(
601
606
  'progress',
602
607
  evt => {
@@ -661,24 +666,23 @@ if (typeof window !== 'undefined') {
661
666
  this.#token.listener = true
662
667
  }
663
668
  if (!this.#token.hash.length) {
664
- var req = new XMLHttpRequest()
669
+ const req = new XMLHttpRequest()
665
670
  req.open('GET', '/', false)
666
671
  req.setRequestHeader('X-Odac', 'token')
667
672
  req.setRequestHeader('X-Odac-Client', this.client())
668
673
  req.send(null)
669
- var req_data = JSON.parse(req.response)
674
+ const req_data = JSON.parse(req.response)
670
675
  if (req_data.token) this.#token.hash.push(req_data.token)
671
676
  }
672
- this.#token.hash.filter(n => n)
673
- var return_token = this.#token.hash.shift()
677
+ this.#token.hash = this.#token.hash.filter(n => n)
678
+ const return_token = this.#token.hash.shift()
674
679
  if (!this.#token.hash.length)
675
680
  this.#ajax({
676
681
  url: '/',
677
682
  type: 'GET',
678
683
  headers: {'X-Odac': 'token', 'X-Odac-Client': this.client()},
679
684
  success: data => {
680
- var result = JSON.parse(JSON.stringify(data))
681
- if (result.token) this.#token.hash.push(result.token)
685
+ if (data.token) this.#token.hash.push(data.token)
682
686
  }
683
687
  })
684
688
  return return_token
@@ -0,0 +1,49 @@
1
+ # ODAC AI Agent Master Guide
2
+
3
+ Welcome! If you are reading this document, you are an AI Agent tasked with developing a project using the ODAC (Open Distributed Application Container) Framework.
4
+
5
+ ODAC is a high-performance, enterprise-grade, and zero-configuration Node.js framework. Your mission is to produce secure, scalable code while strictly adhering to the framework's principles.
6
+
7
+ ## Core Mandate
8
+ When developing with ODAC, you must not only write code but also leverage the framework's optimized structures (Route, View, Database, Hub, etc.) in the most efficient way possible.
9
+
10
+ ## Agent Principles
11
+ 1. **Performance Focused**: Always aim for O(1) or O(n log n) complexity. Avoid inefficient queries like `SELECT *`.
12
+ 2. **Security-by-Default**: Validate all input data using the `Validator`. Trust the auto-sanitizing View engine but maintain manual control in critical areas.
13
+ 3. **Error Management**: Never swallow errors. Use framework-specific methods like `Odac.Request.error()` to return structured error messages.
14
+ 4. **Clean Code**: Keep functions small (Single Responsibility) and adhere to ESM (ES Modules) standards.
15
+
16
+ ## How to Use This Guide
17
+ The `skills/` directory contains a master `SKILL.md` that indexes specialized rules for each module. When adding a feature, you MUST refer to these rules and base your implementation on the "Reference Patterns".
18
+
19
+ ## Core Rules
20
+ Detailed instructions are organized into Backend and Frontend categories:
21
+
22
+ ### Backend
23
+ - `backend/authentication.md`: Sessions, Auth, and Realtime Hubs.
24
+ - `backend/config.md`: Configuration management and environment variables.
25
+ - `backend/controllers.md`: Request handling and Class-Based Controllers.
26
+ - `backend/cron.md`: Scheduled background tasks and automation.
27
+ - `backend/database.md`: High-performance query builder usage.
28
+ - `backend/forms.md`: Form processing and validation logic.
29
+ - `backend/ipc.md`: Inter-Process Communication and state sharing.
30
+ - `backend/mail.md`: Transactional email sending.
31
+ - `backend/request_response.md`: Handling Odac.Request and Odac.Response.
32
+ - `backend/routing.md`: Route definitions, Middlewares, and Error Pages.
33
+ - `backend/storage.md`: Persistent key-value storage (LMDB).
34
+ - `backend/streaming.md`: Server-Sent Events (SSE) and Streaming API.
35
+ - `backend/structure.md`: Project organization and Service Classes.
36
+ - `backend/translations.md`: Multi-language support (i18n).
37
+ - `backend/utilities.md`: Odac.Var (String Manipulation) and Flow Control.
38
+ - `backend/validation.md`: Input sanitization and security checks.
39
+ - `backend/views.md`: Template syntax, skeletons, and server-side JS.
40
+
41
+ ### Frontend
42
+ - `frontend/core.md`: Framework lifecycle, page scoping, and storage.
43
+ - `frontend/forms.md`: AJAX form handling and API requests.
44
+ - `frontend/navigation.md`: AJAX Navigation (SPA) behavior.
45
+ - `frontend/realtime.md`: WebSocket Hubs and EventSource usage.
46
+
47
+ ---
48
+
49
+ **Remember:** You are an ODAC expert. Every line of code you write should reflect the "Enterprise" spirit of the framework.
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: odac-framework
3
+ description: Comprehensive AI developer skills for the ODAC Framework (Backend & Frontend).
4
+ metadata:
5
+ tags: nodejs, framework, backend, frontend, architecture, security
6
+ ---
7
+
8
+ ## When to use
9
+
10
+ Use this skill whenever you are developing an application with the ODAC Framework. It provides domain-specific knowledge for both server-side logic and client-side interactions.
11
+
12
+ ## How to use
13
+
14
+ Read the specific rule files based on whether you are working on the Backend or Frontend:
15
+
16
+ ### Backend Rules
17
+ - [backend/authentication.md](backend/authentication.md) - Sessions, Auth, and Realtime Hubs
18
+ - [backend/config.md](backend/config.md) - Configuration management and environment variables
19
+ - [backend/controllers.md](backend/controllers.md) - Request handling and Class-Based Controllers
20
+ - [backend/cron.md](backend/cron.md) - Scheduled background tasks and automation
21
+ - [backend/database.md](backend/database.md) - Query Builder and DB best practices
22
+ - [backend/forms.md](backend/forms.md) - Form processing and Validation logic
23
+ - [backend/ipc.md](backend/ipc.md) - Inter-Process Communication and state sharing
24
+ - [backend/mail.md](backend/mail.md) - Transactional email sending
25
+ - [backend/request_response.md](backend/request_response.md) - Handling Odac.Request and Odac.Response
26
+ - [backend/routing.md](backend/routing.md) - Route definitions, Middlewares, and Error Pages
27
+ - [backend/storage.md](backend/storage.md) - Persistent key-value storage (LMDB)
28
+ - [backend/streaming.md](backend/streaming.md) - Server-Sent Events (SSE) and Streaming API
29
+ - [backend/structure.md](backend/structure.md) - Project organization and Service Classes
30
+ - [backend/translations.md](backend/translations.md) - Multi-language support (i18n)
31
+ - [backend/utilities.md](backend/utilities.md) - Odac.Var (String Manipulation) and Flow Control
32
+ - [backend/validation.md](backend/validation.md) - Input sanitization and security checks
33
+ - [backend/views.md](backend/views.md) - Template syntax, skeletons, and server-side JS
34
+
35
+ ### Frontend Rules
36
+ - [frontend/core.md](frontend/core.md) - Framework lifecycle, page scoping, and storage
37
+ - [frontend/forms.md](frontend/forms.md) - AJAX form handling and API requests
38
+ - [frontend/navigation.md](frontend/navigation.md) - AJAX Navigation (SPA) behavior
39
+ - [frontend/realtime.md](frontend/realtime.md) - WebSocket Hubs and EventSource usage
@@ -0,0 +1,67 @@
1
+ # Backend Authentication & Realtime Skill
2
+
3
+ Secure user authentication, session management, and bidirectional communication.
4
+
5
+ ## Architectural Approach
6
+ ODAC provides built-in drivers for session handling (Memory/Redis) and multiple authentication flows including standard password-based login and passwordless Magic Links.
7
+
8
+ ## Core Rules
9
+ 1. **Auth Guard**: Protect routes using `Odac.Route.auth`.
10
+ 2. **Session Integrity**: `Odac.Request.setSession()` MUST be called before accessing `Odac.Request.session()`.
11
+ 3. **Password Security**: The framework handles BCrypt hashing automatically via `Odac.Auth`.
12
+ 4. **Magic Links**: Use `Odac.Auth.magic(email)` for passwordless flows.
13
+ 5. **Token Rotation**: Enterprise-grade rotation is enabled by default. It uses a 60s grace period to prevent race conditions in SPAs.
14
+ 6. **Persistence**: Cookies use the configured `maxAge` to persist beyond browser closure.
15
+ ## Reference Patterns
16
+
17
+ ### 1. Standard Login & Check
18
+ ```javascript
19
+ // Check if user is logged in
20
+ if (Odac.Auth.check()) {
21
+ const user = Odac.Auth.user();
22
+ const userId = Odac.Auth.id();
23
+ }
24
+
25
+ // Log in a user manually
26
+ await Odac.Auth.login(userId);
27
+
28
+ // Log out
29
+ await Odac.Auth.logout();
30
+ ```
31
+
32
+ ### 2. Magic Links (Passwordless)
33
+ ```javascript
34
+ // Generate and send a magic link
35
+ const result = await Odac.Auth.magic('user@example.com', {
36
+ redirect: '/dashboard',
37
+ subject: 'Login to MyApp'
38
+ });
39
+
40
+ if (result.success) {
41
+ return { message: 'Link sent!' };
42
+ }
43
+ ```
44
+
45
+ ### 3. Session Management
46
+ ```javascript
47
+ // Get/Set session data
48
+ Odac.session('key', 'value');
49
+ const val = Odac.session('key');
50
+
51
+ // Destroy session
52
+ Odac.session('key', null);
53
+ ```
54
+
55
+ ### 4. Realtime Hubs (WebSockets)
56
+ ```javascript
57
+ // Broadcast to everyone in a room
58
+ Odac.Hub.to('lobby').send('chat_message', { text: 'Hello!' });
59
+
60
+ // Targeted user broadcast
61
+ Odac.Hub.user(userId).send('notification', { text: 'New follower' });
62
+ ```
63
+
64
+ ## Security Best Practices
65
+ - **CSRF Protection**: Native `Odac.form` and `Odac.post` handle CSRF tokens automatically using `{{ TOKEN }}` in views.
66
+ - **Brute Force**: Always use `validator.brute()` on authentication endpoints.
67
+ - **Passwordless Preference**: Consider using Magic Links for enhanced security and better user experience.
@@ -0,0 +1,32 @@
1
+ # Backend Configuration Skill
2
+
3
+ Managing application settings using `odac.json` and environment variables.
4
+
5
+ ## Architectural Approach
6
+ ODAC uses `odac.json` for structure and `.env` for secrets. Values can be accessed via `Odac.Config` or the `Odac.env()` helper.
7
+
8
+ ## Core Rules
9
+ 1. **Direct Access**: Use `Odac.Config.key` for settings in `odac.json`.
10
+ 2. **Environment Variables**: Use `${VAR_NAME}` in `odac.json` to map to `.env` values.
11
+ 3. **Encapsulation**: Never hardcode credentials. Always use `.env`.
12
+
13
+ ## Reference Patterns
14
+ ### 1. Accessing Config
15
+ ```javascript
16
+ // From odac.json: { "app": { "name": "My App" } }
17
+ const appName = Odac.Config.app.name;
18
+
19
+ // From .env: API_KEY=secret
20
+ const apiKey = Odac.env('API_KEY');
21
+ ```
22
+
23
+ ### 2. odac.json Structure
24
+ ```json
25
+ {
26
+ "mysql": {
27
+ "host": "${DB_HOST}",
28
+ "password": "${DB_PASSWORD}"
29
+ },
30
+ "debug": true
31
+ }
32
+ ```
@@ -0,0 +1,62 @@
1
+ # Backend Controllers Skill
2
+
3
+ Controllers are the bridge between routes and views/services. This skill covers how to write clean, professional controllers in ODAC.
4
+
5
+ ## Architectural Approach
6
+ ODAC supports both simple function-based controllers and class-based controllers. For enterprise-grade applications, class-based controllers are strongly recommended for better organization.
7
+
8
+ ## Core Rules
9
+ 1. **Class-Based Controllers**: Use classes to group related logic. Each method handles a specific route.
10
+ 2. **Naming Convention**: Controllers are usually PascalCase (e.g., `UserController.js`).
11
+ 3. **Route Mapping**: Use the `ControllerName@MethodName` syntax in routes.
12
+ 4. **Automatic Injection**: Methods receive the `Odac` instance as the first argument automatically.
13
+
14
+ ## Reference Patterns
15
+
16
+ ### 1. Class-Based Controller (Recommended)
17
+ ```javascript
18
+ // controller/User.js
19
+ class User {
20
+ // GET /users
21
+ async index(Odac) {
22
+ const users = await Odac.Service.get('User').all();
23
+ return Odac.View.make('user.list', { users });
24
+ }
25
+
26
+ // GET /users/{id}
27
+ async show(Odac) {
28
+ const id = Odac.Request.input('id');
29
+ const user = await Odac.Service.get('User').find(id);
30
+ return Odac.return(user);
31
+ }
32
+
33
+ // POST /users
34
+ async store(Odac) {
35
+ const data = Odac.Request.post();
36
+ // Logic to save user...
37
+ return { success: true };
38
+ }
39
+ }
40
+
41
+ module.exports = User;
42
+ ```
43
+
44
+ ### 2. Simple Function-Based Controller
45
+ ```javascript
46
+ // controller/Home.js
47
+ module.exports = function(Odac) {
48
+ return "Welcome to ODAC!";
49
+ };
50
+ ```
51
+
52
+ ### 3. Usage in Routes
53
+ ```javascript
54
+ // route/web.js
55
+ Odac.Route.get('/users', 'User@index');
56
+ Odac.Route.get('/home', 'Home'); // Auto-calls the exported function
57
+ ```
58
+
59
+ ## Best Practices
60
+ - **Keep it Thin**: Controllers should only handle request parsing and response formatting. Core logic belongs in **Services**.
61
+ - **Asynchronous Handling**: Always use `async/await` for database or network operations.
62
+ - **Structured Returns**: Use `Odac.return()` for JSON or `Odac.View.make()` for rendering.