odac 1.4.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 +3 -0
- package/.github/workflows/release.yml +1 -1
- package/CHANGELOG.md +26 -0
- package/README.md +10 -0
- package/bin/odac.js +190 -0
- package/docs/ai/skills/SKILL.md +4 -3
- package/docs/ai/skills/backend/authentication.md +7 -0
- package/docs/ai/skills/backend/config.md +7 -0
- package/docs/ai/skills/backend/controllers.md +7 -0
- package/docs/ai/skills/backend/cron.md +9 -2
- package/docs/ai/skills/backend/database.md +18 -2
- package/docs/ai/skills/backend/forms.md +8 -1
- package/docs/ai/skills/backend/ipc.md +7 -0
- package/docs/ai/skills/backend/mail.md +7 -0
- package/docs/ai/skills/backend/migrations.md +80 -0
- package/docs/ai/skills/backend/request_response.md +7 -0
- package/docs/ai/skills/backend/routing.md +7 -0
- package/docs/ai/skills/backend/storage.md +7 -0
- package/docs/ai/skills/backend/streaming.md +7 -0
- package/docs/ai/skills/backend/structure.md +8 -1
- package/docs/ai/skills/backend/translations.md +7 -0
- package/docs/ai/skills/backend/utilities.md +7 -0
- package/docs/ai/skills/backend/validation.md +7 -0
- package/docs/ai/skills/backend/views.md +7 -0
- package/docs/ai/skills/frontend/core.md +7 -0
- package/docs/ai/skills/frontend/forms.md +7 -0
- package/docs/ai/skills/frontend/navigation.md +7 -0
- package/docs/ai/skills/frontend/realtime.md +7 -0
- package/docs/backend/08-database/04-migrations.md +258 -37
- package/package.json +1 -1
- package/src/Auth.js +70 -44
- 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/template/schema/users.js +23 -0
- package/test/Auth.test.js +64 -3
- package/test/Config.test.js +7 -0
- package/test/Database/ConnectionFactory.test.js +80 -0
- package/test/Migration.test.js +943 -0
package/.agent/rules/memory.md
CHANGED
|
@@ -36,6 +36,9 @@ trigger: always_on
|
|
|
36
36
|
## Naming & Text Conventions
|
|
37
37
|
- **ODAC Casing:** Always write "ODAC" in uppercase letters when referring to the framework name in strings, comments, log messages, or user-facing text. **EXCEPTION:** The class name itself (`class Odac`) and variable references to it should remain `Odac` (PascalCase) as per code conventions.
|
|
38
38
|
|
|
39
|
+
## Documentation Standards
|
|
40
|
+
- **AI Skill Front Matter:** Every file under `docs/ai/skills/**/*.md` must start with YAML front matter containing `name`, `description`, and `metadata.tags`; values must be specific to that document's topic (never copied from generic examples).
|
|
41
|
+
|
|
39
42
|
## Testing & Validation
|
|
40
43
|
- **Mandatory Test Coverage:** Every new feature, method, or significant logic change MUST be accompanied by a corresponding unit or integration test.
|
|
41
44
|
- **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).
|
|
@@ -62,6 +62,7 @@ jobs:
|
|
|
62
62
|
with:
|
|
63
63
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
64
64
|
michelangelo: ${{ secrets.MICHELANGELO }}
|
|
65
|
+
version: ${{ steps.version.outputs.version }}
|
|
65
66
|
timeout-minutes: 15
|
|
66
67
|
continue-on-error: true
|
|
67
68
|
|
|
@@ -96,7 +97,6 @@ jobs:
|
|
|
96
97
|
if: steps.ai_notes.outcome == 'success' && steps.version.outputs.version != ''
|
|
97
98
|
with:
|
|
98
99
|
tag_name: v${{ steps.version.outputs.version }}
|
|
99
|
-
name: ${{ steps.ai_notes.outputs.release-title }}
|
|
100
100
|
body_path: RELEASE_NOTE.md
|
|
101
101
|
draft: false
|
|
102
102
|
prerelease: false
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
### doc
|
|
2
|
+
|
|
3
|
+
- enhance AI skills documentation with structured YAML front matter and detailed descriptions
|
|
4
|
+
|
|
5
|
+
### ⚙️ Engine Tuning
|
|
6
|
+
|
|
7
|
+
- **database:** centralize knex connection bootstrap for runtime and CLI
|
|
8
|
+
|
|
9
|
+
### 📚 Documentation
|
|
10
|
+
|
|
11
|
+
- add section for loading and updating AI skills in projects
|
|
12
|
+
|
|
13
|
+
### 🛠️ Fixes & Improvements
|
|
14
|
+
|
|
15
|
+
- **auth:** improve token rotation logic and ensure proper cookie attributes
|
|
16
|
+
- **cli:** parse .env values consistently in migration loader
|
|
17
|
+
- **config:** update interpolation regex to support variable names with hyphens
|
|
18
|
+
- **migration:** normalize column-level unique constraints and enhance idempotency in migrations
|
|
19
|
+
- **release:** add version output to release notes and update release title condition
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
Powered by [⚡ ODAC](https://odac.run)
|
|
26
|
+
|
|
1
27
|
### ⚙️ Engine Tuning
|
|
2
28
|
|
|
3
29
|
- Extract MIME type definitions into a dedicated module.
|
package/README.md
CHANGED
|
@@ -53,6 +53,16 @@ cd my-app
|
|
|
53
53
|
npm run dev
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
## 🤖 AI Skills in Projects
|
|
57
|
+
|
|
58
|
+
Load or update ODAC skills from your project root with:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npx odac skills
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This command syncs built-in skills to your selected AI tool folder and can be re-run anytime to update them.
|
|
65
|
+
|
|
56
66
|
## 📂 Project Structure
|
|
57
67
|
|
|
58
68
|
```
|
package/bin/odac.js
CHANGED
|
@@ -5,6 +5,8 @@ const path = require('node:path')
|
|
|
5
5
|
const readline = require('node:readline')
|
|
6
6
|
const {execSync, spawn} = require('node:child_process')
|
|
7
7
|
const cluster = require('node:cluster')
|
|
8
|
+
const Env = require('../src/Env')
|
|
9
|
+
const {buildConnections} = require('../src/Database/ConnectionFactory')
|
|
8
10
|
|
|
9
11
|
const command = process.argv[2]
|
|
10
12
|
const args = process.argv.slice(3)
|
|
@@ -227,6 +229,188 @@ async function manageSkills(targetDir = process.cwd()) {
|
|
|
227
229
|
}
|
|
228
230
|
}
|
|
229
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Bootstraps the database and migration engine, then executes the requested migration command.
|
|
234
|
+
* Why: Migration commands need DB connections but not the full server stack.
|
|
235
|
+
* @param {string} cmd - The migration subcommand
|
|
236
|
+
* @param {string[]} cliArgs - CLI arguments (e.g. --db=analytics)
|
|
237
|
+
*/
|
|
238
|
+
async function runMigration(cmd, cliArgs) {
|
|
239
|
+
const projectDir = process.cwd()
|
|
240
|
+
const envPath = path.join(projectDir, '.env')
|
|
241
|
+
const configPath = path.join(projectDir, 'odac.json')
|
|
242
|
+
|
|
243
|
+
// Load .env
|
|
244
|
+
if (fs.existsSync(envPath)) {
|
|
245
|
+
const envContent = fs.readFileSync(envPath, 'utf8')
|
|
246
|
+
envContent.split('\n').forEach(line => {
|
|
247
|
+
line = line.trim()
|
|
248
|
+
if (!line || line.startsWith('#')) return
|
|
249
|
+
const idx = line.indexOf('=')
|
|
250
|
+
if (idx === -1) return
|
|
251
|
+
const key = line.slice(0, idx).trim()
|
|
252
|
+
const value = Env._parseValue(line.slice(idx + 1).trim())
|
|
253
|
+
if (process.env[key] === undefined) process.env[key] = value
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Load config
|
|
258
|
+
if (!fs.existsSync(configPath)) {
|
|
259
|
+
console.error('❌ No odac.json found in current directory.')
|
|
260
|
+
process.exit(1)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
let config
|
|
264
|
+
try {
|
|
265
|
+
let raw = fs.readFileSync(configPath, 'utf8')
|
|
266
|
+
config = JSON.parse(raw)
|
|
267
|
+
// Interpolate env vars safely by traversing parsed object values.
|
|
268
|
+
const interpolateConfig = input => {
|
|
269
|
+
if (typeof input === 'string') {
|
|
270
|
+
return input.replace(/\$\{([^{}]+)\}/g, (_, key) => process.env[key] || '')
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (Array.isArray(input)) {
|
|
274
|
+
return input.map(item => interpolateConfig(item))
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (input && typeof input === 'object') {
|
|
278
|
+
const output = {}
|
|
279
|
+
for (const key of Object.keys(input)) {
|
|
280
|
+
output[key] = interpolateConfig(input[key])
|
|
281
|
+
}
|
|
282
|
+
return output
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return input
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
config = interpolateConfig(config)
|
|
289
|
+
} catch (err) {
|
|
290
|
+
console.error('❌ Failed to parse odac.json:', err.message)
|
|
291
|
+
process.exit(1)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const dbConfig = config.database
|
|
295
|
+
if (!dbConfig) {
|
|
296
|
+
console.error('❌ No database configuration found in odac.json.')
|
|
297
|
+
process.exit(1)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const connections = buildConnections(dbConfig)
|
|
301
|
+
|
|
302
|
+
for (const key of Object.keys(connections)) {
|
|
303
|
+
try {
|
|
304
|
+
await connections[key].raw('SELECT 1')
|
|
305
|
+
} catch (e) {
|
|
306
|
+
console.error(`❌ Failed to connect to '${key}' database:`, e.message)
|
|
307
|
+
process.exit(1)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Parse --db flag
|
|
312
|
+
const dbFlag = cliArgs.find(a => a.startsWith('--db='))
|
|
313
|
+
const options = dbFlag ? {db: dbFlag.split('=')[1]} : {}
|
|
314
|
+
|
|
315
|
+
// Initialize migration engine
|
|
316
|
+
const Migration = require('../src/Database/Migration')
|
|
317
|
+
Migration.init(projectDir, connections)
|
|
318
|
+
|
|
319
|
+
try {
|
|
320
|
+
if (cmd === 'migrate') {
|
|
321
|
+
console.log('🔄 Running migrations...\n')
|
|
322
|
+
const summary = await Migration.migrate(options)
|
|
323
|
+
printMigrationSummary(summary)
|
|
324
|
+
} else if (cmd === 'migrate:status') {
|
|
325
|
+
console.log('📋 Migration Status (dry-run):\n')
|
|
326
|
+
const summary = await Migration.status(options)
|
|
327
|
+
printMigrationSummary(summary)
|
|
328
|
+
} else if (cmd === 'migrate:rollback') {
|
|
329
|
+
console.log('⏪ Rolling back last batch...\n')
|
|
330
|
+
const summary = await Migration.rollback(options)
|
|
331
|
+
printMigrationSummary(summary)
|
|
332
|
+
} else if (cmd === 'migrate:snapshot') {
|
|
333
|
+
console.log('📸 Generating schema files from database...\n')
|
|
334
|
+
const result = await Migration.snapshot(options)
|
|
335
|
+
for (const [key, files] of Object.entries(result)) {
|
|
336
|
+
console.log(` \x1b[36m${key}\x1b[0m: ${files.length} schema file(s) generated`)
|
|
337
|
+
for (const f of files) {
|
|
338
|
+
console.log(` → ${path.relative(projectDir, f)}`)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
console.log('\n✅ Snapshot complete.')
|
|
342
|
+
}
|
|
343
|
+
} catch (err) {
|
|
344
|
+
console.error('❌ Migration error:', err.message)
|
|
345
|
+
process.exit(1)
|
|
346
|
+
} finally {
|
|
347
|
+
for (const conn of Object.values(connections)) {
|
|
348
|
+
await conn.destroy()
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Formats and prints migration operation summary to stdout.
|
|
355
|
+
* @param {object} summary - Migration result per connection
|
|
356
|
+
*/
|
|
357
|
+
function printMigrationSummary(summary) {
|
|
358
|
+
let totalOps = 0
|
|
359
|
+
|
|
360
|
+
for (const [key, result] of Object.entries(summary)) {
|
|
361
|
+
console.log(` \x1b[36m[${key}]\x1b[0m`)
|
|
362
|
+
|
|
363
|
+
const allOps = [...(result.schema || []), ...(result.files || []), ...(result.seeds || [])]
|
|
364
|
+
|
|
365
|
+
if (allOps.length === 0) {
|
|
366
|
+
console.log(' Nothing to do.')
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
for (const op of allOps) {
|
|
370
|
+
totalOps++
|
|
371
|
+
const label = formatOp(op)
|
|
372
|
+
console.log(` ${label}`)
|
|
373
|
+
}
|
|
374
|
+
console.log('')
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
console.log(totalOps > 0 ? `✅ ${totalOps} operation(s) completed.` : '✅ Everything is up to date.')
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Formats a single migration operation for CLI display.
|
|
382
|
+
* @param {object} op - Operation descriptor
|
|
383
|
+
* @returns {string} Formatted label
|
|
384
|
+
*/
|
|
385
|
+
function formatOp(op) {
|
|
386
|
+
switch (op.type) {
|
|
387
|
+
case 'create_table':
|
|
388
|
+
return `\x1b[32m+ CREATE TABLE\x1b[0m ${op.table}`
|
|
389
|
+
case 'add_column':
|
|
390
|
+
return `\x1b[32m+ ADD COLUMN\x1b[0m ${op.table}.${op.column}`
|
|
391
|
+
case 'drop_column':
|
|
392
|
+
return `\x1b[31m- DROP COLUMN\x1b[0m ${op.table}.${op.column}`
|
|
393
|
+
case 'alter_column':
|
|
394
|
+
return `\x1b[33m~ ALTER COLUMN\x1b[0m ${op.table}.${op.column}`
|
|
395
|
+
case 'add_index':
|
|
396
|
+
return `\x1b[32m+ ADD INDEX\x1b[0m ${op.table} (${op.index.columns.join(', ')})`
|
|
397
|
+
case 'drop_index':
|
|
398
|
+
return `\x1b[31m- DROP INDEX\x1b[0m ${op.table} (${op.index.columns.join(', ')})`
|
|
399
|
+
case 'pending_file':
|
|
400
|
+
return `\x1b[33m⏳ PENDING\x1b[0m ${op.name}`
|
|
401
|
+
case 'applied_file':
|
|
402
|
+
return `\x1b[32m✓ APPLIED\x1b[0m ${op.name}`
|
|
403
|
+
case 'rolled_back':
|
|
404
|
+
return `\x1b[33m↩ ROLLED BACK\x1b[0m ${op.name}`
|
|
405
|
+
case 'seed_insert':
|
|
406
|
+
return `\x1b[32m+ SEED INSERT\x1b[0m ${op.table} (${op.key})`
|
|
407
|
+
case 'seed_update':
|
|
408
|
+
return `\x1b[33m~ SEED UPDATE\x1b[0m ${op.table} (${op.key})`
|
|
409
|
+
default:
|
|
410
|
+
return ` ${op.type}`
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
230
414
|
async function run() {
|
|
231
415
|
if (command === 'init') {
|
|
232
416
|
const projectName = args[0] || '.'
|
|
@@ -376,6 +560,8 @@ async function run() {
|
|
|
376
560
|
require('../index.js')
|
|
377
561
|
} else if (command === 'skills') {
|
|
378
562
|
await manageSkills()
|
|
563
|
+
} else if (command === 'migrate' || command === 'migrate:status' || command === 'migrate:rollback' || command === 'migrate:snapshot') {
|
|
564
|
+
await runMigration(command, args)
|
|
379
565
|
} else {
|
|
380
566
|
console.log('Usage:')
|
|
381
567
|
console.log(' npx odac init (Interactive mode)')
|
|
@@ -384,6 +570,10 @@ async function run() {
|
|
|
384
570
|
console.log(' npx odac build (Production build)')
|
|
385
571
|
console.log(' npx odac start (Start server)')
|
|
386
572
|
console.log(' npx odac skills (Sync AI Agent skills)')
|
|
573
|
+
console.log(' npx odac migrate (Run pending migrations)')
|
|
574
|
+
console.log(' npx odac migrate:status (Show pending changes)')
|
|
575
|
+
console.log(' npx odac migrate:rollback (Rollback last batch)')
|
|
576
|
+
console.log(' npx odac migrate:snapshot (Reverse-engineer DB to schema/)')
|
|
387
577
|
}
|
|
388
578
|
|
|
389
579
|
rl.close()
|
package/docs/ai/skills/SKILL.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: odac-framework
|
|
3
|
-
description: Comprehensive AI
|
|
2
|
+
name: odac-framework-skill-catalog
|
|
3
|
+
description: Comprehensive ODAC backend and frontend AI skill index for architecture, security, and high-performance application development.
|
|
4
4
|
metadata:
|
|
5
|
-
tags:
|
|
5
|
+
tags: odac, skills, backend, frontend, architecture, security, performance
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
## When to use
|
|
@@ -22,6 +22,7 @@ Read the specific rule files based on whether you are working on the Backend or
|
|
|
22
22
|
- [backend/forms.md](backend/forms.md) - Form processing and Validation logic
|
|
23
23
|
- [backend/ipc.md](backend/ipc.md) - Inter-Process Communication and state sharing
|
|
24
24
|
- [backend/mail.md](backend/mail.md) - Transactional email sending
|
|
25
|
+
- [backend/migrations.md](backend/migrations.md) - Schema-first, auto-run, cluster-safe DB migrations
|
|
25
26
|
- [backend/request_response.md](backend/request_response.md) - Handling Odac.Request and Odac.Response
|
|
26
27
|
- [backend/routing.md](backend/routing.md) - Route definitions, Middlewares, and Error Pages
|
|
27
28
|
- [backend/storage.md](backend/storage.md) - Persistent key-value storage (LMDB)
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-authentication-realtime-skill
|
|
3
|
+
description: Secure ODAC authentication patterns for sessions, guards, passwordless flows, and realtime channel protection.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, authentication, session, auth-guard, magic-link, realtime, security
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Backend Authentication & Realtime Skill
|
|
2
9
|
|
|
3
10
|
Secure user authentication, session management, and bidirectional communication.
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-configuration-skill
|
|
3
|
+
description: ODAC configuration standards for odac.json usage, environment variable mapping, and secure runtime settings.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, configuration, odac-json, environment, secrets, settings
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Backend Configuration Skill
|
|
2
9
|
|
|
3
10
|
Managing application settings using `odac.json` and environment variables.
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-controllers-skill
|
|
3
|
+
description: Best practices for ODAC controller architecture, class-based routing, and clean request handling boundaries.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, controllers, class-based, route-mapping, architecture, maintainability
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Backend Controllers Skill
|
|
2
9
|
|
|
3
10
|
Controllers are the bridge between routes and views/services. This skill covers how to write clean, professional controllers in ODAC.
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-cron-jobs-skill
|
|
3
|
+
description: Reliable ODAC cron scheduling patterns for background automation, timing control, and safe execution design.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, cron, scheduler, background-jobs, automation, timing
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Backend Cron Jobs Skill
|
|
2
9
|
|
|
3
10
|
ODAC provides a built-in cron system for automating background tasks without external dependencies.
|
|
@@ -21,14 +28,14 @@ Odac.Route.cron('cleanup').at('03:00'); // Runs daily at 03:00
|
|
|
21
28
|
// controller/cron/cleanup.js
|
|
22
29
|
module.exports = async (Odac) => {
|
|
23
30
|
console.log('Running nightly cleanup...');
|
|
24
|
-
await Odac.
|
|
31
|
+
await Odac.DB.table('logs').where('created_at', '<', 'NOW() - INTERVAL 30 DAY').delete();
|
|
25
32
|
};
|
|
26
33
|
```
|
|
27
34
|
|
|
28
35
|
### 2. Inline Function Cron
|
|
29
36
|
```javascript
|
|
30
37
|
Odac.Route.cron(async () => {
|
|
31
|
-
const stats = await Odac.
|
|
38
|
+
const stats = await Odac.DB.table('orders').count();
|
|
32
39
|
console.log('Current orders:', stats);
|
|
33
40
|
}).everyHour(1);
|
|
34
41
|
```
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-database-skill
|
|
3
|
+
description: High-performance ODAC database querying patterns using the built-in query builder with secure and efficient data access.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, database, query-builder, sql, indexing, performance, security
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Backend Database Skill
|
|
2
9
|
|
|
3
10
|
High-performance database operations using the ODAC Query Builder.
|
|
@@ -9,13 +16,22 @@ High-performance database operations using the ODAC Query Builder.
|
|
|
9
16
|
|
|
10
17
|
## Patterns
|
|
11
18
|
```javascript
|
|
12
|
-
const user = await Odac.
|
|
19
|
+
const user = await Odac.DB.table('users')
|
|
13
20
|
.select('id', 'name', 'email')
|
|
14
21
|
.where('status', 'active')
|
|
15
22
|
.first();
|
|
16
23
|
|
|
17
|
-
await Odac.
|
|
24
|
+
await Odac.DB.table('posts').insert({
|
|
18
25
|
title: 'Hello',
|
|
19
26
|
user_id: 1
|
|
20
27
|
});
|
|
21
28
|
```
|
|
29
|
+
|
|
30
|
+
## Migration Awareness
|
|
31
|
+
1. **Schema-First**: Structural DB changes must be defined in `schema/*.js`.
|
|
32
|
+
2. **Auto-Migrate**: Migrations run automatically at startup from `Database.init()`.
|
|
33
|
+
3. **Cluster-Safe**: Migration execution is limited to primary process (`cluster.isPrimary`).
|
|
34
|
+
4. **Indexes**: Keep index definitions in schema so add/drop is managed automatically.
|
|
35
|
+
5. **Data Changes**: Use `migration/*.js` only for one-time data transformation.
|
|
36
|
+
|
|
37
|
+
See: [migrations.md](./migrations.md)
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-forms-validation-skill
|
|
3
|
+
description: Secure ODAC form processing workflow with validation, CSRF protection, and safe request-to-database handling.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, forms, validation, csrf, input-security, request-processing
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Backend Forms & Validation Skill
|
|
2
9
|
|
|
3
10
|
Processing form data securely and validating inputs.
|
|
4
11
|
|
|
5
12
|
## Rules
|
|
6
13
|
1. **Validator**: Always use `Odac.Validator` for input.
|
|
7
|
-
2. **Auto-save**: Use `Odac.
|
|
14
|
+
2. **Auto-save**: Use `Odac.DB.table().save(Odac.Request.post())` for quick inserts.
|
|
8
15
|
3. **CSRF**: Ensure `{{ TOKEN }}` is in your HTML forms.
|
|
9
16
|
|
|
10
17
|
## Patterns
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-ipc-skill
|
|
3
|
+
description: ODAC inter-process communication guidance for memory and Redis drivers, shared state, and distributed coordination.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, ipc, redis, cluster, distributed-state, synchronization
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Backend IPC (Inter-Process Communication) Skill
|
|
2
9
|
|
|
3
10
|
ODAC provides a built-in IPC system to share data and sync states across application workers or multiple servers.
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-mail-skill
|
|
3
|
+
description: Transactional email integration patterns in ODAC using fluent mail APIs, templating, and transport configuration.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, mail, smtp, transactional-email, templating, notifications
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Backend Mail Skill
|
|
2
9
|
|
|
3
10
|
Sending transactional emails using the fluent `Odac.Mail` service.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-migrations-skill
|
|
3
|
+
description: Schema-first ODAC migration strategy for deterministic database evolution, index sync, and cluster-safe execution.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, migrations, schema, database-evolution, indexes, cluster-safety
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Backend Migrations Skill
|
|
9
|
+
|
|
10
|
+
Schema-first, zero-config migration strategy for ODAC.
|
|
11
|
+
|
|
12
|
+
## Architectural Approach
|
|
13
|
+
ODAC migrations are **declarative**. The `schema/` directory is the single source of truth for final DB state. The migration engine diffs desired schema vs current DB and applies create/alter/drop operations automatically.
|
|
14
|
+
|
|
15
|
+
## Core Rules
|
|
16
|
+
1. **Source of Truth**: Always update `schema/*.js` files, not historical migration chains, for structural changes.
|
|
17
|
+
2. **Auto Execution**: Migrations run automatically during app startup via `Database.init()`.
|
|
18
|
+
3. **Cluster Safety**: Auto-migration runs only on `cluster.isPrimary` to prevent race conditions.
|
|
19
|
+
4. **Index Sync**: Define indexes in schema; engine adds/removes them automatically.
|
|
20
|
+
5. **Drop Behavior**: If a column/index is removed from schema, it is removed from DB on next startup.
|
|
21
|
+
6. **Seeds**: Use `seed` + `seedKey` for idempotent reference data.
|
|
22
|
+
7. **Data Transformations**: Use imperative files under `migration/` only for one-time data migration logic.
|
|
23
|
+
|
|
24
|
+
## Reference Patterns
|
|
25
|
+
### 1. Schema File (Final State)
|
|
26
|
+
```javascript
|
|
27
|
+
// schema/users.js
|
|
28
|
+
'use strict'
|
|
29
|
+
|
|
30
|
+
module.exports = {
|
|
31
|
+
columns: {
|
|
32
|
+
id: {type: 'increments'},
|
|
33
|
+
email: {type: 'string', length: 255, nullable: false},
|
|
34
|
+
role: {type: 'enum', values: ['admin', 'user'], default: 'user'},
|
|
35
|
+
timestamps: {type: 'timestamps'}
|
|
36
|
+
},
|
|
37
|
+
indexes: [
|
|
38
|
+
{columns: ['email'], unique: true}
|
|
39
|
+
],
|
|
40
|
+
seed: [
|
|
41
|
+
{email: 'admin@example.com', role: 'admin'}
|
|
42
|
+
],
|
|
43
|
+
seedKey: 'email'
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2. Multi-Database Layout
|
|
48
|
+
```
|
|
49
|
+
schema/
|
|
50
|
+
users.js # default DB
|
|
51
|
+
analytics/
|
|
52
|
+
events.js # analytics DB
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 3. Imperative Data Migration (One-Time)
|
|
56
|
+
```javascript
|
|
57
|
+
// migration/20260225_001_backfill_roles.js
|
|
58
|
+
module.exports = {
|
|
59
|
+
async up(db) {
|
|
60
|
+
await db('users').whereNull('role').update({role: 'user'})
|
|
61
|
+
},
|
|
62
|
+
async down(db) {
|
|
63
|
+
await db('users').where('role', 'user').update({role: null})
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 4. CLI Operations
|
|
69
|
+
```bash
|
|
70
|
+
npx odac migrate
|
|
71
|
+
npx odac migrate:status
|
|
72
|
+
npx odac migrate:rollback
|
|
73
|
+
npx odac migrate:snapshot
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Performance and Safety Notes
|
|
77
|
+
- Keep schema declarations deterministic and minimal.
|
|
78
|
+
- Prefer additive changes; drops are destructive and should be intentional.
|
|
79
|
+
- Ensure high-cardinality lookup columns are indexed in schema definitions.
|
|
80
|
+
- For very large tables, plan expensive column rewrites as dedicated data migrations.
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-request-response-skill
|
|
3
|
+
description: ODAC request parsing and response composition patterns for consistent, secure, and predictable API behavior.
|
|
4
|
+
metadata:
|
|
5
|
+
tags: backend, request, response, headers, status-codes, json, api
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Backend Request & Response Skill
|
|
2
9
|
|
|
3
10
|
Handling incoming data and sending structured responses.
|
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
|
|
1
8
|
# Backend Routing & Middleware Skill
|
|
2
9
|
|
|
3
10
|
Routing manages the request pipeline, directing URLs to controllers while applying security and business logic via middlewares.
|
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
|
|
1
8
|
# Backend Persistent Storage Skill
|
|
2
9
|
|
|
3
10
|
ODAC provides a high-performance, embedded key-value store using LMDB, exposed via `Odac.Storage`.
|
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
|
|
1
8
|
# Backend Streaming API Skill
|
|
2
9
|
|
|
3
10
|
Real-time data streaming using Server-Sent Events (SSE).
|
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
|
|
1
8
|
# Backend Structure & Services Skill
|
|
2
9
|
|
|
3
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.
|
|
@@ -31,7 +38,7 @@ class User {
|
|
|
31
38
|
|
|
32
39
|
async getProfile(id) {
|
|
33
40
|
// Access database or auth via this.Odac
|
|
34
|
-
return await this.Odac.
|
|
41
|
+
return await this.Odac.DB.table('users').where('id', id).first();
|
|
35
42
|
}
|
|
36
43
|
}
|
|
37
44
|
module.exports = User;
|
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
|
|
1
8
|
# Backend Translations (i18n) Skill
|
|
2
9
|
|
|
3
10
|
ODAC provides built-in support for internationalization, allowing for easy multi-language application development.
|
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
|
|
1
8
|
# Backend Utilities Skill
|
|
2
9
|
|
|
3
10
|
String manipulation, hashing, and flow control.
|
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
|
|
1
8
|
# Backend Validation Skill
|
|
2
9
|
|
|
3
10
|
The `Validator` service provides a fluent, chainable API for securing user input and enforcing business rules.
|
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
|
|
1
8
|
# Backend Views & Templates Skill
|
|
2
9
|
|
|
3
10
|
High-performance server-side rendering using ODAC's optimized template engine.
|
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
|
|
1
8
|
# Frontend Core Skill
|
|
2
9
|
|
|
3
10
|
The foundational principles of the `odac.js` library for building reactive and interactive user interfaces.
|