odac 1.3.0 → 1.4.1
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/memory.md +10 -1
- package/.github/workflows/release.yml +1 -5
- package/AGENTS.md +47 -0
- package/CHANGELOG.md +58 -0
- package/README.md +11 -1
- package/bin/odac.js +359 -6
- package/client/odac.js +15 -11
- package/docs/ai/README.md +49 -0
- package/docs/ai/skills/SKILL.md +40 -0
- package/docs/ai/skills/backend/authentication.md +74 -0
- package/docs/ai/skills/backend/config.md +39 -0
- package/docs/ai/skills/backend/controllers.md +69 -0
- package/docs/ai/skills/backend/cron.md +57 -0
- package/docs/ai/skills/backend/database.md +37 -0
- package/docs/ai/skills/backend/forms.md +26 -0
- package/docs/ai/skills/backend/ipc.md +62 -0
- package/docs/ai/skills/backend/mail.md +41 -0
- package/docs/ai/skills/backend/migrations.md +80 -0
- package/docs/ai/skills/backend/request_response.md +42 -0
- package/docs/ai/skills/backend/routing.md +58 -0
- package/docs/ai/skills/backend/storage.md +50 -0
- package/docs/ai/skills/backend/streaming.md +41 -0
- package/docs/ai/skills/backend/structure.md +64 -0
- package/docs/ai/skills/backend/translations.md +49 -0
- package/docs/ai/skills/backend/utilities.md +31 -0
- package/docs/ai/skills/backend/validation.md +60 -0
- package/docs/ai/skills/backend/views.md +68 -0
- package/docs/ai/skills/frontend/core.md +73 -0
- package/docs/ai/skills/frontend/forms.md +28 -0
- package/docs/ai/skills/frontend/navigation.md +27 -0
- package/docs/ai/skills/frontend/realtime.md +54 -0
- package/docs/backend/08-database/04-migrations.md +258 -37
- package/docs/backend/10-authentication/01-user-logins-with-authjs.md +2 -0
- package/docs/backend/10-authentication/05-session-management.md +25 -3
- package/package.json +1 -1
- package/src/Auth.js +128 -17
- package/src/Config.js +1 -1
- package/src/Database/ConnectionFactory.js +69 -0
- package/src/Database/Migration.js +1203 -0
- package/src/Database.js +35 -35
- package/src/Route/Internal.js +21 -18
- package/src/Route/MimeTypes.js +56 -0
- package/src/Route.js +40 -63
- package/src/View/Form.js +91 -51
- package/src/View.js +8 -3
- package/template/schema/users.js +23 -0
- package/test/Auth.test.js +310 -0
- package/test/Client.test.js +29 -0
- package/test/Config.test.js +7 -0
- package/test/Database/ConnectionFactory.test.js +80 -0
- package/test/Migration.test.js +943 -0
- package/test/View/Form.test.js +37 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-routing-middleware-skill
|
|
3
|
+
description: High-performance ODAC routing and middleware orchestration for secure request pipelines and scalable URL mapping.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, routing, middleware, pipeline, auth, performance, url-matching
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Backend Routing & Middleware Skill
|
|
9
|
+
|
|
10
|
+
Routing manages the request pipeline, directing URLs to controllers while applying security and business logic via middlewares.
|
|
11
|
+
|
|
12
|
+
## Architectural Approach
|
|
13
|
+
Routes are defined in the `route/` directory. ODAC uses a two-phase routing strategy: O(1) exact matches followed by an indexed segment-based parametric lookup for maximum performance.
|
|
14
|
+
|
|
15
|
+
## Core Rules
|
|
16
|
+
1. **Methods**:
|
|
17
|
+
- `Odac.Route.page(url, controller)`: For HTML views (GET).
|
|
18
|
+
- `Odac.Route.get(url, controller)`: Targeted GET requests.
|
|
19
|
+
- `Odac.Route.post(url, controller)`: Sensitive POST requests (CSRF enabled by default).
|
|
20
|
+
2. **Parameters**: Use `{id}` syntax for dynamic segments. Accessed via `Odac.request('id')`.
|
|
21
|
+
3. **Middlewares**: Chain logic using `.use('name')`. Global middlewares reside in `middleware/`.
|
|
22
|
+
4. **Error Handling**: Use `Odac.Route.error(code, controller)` for custom 404/500 pages.
|
|
23
|
+
5. **Auth Guard**: `Odac.Route.auth` automatically checks authentication before running the route.
|
|
24
|
+
|
|
25
|
+
## Reference Patterns
|
|
26
|
+
|
|
27
|
+
### 1. Standard Web Routes
|
|
28
|
+
```javascript
|
|
29
|
+
// page(path, controller)
|
|
30
|
+
Odac.Route.page('/', 'Home');
|
|
31
|
+
Odac.Route.page('/profile/{username}', 'User@profile');
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 2. Protected Routes & Middlewares
|
|
35
|
+
```javascript
|
|
36
|
+
// Only authenticated admins can see stats
|
|
37
|
+
Odac.Route.auth
|
|
38
|
+
.use('is_admin')
|
|
39
|
+
.page('/admin/stats', 'Admin@stats');
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 3. Error Pages mapping
|
|
43
|
+
```javascript
|
|
44
|
+
Odac.Route.error(404, 'errors/NotFound');
|
|
45
|
+
Odac.Route.error(500, 'errors/ServerError');
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 4. API Routes
|
|
49
|
+
```javascript
|
|
50
|
+
// Disable CSRF token check for external APIs
|
|
51
|
+
Odac.Route.post('/api/webhook', 'Api@webhook', { token: false });
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Best Practices
|
|
55
|
+
- **Method Specification**: Use `.page()` for views to enable AJAX navigation compatibility.
|
|
56
|
+
- **Static First**: Prefer exact URL matches over parametric ones where possible (faster).
|
|
57
|
+
- **Controller Isolation**: Place error controllers in `controller/errors/` for better organization.
|
|
58
|
+
- **Parametric Safety**: Do not use too many nested dynamic segments in a single route.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-persistent-storage-skill
|
|
3
|
+
description: Embedded ODAC storage usage patterns with LMDB for sub-millisecond key-value persistence across workers.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, storage, lmdb, key-value, persistence, high-performance
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Backend Persistent Storage Skill
|
|
9
|
+
|
|
10
|
+
ODAC provides a high-performance, embedded key-value store using LMDB, exposed via `Odac.Storage`.
|
|
11
|
+
|
|
12
|
+
## Architectural Approach
|
|
13
|
+
Storage is ideal for persistent data that requires sub-millisecond access and does not need the complexity of a relational database. It is shared across all processes and workers.
|
|
14
|
+
|
|
15
|
+
## Core Rules
|
|
16
|
+
1. **Usage**: Access via `Odac.Storage`.
|
|
17
|
+
2. **Atomicity**: LMDB is ACID compliant and thread-safe.
|
|
18
|
+
3. **Data Types**: Supports strings, numbers, and JSON objects natively.
|
|
19
|
+
4. **Automatic Initialization**: The primary storage is initialized in the `storage/` directory automatically.
|
|
20
|
+
|
|
21
|
+
## Reference Patterns
|
|
22
|
+
|
|
23
|
+
### 1. Basic KV Operations
|
|
24
|
+
```javascript
|
|
25
|
+
// Setting data
|
|
26
|
+
Odac.Storage.put('setting_theme', 'dark');
|
|
27
|
+
Odac.Storage.put('app_data', { version: '1.0.0', last_check: Date.now() });
|
|
28
|
+
|
|
29
|
+
// Getting data
|
|
30
|
+
const theme = Odac.Storage.get('setting_theme');
|
|
31
|
+
const appData = Odac.Storage.get('app_data');
|
|
32
|
+
|
|
33
|
+
// Removing data
|
|
34
|
+
Odac.Storage.remove('setting_theme');
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Range Queries
|
|
38
|
+
```javascript
|
|
39
|
+
// Get all keys starting with 'pref:'
|
|
40
|
+
const preferences = Odac.Storage.getRange({ start: 'pref:', end: 'pref:~' });
|
|
41
|
+
for (const { key, value } of preferences) {
|
|
42
|
+
console.log(key, value);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Best Practices
|
|
47
|
+
- **Keyspacing**: Use prefixes like `sess:`, `cache:`, or `pref:` to organize your keys.
|
|
48
|
+
- **Performance**: Since it's memory-mapped, random reads are extremely fast (O(1)).
|
|
49
|
+
- **No Migrations**: Unlike SQL, Storage is schemaless. Ensure your code handles version changes in the stored JSON objects.
|
|
50
|
+
- **Avoid Large Blobs**: While it can store large values, keep them reasonable to maintain OS-level cache efficiency.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-streaming-sse-skill
|
|
3
|
+
description: Server-Sent Events streaming patterns in ODAC for realtime one-way updates with safe connection lifecycle management.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, streaming, sse, realtime, event-stream, connection-lifecycle
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Backend Streaming API Skill
|
|
9
|
+
|
|
10
|
+
Real-time data streaming using Server-Sent Events (SSE).
|
|
11
|
+
|
|
12
|
+
## Core Rules
|
|
13
|
+
1. **Usage**: Use `Odac.stream(callback)` to keep the connection open.
|
|
14
|
+
2. **Safety**: Always use `Odac.setInterval` and `Odac.setTimeout` inside streams; they are automatically cleaned up on disconnect.
|
|
15
|
+
3. **Return**: You must `return Odac.stream(...)` from the controller.
|
|
16
|
+
|
|
17
|
+
## Reference Patterns
|
|
18
|
+
### 1. Simple Stream
|
|
19
|
+
```javascript
|
|
20
|
+
module.exports = async (Odac) => {
|
|
21
|
+
return Odac.stream((send) => {
|
|
22
|
+
send({ status: 'connected' });
|
|
23
|
+
|
|
24
|
+
Odac.setInterval(() => {
|
|
25
|
+
send({ time: Date.now() });
|
|
26
|
+
}, 1000);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. Async Generator Stream
|
|
32
|
+
```javascript
|
|
33
|
+
module.exports = async (Odac) => {
|
|
34
|
+
return Odac.stream(async function* () {
|
|
35
|
+
const logs = await getLogStream();
|
|
36
|
+
for await (const log of logs) {
|
|
37
|
+
yield log;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-structure-services-skill
|
|
3
|
+
description: ODAC project organization rules for directory structure, service classes, and request-scoped architecture.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, structure, services, architecture, request-scope, organization
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Backend Structure & Services Skill
|
|
9
|
+
|
|
10
|
+
ODAC follows a strictly organized directory structure and focuses on request-scoped architecture. This skill explains how to organize code and use Service Classes.
|
|
11
|
+
|
|
12
|
+
## Architectural Approach
|
|
13
|
+
ODAC uses a request-scoped container. Most logic should be encapsulated in Service Classes (`class/`) which are automatically instantiated and attached to the `Odac` instance for every request.
|
|
14
|
+
|
|
15
|
+
## Core Rules
|
|
16
|
+
1. **Directory Mapping**:
|
|
17
|
+
- `route/`: URL definitions using `Odac.Route`.
|
|
18
|
+
- `controller/`: Request handling logic (Input -> Response).
|
|
19
|
+
- `class/`: Reusable business logic (Service Classes).
|
|
20
|
+
- `view/`: HTML/Template files.
|
|
21
|
+
- `middleware/`: Request interceptors.
|
|
22
|
+
- `locale/`: Translation JSON files.
|
|
23
|
+
2. **Service Classes**:
|
|
24
|
+
- Place classes in the `class/` directory.
|
|
25
|
+
- They are automatically instantiated and attached to `Odac` as `Odac.ClassName`.
|
|
26
|
+
- They are **Request Scoped** (new instance per request).
|
|
27
|
+
3. **Dependency Injection**: Services receive the framework instance (`Odac`) in their constructor.
|
|
28
|
+
|
|
29
|
+
## Reference Patterns
|
|
30
|
+
|
|
31
|
+
### 1. Defining a Service Class (Recommended)
|
|
32
|
+
```javascript
|
|
33
|
+
// class/User.js
|
|
34
|
+
class User {
|
|
35
|
+
constructor(Odac) {
|
|
36
|
+
this.Odac = Odac;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async getProfile(id) {
|
|
40
|
+
// Access database or auth via this.Odac
|
|
41
|
+
return await this.Odac.DB.table('users').where('id', id).first();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
module.exports = User;
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2. Using a Service in a Controller
|
|
48
|
+
```javascript
|
|
49
|
+
// controller/User.js
|
|
50
|
+
class User {
|
|
51
|
+
async show(Odac) {
|
|
52
|
+
// Service is automatically available as Odac.User
|
|
53
|
+
const profile = await Odac.User.getProfile(Odac.Request.input('id'));
|
|
54
|
+
|
|
55
|
+
return Odac.View.make('user.profile', { profile });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
module.exports = User;
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Best Practices
|
|
62
|
+
- **Context Awareness**: Use `this.Odac` inside service classes to access the specific request's state (current user, session, etc.).
|
|
63
|
+
- **Naming**: If a class name conflicts with core services (like `Mail`), it is placed under `Odac.App` (e.g., `Odac.App.Mail`).
|
|
64
|
+
- **Separation**: Keep controllers focused on request/response; move all data processing and business logic to the `class/` directory.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-translations-i18n-skill
|
|
3
|
+
description: Internationalization patterns in ODAC for locale files, placeholders, and multilingual rendering workflows.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, i18n, translations, locale, placeholders, multilingual
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Backend Translations (i18n) Skill
|
|
9
|
+
|
|
10
|
+
ODAC provides built-in support for internationalization, allowing for easy multi-language application development.
|
|
11
|
+
|
|
12
|
+
## Architectural Approach
|
|
13
|
+
Translations are managed via JSON files in the `locale/` directory. The framework uses a flexible key-based system with support for placeholders.
|
|
14
|
+
|
|
15
|
+
## Core Rules
|
|
16
|
+
1. **Storage**: Place translation files in `locale/` (e.g., `en.json`, `tr.json`).
|
|
17
|
+
2. **Tag Usage**: Use `<odac translate>Key</odac>` in views.
|
|
18
|
+
3. **Placeholders**: Use `%s1`, `%s2` in JSON and nested `<odac var="...">` tags in views.
|
|
19
|
+
4. **Backend Access**: Use `Odac.__(key, ...args)` in controllers.
|
|
20
|
+
|
|
21
|
+
## Reference Patterns
|
|
22
|
+
|
|
23
|
+
### 1. View Translations
|
|
24
|
+
```html
|
|
25
|
+
<!-- Simple -->
|
|
26
|
+
<odac translate>Welcome</odac>
|
|
27
|
+
|
|
28
|
+
<!-- With Placeholders -->
|
|
29
|
+
<odac translate>Hello <odac var="user.name" /></odac>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Controller Translations
|
|
33
|
+
```javascript
|
|
34
|
+
const msg = Odac.__('Welcome back, %s1!', user.name);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 3. Locale JSON Structure
|
|
38
|
+
```json
|
|
39
|
+
// locale/tr.json
|
|
40
|
+
{
|
|
41
|
+
"Welcome": "Hoş Geldiniz",
|
|
42
|
+
"Hello %s1": "Merhaba %s1"
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Best Practices
|
|
47
|
+
- **Descriptive Keys**: Use meaningful keys like `nav.home` or `form.error.required`.
|
|
48
|
+
- **Html Safety**: By default, translations are escaped. Use the `raw` attribute (`<odac translate raw>`) only for trusted HTML.
|
|
49
|
+
- **Language Selection**: Set the language at the start of a request via `Odac.Lang.setLanguage('tr')`.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-utilities-skill
|
|
3
|
+
description: Practical ODAC utility patterns for string processing, hashing, encryption, and request flow control.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, utilities, strings, hashing, encryption, flow-control
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Backend Utilities Skill
|
|
9
|
+
|
|
10
|
+
String manipulation, hashing, and flow control.
|
|
11
|
+
|
|
12
|
+
## Core Rules
|
|
13
|
+
1. **Odac.Var**: A fluent interface for strings. Use it for `.slug()`, `.hash()`, `.is('email')`, and `.encrypt()`.
|
|
14
|
+
2. **Flow Control**:
|
|
15
|
+
- `Odac.abort(code)`: Terminate request with HTTP status (e.g., 404, 403).
|
|
16
|
+
- `Odac.direct(url)`: Redirect the user.
|
|
17
|
+
- `Odac.session(key, value)`: Manage session data.
|
|
18
|
+
|
|
19
|
+
## Reference Patterns
|
|
20
|
+
### 1. Odac.Var (String Power)
|
|
21
|
+
```javascript
|
|
22
|
+
const slug = Odac.Var('My Post Title').slug();
|
|
23
|
+
const isValid = Odac.Var('test@test.com').is('email');
|
|
24
|
+
const password = Odac.Var('secret').hash(); // BCrypt
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 2. Redirect and Abort
|
|
28
|
+
```javascript
|
|
29
|
+
if (!user) return Odac.abort(404);
|
|
30
|
+
if (!isLoggedIn) return Odac.direct('/login');
|
|
31
|
+
```
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-validation-skill
|
|
3
|
+
description: Fluent ODAC validation strategies for input hardening, brute-force protection, and standardized error responses.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, validation, fluent-api, input-security, brute-force, error-handling
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Backend Validation Skill
|
|
9
|
+
|
|
10
|
+
The `Validator` service provides a fluent, chainable API for securing user input and enforcing business rules.
|
|
11
|
+
|
|
12
|
+
## Architectural Approach
|
|
13
|
+
Validation should happen as early as possible in the request lifecycle. The `Validator` service handles automatic error formatting and frontend integration.
|
|
14
|
+
|
|
15
|
+
## Core Rules
|
|
16
|
+
1. **Chaining**: Use the fluent API: `.post(key).check(rules).message(msg)`.
|
|
17
|
+
2. **Brute Force**: Protect sensitive endpoints with `.brute(attempts)`.
|
|
18
|
+
3. **Automatic Errors**: Use `await validator.error()` to check status and `await validator.result()` to return standardized JSON.
|
|
19
|
+
4. **Inverse Rules**: Use `!` to invert any rule (e.g., `!required`).
|
|
20
|
+
|
|
21
|
+
## Reference Patterns
|
|
22
|
+
|
|
23
|
+
### 1. Standard Validation Chaining
|
|
24
|
+
```javascript
|
|
25
|
+
module.exports = async function (Odac) {
|
|
26
|
+
const validator = Odac.Validator;
|
|
27
|
+
|
|
28
|
+
validator
|
|
29
|
+
.post('email').check('required|email').message('Valid email required')
|
|
30
|
+
.post('password').check('required|minlen:8').message('Password too short');
|
|
31
|
+
|
|
32
|
+
if (await validator.error()) {
|
|
33
|
+
return validator.result('Please fix input errors');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Proceed with validated data
|
|
37
|
+
return validator.success('Success');
|
|
38
|
+
};
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 2. Custom Variable and Security Validation
|
|
42
|
+
```javascript
|
|
43
|
+
validator.var('age', userAge).check('numeric|min:18').message('Must be 18+');
|
|
44
|
+
|
|
45
|
+
// Security checks
|
|
46
|
+
validator.post('bio').check('xss').message('Malicious HTML detected');
|
|
47
|
+
validator.var('auth', null).check('usercheck').message('Authentication required');
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 3. Common Rules Reference
|
|
51
|
+
- `required`, `email`, `numeric`, `username`, `url`, `ip`, `json`.
|
|
52
|
+
- `len:X`, `minlen:X`, `maxlen:X`.
|
|
53
|
+
- `mindate:YYYY-MM-DD`, `maxdate:YYYY-MM-DD`.
|
|
54
|
+
- `regex:pattern`, `same:field`, `different:field`.
|
|
55
|
+
- `!disposable`: Blocks temporary email providers.
|
|
56
|
+
|
|
57
|
+
## Best Practices
|
|
58
|
+
- **Specific Messages**: Provide helpful error messages that guide the user.
|
|
59
|
+
- **Security First**: Use the `xss` rule for any user-generated content that will be rendered later.
|
|
60
|
+
- **Fail Fast**: Return the validation result immediately if `validator.error()` is true.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-views-templates-skill
|
|
3
|
+
description: ODAC server-side rendering guidelines for template performance, skeleton layouts, and safe output rendering.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, views, templates, ssr, xss-protection, skeleton, rendering
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Backend Views & Templates Skill
|
|
9
|
+
|
|
10
|
+
High-performance server-side rendering using ODAC's optimized template engine.
|
|
11
|
+
|
|
12
|
+
## Architectural Approach
|
|
13
|
+
Views in ODAC are logic-light but powerful. They support automatic XSS protection, high-performance looping, and server-side JavaScript execution via `<script:odac>`.
|
|
14
|
+
|
|
15
|
+
## Core Rules
|
|
16
|
+
1. **Skeleton Architecture**: Use `Odac.View.skeleton('name')` to wrap content in a layout.
|
|
17
|
+
2. **Data Binding**:
|
|
18
|
+
- `{{ key }}`: Escaped output (Standard).
|
|
19
|
+
- `{!! key !!}`: Raw output (Use with extreme caution).
|
|
20
|
+
3. **Conditionals**: Use `<odac:if condition="VAR"> ... </odac:if>`.
|
|
21
|
+
4. **Looping**: Use `<odac:for in="ARRAY" value="ITEM"> ... </odac:for>` or the performance-optimized `[[odac_for ...]]`.
|
|
22
|
+
5. **Server-Side JS**: Use `<script:odac>` for complex calculations during rendering.
|
|
23
|
+
|
|
24
|
+
## Reference Patterns
|
|
25
|
+
|
|
26
|
+
### 1. The Controller to View Flow
|
|
27
|
+
```javascript
|
|
28
|
+
// Controller
|
|
29
|
+
Odac.View.skeleton('main');
|
|
30
|
+
Odac.View.set({
|
|
31
|
+
title: 'Dashboard',
|
|
32
|
+
stats: { users: 150, orders: 45 }
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 2. Template Syntax Reference
|
|
37
|
+
```html
|
|
38
|
+
<!-- Display Variable -->
|
|
39
|
+
<h1>{{ title }}</h1>
|
|
40
|
+
|
|
41
|
+
<!-- Conditional -->
|
|
42
|
+
<odac:if condition="stats.users > 100">
|
|
43
|
+
<span class="badge">Popular!</span>
|
|
44
|
+
</odac:if>
|
|
45
|
+
|
|
46
|
+
<!-- Performance Loop -->
|
|
47
|
+
[[odac_for user in users]]
|
|
48
|
+
<li>{{ user.name }}</li>
|
|
49
|
+
[[odac_endfor]]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 3. Backend JavaScript (`<script:odac>`)
|
|
53
|
+
Perfect for calculations that shouldn't clutter the controller but are too complex for simple tags.
|
|
54
|
+
```html
|
|
55
|
+
<script:odac>
|
|
56
|
+
// Runs on the SERVER during rendering
|
|
57
|
+
const total = items.reduce((sum, i) => sum + i.price, 0);
|
|
58
|
+
const tax = total * 0.18;
|
|
59
|
+
</script:odac>
|
|
60
|
+
|
|
61
|
+
<p>Subtotal: ${{ total }}</p>
|
|
62
|
+
<p>Tax: ${{ tax }}</p>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Security Best Practices
|
|
66
|
+
- **Always use `{{ }}`**: Standard tags prevent XSS.
|
|
67
|
+
- **Limit `<script:odac>`**: Do not perform database queries or API calls inside views; keep them in the controller.
|
|
68
|
+
- **Partial Awareness**: Use `<odac:include view="path.to.view" />` for reusable components.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-core-skill
|
|
3
|
+
description: Core ODAC frontend architecture patterns based on actions, lifecycle hooks, and event-driven UI behavior.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: frontend, odac-js, actions, lifecycle, events, ui-architecture
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Frontend Core Skill
|
|
9
|
+
|
|
10
|
+
The foundational principles of the `odac.js` library for building reactive and interactive user interfaces.
|
|
11
|
+
|
|
12
|
+
## Architectural Approach
|
|
13
|
+
Frontend logic is organized into **Actions** using `Odac.action()`. This method centralizes event listeners, page-specific code, and lifecycle hooks.
|
|
14
|
+
|
|
15
|
+
## Core Rules
|
|
16
|
+
1. **Centralization**: All frontend logic should be defined within `Odac.action({})`.
|
|
17
|
+
2. **Lifecycle Hooks**:
|
|
18
|
+
- `start`: Fires once when the script initializes.
|
|
19
|
+
- `load`: Fires after every page load (including AJAX navigations).
|
|
20
|
+
3. **Page Scoping**: Use the `page: { name: fn }` object to isolate code to specific routes.
|
|
21
|
+
4. **Persistent Storage**: Use `odac.storage(key, value)` for a secure LocalStorage wrapper.
|
|
22
|
+
|
|
23
|
+
## Reference Patterns
|
|
24
|
+
|
|
25
|
+
### 1. Global Lifecycle & Page Scoping
|
|
26
|
+
```javascript
|
|
27
|
+
Odac.action({
|
|
28
|
+
// Global - runs on every page
|
|
29
|
+
load: function() {
|
|
30
|
+
console.log('Page ready');
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
// Scoped - runs only on the 'dashboard' page
|
|
34
|
+
page: {
|
|
35
|
+
dashboard: function(vars) {
|
|
36
|
+
console.log('Welcome to Dashboard', vars);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2. Event Handling
|
|
43
|
+
```javascript
|
|
44
|
+
Odac.action({
|
|
45
|
+
click: {
|
|
46
|
+
'#save-btn': function() {
|
|
47
|
+
alert('Saving...');
|
|
48
|
+
},
|
|
49
|
+
'.delete-item': 'fn.confirmDelete' // Reference a custom function
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
fn: {
|
|
53
|
+
confirmDelete: function() {
|
|
54
|
+
return confirm('Are you sure?');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 3. Data Utilities
|
|
61
|
+
```javascript
|
|
62
|
+
// Accessing data shared from backend (Odac.share)
|
|
63
|
+
const user = odac.data('user');
|
|
64
|
+
|
|
65
|
+
// Using Storage wrapper
|
|
66
|
+
odac.storage('theme', 'dark');
|
|
67
|
+
const theme = odac.storage('theme');
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Best Practices
|
|
71
|
+
- **Clean Selectors**: Use ID or specific data-attributes for event listeners to avoid conflicts.
|
|
72
|
+
- **No Inline JS**: Move all logic from HTML attributes (onclick, etc.) into `Odac.action()`.
|
|
73
|
+
- **Shared State**: Use `odac.data()` to pass complex objects from the backend once per request.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-forms-api-skill
|
|
3
|
+
description: AJAX form and API request patterns in odac.js for interactive UX and predictable frontend data flows.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: frontend, forms, ajax, api-requests, odac-get, odac-post
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Frontend Forms & API Skill
|
|
9
|
+
|
|
10
|
+
Handling AJAX form submissions and API requests.
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
1. **Forms**: Use `odac.form('#id', callback)` for AJAX submission.
|
|
14
|
+
2. **Requests**: Use `odac.get()` and `odac.post()` for manual requests.
|
|
15
|
+
3. **Realtime**: Handle WebSocket events using Hub structures in `Odac.action()`.
|
|
16
|
+
|
|
17
|
+
## Patterns
|
|
18
|
+
```javascript
|
|
19
|
+
// Form with automatic validation feedback
|
|
20
|
+
odac.form('#my-form', (res) => {
|
|
21
|
+
if(res.success) odac.visit('/done');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Simple API Check
|
|
25
|
+
odac.get('/api/status', (data) => {
|
|
26
|
+
console.log('Status:', data);
|
|
27
|
+
});
|
|
28
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-navigation-spa-skill
|
|
3
|
+
description: Single-page navigation patterns in odac.js for smooth transitions, route control, and lifecycle-safe execution.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: frontend, navigation, spa, ajax-navigation, page-lifecycle, transitions
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Frontend Navigation & SPA Skill
|
|
9
|
+
|
|
10
|
+
Smooth transitions and single-page application behavior using `odac.js`.
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
1. **Selection**: Enable via `Odac.action({ navigate: 'main' })`.
|
|
14
|
+
2. **Exclusion**: Use `data-navigate="false"` or `.no-navigate` class for full reloads.
|
|
15
|
+
3. **Lifecycle**: Use `load` and `page` events to run code after navigation.
|
|
16
|
+
|
|
17
|
+
## Patterns
|
|
18
|
+
```javascript
|
|
19
|
+
Odac.action({
|
|
20
|
+
navigate: {
|
|
21
|
+
update: 'main',
|
|
22
|
+
on: function(page, vars) {
|
|
23
|
+
console.log('Navigated to:', page);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-realtime-websocket-skill
|
|
3
|
+
description: Realtime frontend communication patterns in odac.js using shared WebSockets, SSE, and resilient reconnect behavior.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: frontend, realtime, websocket, sse, sharedworker, auto-reconnect
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Frontend Realtime & WebSocket Skill
|
|
9
|
+
|
|
10
|
+
Real-time bidirectional communication and server-sent events with high efficiency.
|
|
11
|
+
|
|
12
|
+
## Architectural Approach
|
|
13
|
+
ODAC prioritizes connection efficiency. `Odac.ws()` provides shared WebSocket connections across multiple browser tabs using `SharedWorker`, significantly reducing server load.
|
|
14
|
+
|
|
15
|
+
## Core Rules
|
|
16
|
+
1. **Shared Connections**: Always prefer `Odac.ws(url, { shared: true })` for scalable real-time apps.
|
|
17
|
+
2. **Auto-Reconnect**: Enabled by default; the client handles network drops automatically.
|
|
18
|
+
3. **SSE (Streaming)**: Use `new EventSource(url)` for one-way streams (e.g., live logs, notifications).
|
|
19
|
+
4. **JSON Native**: Messages sent and received via `Odac.ws` are automatically parsed/stringified.
|
|
20
|
+
|
|
21
|
+
## Reference Patterns
|
|
22
|
+
|
|
23
|
+
### 1. Shared WebSocket (Cross-Tab)
|
|
24
|
+
```javascript
|
|
25
|
+
// One connection shared across all open tabs
|
|
26
|
+
const ws = Odac.ws('/chat', { shared: true });
|
|
27
|
+
|
|
28
|
+
ws.on('message', (data) => {
|
|
29
|
+
console.log('Update received in all tabs:', data);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Sends message from current tab; others will receive the response
|
|
33
|
+
ws.send({ type: 'chat', text: 'Hello World' });
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 2. Standard WebSocket (Per-Tab)
|
|
37
|
+
```javascript
|
|
38
|
+
const ws = Odac.ws('/game', { shared: false });
|
|
39
|
+
ws.on('open', () => console.log('Game connected'));
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 3. Server-Sent Events (SSE)
|
|
43
|
+
```javascript
|
|
44
|
+
const source = new EventSource('/api/events');
|
|
45
|
+
source.onmessage = (event) => {
|
|
46
|
+
const data = JSON.parse(event.data);
|
|
47
|
+
updateUI(data);
|
|
48
|
+
};
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Best Practices
|
|
52
|
+
- **Resource Management**: Shared WebSocket automatically closes when the last tab using it is closed.
|
|
53
|
+
- **Fallback**: If `SharedWorker` is not supported (e.g., Safari), `Odac.ws` automatically falls back to a standard WebSocket.
|
|
54
|
+
- **Server-Side Hubs**: Ensure the backend uses `Odac.Hub` to send messages to the correct rooms or users.
|