odac 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/rules/memory.md +10 -1
- package/.github/workflows/release.yml +27 -1
- package/.husky/pre-push +3 -3
- package/.releaserc.js +2 -2
- package/CHANGELOG.md +32 -0
- package/bin/odac.js +22 -6
- package/client/odac.js +228 -167
- package/docs/backend/04-routing/09-websocket.md +14 -1
- package/package.json +13 -13
- package/src/Database.js +1 -1
- package/src/Mail.js +19 -9
- package/src/Odac.js +17 -14
- package/src/Request.js +5 -1
- package/src/Route.js +96 -29
- package/src/Validator.js +23 -14
- package/src/View.js +7 -7
- package/src/WebSocket.js +45 -12
- package/test/Odac.test.js +4 -2
- package/test/Route.test.js +104 -0
- package/test/WebSocket.test.js +141 -3
- package/.github/workflows/test-publish.yml +0 -36
package/.agent/rules/memory.md
CHANGED
|
@@ -28,6 +28,15 @@ trigger: always_on
|
|
|
28
28
|
- **Loop Optimization:** Use labeled loops (`label: for`) for efficient control flow in nested structures. Eliminate intermediate "flag" variables (`isMatch`, `found`) by using direct `return` or `continue label`.
|
|
29
29
|
- **Direct Returns:** Return a value as soon as it is determined. Avoid assigning to a temporary variable (e.g. `matchedUser`) and breaking the loop, unless post-loop processing is strictly necessary.
|
|
30
30
|
- **Async State Safety:** When an async function depends on mutable class state (like `pendingMiddlewares`), capture that state into a local `const` *synchronously* before triggering any async operations. This prevents race conditions where the state changes before the async task consumes it.
|
|
31
|
+
- **Async I/O Preference:** Prefer asynchronous file system operations (`fs.promises` or `await fs.promises.*`) over synchronous methods (`fs.readFileSync`, `fs.writeFileSync`) to prevent blocking the event loop and ensure high concurrency, especially in request handling paths.
|
|
31
32
|
|
|
32
33
|
## Dependency Management
|
|
33
|
-
- **Prefer Native Fetch:** Use the native `fetch` API for network requests in both Node.js (18+) and browser environments to reduce dependencies and bundle size.
|
|
34
|
+
- **Prefer Native Fetch:** Use the native `fetch` API for network requests in both Node.js (18+) and browser environments to reduce dependencies and bundle size.
|
|
35
|
+
|
|
36
|
+
## Naming & Text Conventions
|
|
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
|
+
|
|
39
|
+
## Testing & Validation
|
|
40
|
+
- **Mandatory Test Coverage:** Every new feature, method, or significant logic change MUST be accompanied by a corresponding unit or integration test.
|
|
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.
|
|
@@ -7,7 +7,7 @@ on:
|
|
|
7
7
|
paths-ignore:
|
|
8
8
|
- 'CHANGELOG.md'
|
|
9
9
|
- 'package.json'
|
|
10
|
-
- '.github/workflows
|
|
10
|
+
- '.github/workflows/**'
|
|
11
11
|
workflow_dispatch:
|
|
12
12
|
|
|
13
13
|
jobs:
|
|
@@ -56,6 +56,8 @@ jobs:
|
|
|
56
56
|
repository: odac-run/actions
|
|
57
57
|
token: ${{ secrets.GH_PAT }}
|
|
58
58
|
path: .github/odac-actions
|
|
59
|
+
ref: main
|
|
60
|
+
persist-credentials: false
|
|
59
61
|
|
|
60
62
|
- name: Generate Release Notes
|
|
61
63
|
id: ai_notes
|
|
@@ -70,11 +72,35 @@ jobs:
|
|
|
70
72
|
- name: Cleanup Actions
|
|
71
73
|
if: always()
|
|
72
74
|
run: rm -rf .github/odac-actions
|
|
75
|
+
|
|
76
|
+
- name: Update PR Title
|
|
77
|
+
uses: actions/github-script@v7
|
|
78
|
+
if: steps.ai_notes.outcome == 'success'
|
|
79
|
+
env:
|
|
80
|
+
AI_TITLE: ${{ steps.ai_notes.outputs.release-title }}
|
|
81
|
+
with:
|
|
82
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
83
|
+
script: |
|
|
84
|
+
const prs = await github.rest.repos.listPullRequestsAssociatedWithCommit({
|
|
85
|
+
owner: context.repo.owner,
|
|
86
|
+
repo: context.repo.repo,
|
|
87
|
+
commit_sha: context.sha,
|
|
88
|
+
});
|
|
89
|
+
if (prs.data.length > 0) {
|
|
90
|
+
await github.rest.pulls.update({
|
|
91
|
+
owner: context.repo.owner,
|
|
92
|
+
repo: context.repo.repo,
|
|
93
|
+
pull_number: prs.data[0].number,
|
|
94
|
+
title: process.env.AI_TITLE
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
73
98
|
- name: Update Release
|
|
74
99
|
uses: softprops/action-gh-release@v1
|
|
75
100
|
if: steps.ai_notes.outcome == 'success' && steps.version.outputs.version != ''
|
|
76
101
|
with:
|
|
77
102
|
tag_name: v${{ steps.version.outputs.version }}
|
|
103
|
+
name: ${{ steps.ai_notes.outputs.release-title }}
|
|
78
104
|
body_path: RELEASE_NOTE.md
|
|
79
105
|
draft: false
|
|
80
106
|
prerelease: false
|
package/.husky/pre-push
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env sh
|
|
2
2
|
. "$(dirname -- "$0")/_/husky.sh"
|
|
3
3
|
|
|
4
|
-
# Prevent pushing code with High/Critical vulnerabilities
|
|
5
|
-
echo "🛡️ Running Security Gate (npm audit)..."
|
|
4
|
+
# Prevent pushing code with High/Critical vulnerabilities in production dependencies
|
|
5
|
+
echo "🛡️ Running Production Security Gate (npm audit)..."
|
|
6
6
|
|
|
7
|
-
npm audit --audit-level=high
|
|
7
|
+
npm audit --audit-level=high --omit=dev
|
|
8
8
|
|
|
9
9
|
if [ $? -ne 0 ]; then
|
|
10
10
|
echo "❌ Security Check Failed! High vulnerabilities detected."
|
package/.releaserc.js
CHANGED
|
@@ -122,7 +122,7 @@ Powered by [⚡ ODAC](https://odac.run)
|
|
|
122
122
|
[
|
|
123
123
|
'@semantic-release/npm',
|
|
124
124
|
{
|
|
125
|
-
|
|
125
|
+
provenance: true
|
|
126
126
|
}
|
|
127
127
|
],
|
|
128
128
|
[
|
|
@@ -134,4 +134,4 @@ Powered by [⚡ ODAC](https://odac.run)
|
|
|
134
134
|
],
|
|
135
135
|
'@semantic-release/github'
|
|
136
136
|
]
|
|
137
|
-
}
|
|
137
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
### ⚙️ Engine Tuning
|
|
2
|
+
|
|
3
|
+
- Improve disposable domain cache management by relocating the cache path, ensuring directory existence, and standardizing error logging.
|
|
4
|
+
- 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
|
+
- remove unused `WebSocketClient` variable assignments in `WebSocket.test.js`
|
|
6
|
+
- streamline cache file reading by removing redundant access check.
|
|
7
|
+
- **validator:** Migrate file operations to `fs.promises` for asynchronous I/O and enhance security with explicit content sanitization.
|
|
8
|
+
|
|
9
|
+
### ⚡️ Performance Upgrades
|
|
10
|
+
|
|
11
|
+
- Optimize parametric route matching by implementing a two-phase, pre-indexed lookup strategy grouped by segment count.
|
|
12
|
+
|
|
13
|
+
### ✨ What's New
|
|
14
|
+
|
|
15
|
+
- Add configurable max payload size and message rate limiting options to WebSocket routes.
|
|
16
|
+
- Refined pre-push security audit to omit dev dependencies, optimized variable initializations, enhanced test mocks with `writeHead` and `finished` properties, introduced conditional `setTimeout` for request handling, and improved code formatting in client-side WebSocket and AJAX logic.
|
|
17
|
+
- update `.gitignore` to no longer ignore package manager lock files and to ignore the `storage/` directory
|
|
18
|
+
|
|
19
|
+
### 🛠️ Fixes & Improvements
|
|
20
|
+
|
|
21
|
+
- Enhance route directory not found error logging and add ODAC casing convention to memory rules.
|
|
22
|
+
- Set owner-only read/write permissions (0o600) for temporary cache files created during validation.
|
|
23
|
+
- suppress tailwind process stdout output
|
|
24
|
+
- Update default Unix socket path and enhance socket connection error handling with specific guidance for `ENOENT` errors.
|
|
25
|
+
- Update Tailwind CSS watch flag to '--watch=always' and refine child process stdio configuration.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
Powered by [⚡ ODAC](https://odac.run)
|
|
32
|
+
|
|
1
33
|
### agent
|
|
2
34
|
|
|
3
35
|
- Clarify logging strategies for development and production environments
|
package/bin/odac.js
CHANGED
|
@@ -117,6 +117,9 @@ async function run() {
|
|
|
117
117
|
if (cluster.isPrimary) {
|
|
118
118
|
const configs = getTailwindConfigs()
|
|
119
119
|
const tails = []
|
|
120
|
+
const names = configs.map(c => c.name).join(', ')
|
|
121
|
+
|
|
122
|
+
console.log(`🎨 \x1b[36mODAC Styles:\x1b[0m Watching for changes (${names})`)
|
|
120
123
|
|
|
121
124
|
configs.forEach(({input, cssOutput, name, isCustom}) => {
|
|
122
125
|
let tailwindProcess = null
|
|
@@ -125,19 +128,32 @@ async function run() {
|
|
|
125
128
|
const localCli = path.join(process.cwd(), 'node_modules', '.bin', 'tailwindcss')
|
|
126
129
|
const useLocal = fs.existsSync(localCli)
|
|
127
130
|
const cmd = useLocal ? localCli : 'npx'
|
|
128
|
-
const args = useLocal
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
console.log(`📂 Watching directory: ${process.cwd()}`)
|
|
131
|
+
const args = useLocal
|
|
132
|
+
? ['-i', input, '-o', cssOutput, '--watch=always']
|
|
133
|
+
: ['@tailwindcss/cli', '-i', input, '-o', cssOutput, '--watch=always']
|
|
132
134
|
|
|
133
135
|
tailwindProcess = spawn(cmd, args, {
|
|
134
|
-
stdio: '
|
|
136
|
+
stdio: ['pipe', 'ignore', 'pipe'],
|
|
135
137
|
shell: !useLocal, // Valid for npm/npx compatibility if local not found
|
|
136
138
|
cwd: process.cwd()
|
|
137
139
|
})
|
|
138
140
|
|
|
141
|
+
// Filter stderr: suppress status noise, forward only real errors
|
|
142
|
+
tailwindProcess.stderr.on('data', chunk => {
|
|
143
|
+
const raw = chunk.toString()
|
|
144
|
+
const lines = raw.split('\n')
|
|
145
|
+
for (const line of lines) {
|
|
146
|
+
// Strip ANSI escape codes to ensure reliable filtering
|
|
147
|
+
const clean = line.replace(/\x1B\[[0-9;]*[JKmsu]/g, '').trim()
|
|
148
|
+
|
|
149
|
+
if (!clean || clean.startsWith('Done in') || clean.startsWith('≈')) continue
|
|
150
|
+
|
|
151
|
+
process.stderr.write(`\x1b[31m[ODAC Style Error]\x1b[0m ${line}\n`)
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
|
|
139
155
|
tailwindProcess.on('error', err => {
|
|
140
|
-
console.error(`❌
|
|
156
|
+
console.error(`❌ \x1b[31m[ODAC Style Error]\x1b[0m Failed to start watcher for ${name}:`, err.message)
|
|
141
157
|
})
|
|
142
158
|
|
|
143
159
|
tailwindProcess.on('exit', code => {
|