@stonyx/events 0.1.1-beta.1 → 0.1.1-beta.11
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/README.md +57 -18
- package/package.json +4 -3
- package/src/main.js +12 -0
- package/.claude/project-structure.md +0 -421
- package/.github/workflows/ci.yml +0 -16
- package/.github/workflows/publish.yml +0 -35
- package/.gitignore +0 -9
- package/.npmignore +0 -2
- package/pnpm-lock.yaml +0 -134
- package/stonyx-bootstrap.cjs +0 -9
package/README.md
CHANGED
|
@@ -19,36 +19,65 @@ npm install @stonyx/events
|
|
|
19
19
|
|
|
20
20
|
## Usage
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
import Events from '@stonyx/events';
|
|
22
|
+
### Option 1: Convenience Functions (Recommended)
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
The package exports convenience functions that use a singleton instance:
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
import { setup, subscribe, emit, once } from '@stonyx/events';
|
|
26
28
|
|
|
27
29
|
// Register available events
|
|
28
|
-
|
|
30
|
+
setup(['userLogin', 'userLogout', 'dataChange']);
|
|
29
31
|
|
|
30
32
|
// Subscribe to events
|
|
31
|
-
|
|
33
|
+
subscribe('userLogin', (user) => {
|
|
32
34
|
console.log(`${user.name} logged in`);
|
|
33
35
|
});
|
|
34
36
|
|
|
35
37
|
// Subscribe once (auto-unsubscribe after first fire)
|
|
36
|
-
|
|
38
|
+
once('dataChange', () => {
|
|
37
39
|
console.log('Data changed for the first time');
|
|
38
40
|
});
|
|
39
41
|
|
|
40
42
|
// Emit events
|
|
41
|
-
|
|
43
|
+
emit('userLogin', { name: 'Alice' });
|
|
42
44
|
|
|
43
45
|
// Unsubscribe
|
|
44
|
-
const unsub =
|
|
46
|
+
const unsub = subscribe('userLogout', handler);
|
|
45
47
|
unsub(); // Remove subscription
|
|
46
48
|
```
|
|
47
49
|
|
|
50
|
+
### Option 2: Class-based (Advanced)
|
|
51
|
+
|
|
52
|
+
You can also instantiate the Events class directly for more control:
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
import Events from '@stonyx/events';
|
|
56
|
+
|
|
57
|
+
const events = new Events();
|
|
58
|
+
|
|
59
|
+
// Register available events
|
|
60
|
+
events.setup(['userLogin', 'userLogout', 'dataChange']);
|
|
61
|
+
|
|
62
|
+
// Subscribe to events
|
|
63
|
+
events.subscribe('userLogin', (user) => {
|
|
64
|
+
console.log(`${user.name} logged in`);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Emit events
|
|
68
|
+
events.emit('userLogin', { name: 'Alice' });
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Note:** The Events class uses a singleton pattern, so all instances share the same event registry.
|
|
72
|
+
|
|
48
73
|
## API Reference
|
|
49
74
|
|
|
50
|
-
|
|
51
|
-
|
|
75
|
+
### Convenience Functions (Exported)
|
|
76
|
+
|
|
77
|
+
All functions use a singleton Events instance:
|
|
78
|
+
|
|
79
|
+
| Function | Parameters | Description |
|
|
80
|
+
|----------|-----------|-------------|
|
|
52
81
|
| `setup()` | `eventNames: string[]` | Register available event names. Events must be registered before subscribing. |
|
|
53
82
|
| `subscribe()` | `event: string, callback: Function` | Subscribe to an event. Returns an unsubscribe function. |
|
|
54
83
|
| `once()` | `event: string, callback: Function` | Subscribe to an event once. Auto-unsubscribes after first emit. |
|
|
@@ -57,16 +86,26 @@ unsub(); // Remove subscription
|
|
|
57
86
|
| `clear()` | `event: string` | Remove all subscriptions for an event. |
|
|
58
87
|
| `reset()` | none | Clear all subscriptions and events. Useful for testing. |
|
|
59
88
|
|
|
60
|
-
|
|
89
|
+
### Events Class Methods
|
|
61
90
|
|
|
62
|
-
|
|
91
|
+
If using the class directly, all methods above are available as instance methods:
|
|
63
92
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
93
|
+
```javascript
|
|
94
|
+
import Events from '@stonyx/events';
|
|
95
|
+
const events = new Events();
|
|
96
|
+
|
|
97
|
+
events.setup(['myEvent']);
|
|
98
|
+
events.subscribe('myEvent', handler);
|
|
99
|
+
events.emit('myEvent', data);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## How It Works
|
|
103
|
+
|
|
104
|
+
- The `Events` class uses a static `instance` property to enforce a singleton -- every `new Events()` returns the same object
|
|
105
|
+
- Event names are held in a `registeredEvents` Set; subscribing to an unregistered name throws immediately, catching typos early
|
|
106
|
+
- Subscribers are stored in a `Map<string, Set<Function>>`, so duplicate function references are automatically deduplicated
|
|
107
|
+
- `emit()` is async: it maps every subscriber into a `Promise`, wraps each in a try/catch for error isolation, and awaits them all with `Promise.all()`
|
|
108
|
+
- `once()` wraps the callback in a self-removing wrapper that calls `unsubscribe` before invoking the original handler
|
|
70
109
|
|
|
71
110
|
## License
|
|
72
111
|
|
package/package.json
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
"keywords": [
|
|
4
4
|
"stonyx-module"
|
|
5
5
|
],
|
|
6
|
-
"version": "0.1.1-beta.
|
|
6
|
+
"version": "0.1.1-beta.11",
|
|
7
7
|
"description": "Lightweight pub/sub event system for the Stonyx framework",
|
|
8
8
|
"main": "src/main.js",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"files": [
|
|
11
|
-
"
|
|
11
|
+
"src",
|
|
12
|
+
"README.md"
|
|
12
13
|
],
|
|
13
14
|
"exports": {
|
|
14
15
|
".": "./src/main.js"
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
},
|
|
32
33
|
"homepage": "https://github.com/abofs/stonyx-events#readme",
|
|
33
34
|
"devDependencies": {
|
|
34
|
-
"@stonyx/utils": "
|
|
35
|
+
"@stonyx/utils": "0.2.3-beta.7",
|
|
35
36
|
"qunit": "^2.24.1",
|
|
36
37
|
"sinon": "^21.0.0"
|
|
37
38
|
},
|
package/src/main.js
CHANGED
|
@@ -165,3 +165,15 @@ class Events {
|
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
export default Events;
|
|
168
|
+
|
|
169
|
+
// Create singleton instance
|
|
170
|
+
const events = new Events();
|
|
171
|
+
|
|
172
|
+
// Export convenience functions that use the singleton
|
|
173
|
+
export const setup = (...args) => events.setup(...args);
|
|
174
|
+
export const subscribe = (...args) => events.subscribe(...args);
|
|
175
|
+
export const once = (...args) => events.once(...args);
|
|
176
|
+
export const unsubscribe = (...args) => events.unsubscribe(...args);
|
|
177
|
+
export const emit = (...args) => events.emit(...args);
|
|
178
|
+
export const clear = (...args) => events.clear(...args);
|
|
179
|
+
export const reset = (...args) => events.reset(...args);
|
|
@@ -1,421 +0,0 @@
|
|
|
1
|
-
# @stonyx/events - Project Structure & Architecture
|
|
2
|
-
|
|
3
|
-
## Project Overview
|
|
4
|
-
|
|
5
|
-
**@stonyx/events** is a lightweight pub/sub event system for the Stonyx framework. It provides a singleton-based event management system with error isolation, async support, and type-safe event registration.
|
|
6
|
-
|
|
7
|
-
### Core Purpose
|
|
8
|
-
- Provide application-wide event bus for decoupled communication
|
|
9
|
-
- Support async event handlers with error isolation
|
|
10
|
-
- Ensure type safety through event registration
|
|
11
|
-
- Maintain singleton pattern for shared event system
|
|
12
|
-
|
|
13
|
-
### Technology Stack
|
|
14
|
-
- **Runtime**: Node.js v24.13.0
|
|
15
|
-
- **Module System**: ES Modules
|
|
16
|
-
- **Testing**: QUnit 2.24.1 + Sinon 21.0.0
|
|
17
|
-
- **License**: Apache 2.0
|
|
18
|
-
|
|
19
|
-
## Architecture Overview
|
|
20
|
-
|
|
21
|
-
### Design Patterns
|
|
22
|
-
|
|
23
|
-
**Singleton Pattern**
|
|
24
|
-
- Single Events instance shared across the application
|
|
25
|
-
- Prevents multiple competing event systems
|
|
26
|
-
- Ensures all parts of the application use the same event bus
|
|
27
|
-
|
|
28
|
-
**Error Isolation**
|
|
29
|
-
- Errors in one handler don't affect other handlers
|
|
30
|
-
- All handlers run even if some fail
|
|
31
|
-
- Errors are logged to console.error but don't propagate
|
|
32
|
-
|
|
33
|
-
**Async Support**
|
|
34
|
-
- All event handlers can be async functions
|
|
35
|
-
- `emit()` waits for all handlers to complete
|
|
36
|
-
- Handlers run in parallel via Promise.all()
|
|
37
|
-
|
|
38
|
-
**Type Safety**
|
|
39
|
-
- Events must be registered with `setup()` before use
|
|
40
|
-
- Prevents typos and invalid event names
|
|
41
|
-
- Enforces explicit event declarations
|
|
42
|
-
|
|
43
|
-
## File Structure
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
stonyx-events/
|
|
47
|
-
├── .github/
|
|
48
|
-
│ └── workflows/
|
|
49
|
-
│ └── ci.yml # GitHub Actions CI pipeline
|
|
50
|
-
├── .claude/
|
|
51
|
-
│ ├── settings.local.json # Claude Code permissions
|
|
52
|
-
│ └── project-structure.md # This file
|
|
53
|
-
├── config/
|
|
54
|
-
│ └── environment.js # Environment configuration
|
|
55
|
-
├── src/
|
|
56
|
-
│ └── main.js # Events class implementation
|
|
57
|
-
├── test/
|
|
58
|
-
│ └── unit/
|
|
59
|
-
│ └── events-test.js # QUnit tests for Events
|
|
60
|
-
├── .gitignore # Git ignore patterns
|
|
61
|
-
├── .npmignore # NPM ignore patterns
|
|
62
|
-
├── .nvmrc # Node version specification
|
|
63
|
-
├── LICENSE.md # Apache 2.0 license
|
|
64
|
-
├── README.md # User-facing documentation
|
|
65
|
-
├── package.json # NPM package configuration
|
|
66
|
-
└── stonyx-bootstrap.cjs # CommonJS bootstrap for testing
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## Core Components Deep Dive
|
|
70
|
-
|
|
71
|
-
### Events Class (`src/main.js`)
|
|
72
|
-
|
|
73
|
-
The Events class is the heart of the module, providing all pub/sub functionality.
|
|
74
|
-
|
|
75
|
-
#### Properties
|
|
76
|
-
|
|
77
|
-
**`static instance`** (Events|null)
|
|
78
|
-
- Singleton instance reference
|
|
79
|
-
- Ensures only one Events instance exists
|
|
80
|
-
|
|
81
|
-
**`events`** (Map<string, Set<Function>>)
|
|
82
|
-
- Map of event names to their subscriber sets
|
|
83
|
-
- Uses Set to prevent duplicate subscriptions
|
|
84
|
-
- Automatically created when events are registered
|
|
85
|
-
|
|
86
|
-
**`registeredEvents`** (Set<string>)
|
|
87
|
-
- Set of all registered event names
|
|
88
|
-
- Used to validate subscriptions
|
|
89
|
-
- Prevents subscribing to unregistered events
|
|
90
|
-
|
|
91
|
-
#### Methods
|
|
92
|
-
|
|
93
|
-
**`setup(eventNames: string[])`**
|
|
94
|
-
- Register available event names
|
|
95
|
-
- Must be called before subscribing to events
|
|
96
|
-
- Validates that all names are strings
|
|
97
|
-
- Creates empty subscriber sets for each event
|
|
98
|
-
|
|
99
|
-
**`subscribe(event: string, callback: Function)`**
|
|
100
|
-
- Subscribe to an event
|
|
101
|
-
- Throws if event is not registered
|
|
102
|
-
- Throws if callback is not a function
|
|
103
|
-
- Returns an unsubscribe function
|
|
104
|
-
- Callback signature: `(...args: any[]) => void | Promise<void>`
|
|
105
|
-
|
|
106
|
-
**`once(event: string, callback: Function)`**
|
|
107
|
-
- Subscribe to an event once
|
|
108
|
-
- Auto-unsubscribes after first emit
|
|
109
|
-
- Wraps callback in a self-removing wrapper
|
|
110
|
-
- Returns an unsubscribe function
|
|
111
|
-
- Supports async callbacks
|
|
112
|
-
|
|
113
|
-
**`emit(event: string, ...args: any[])`**
|
|
114
|
-
- Emit an event with arguments
|
|
115
|
-
- Async function that waits for all handlers
|
|
116
|
-
- Runs all handlers in parallel
|
|
117
|
-
- Isolates errors per handler
|
|
118
|
-
- Does nothing if event has no subscribers
|
|
119
|
-
|
|
120
|
-
**`unsubscribe(event: string, callback: Function)`**
|
|
121
|
-
- Remove a specific subscription
|
|
122
|
-
- Safe to call multiple times
|
|
123
|
-
- Does nothing if event or callback doesn't exist
|
|
124
|
-
|
|
125
|
-
**`clear(event: string)`**
|
|
126
|
-
- Remove all subscriptions for an event
|
|
127
|
-
- Useful for cleanup between tests
|
|
128
|
-
- Event remains registered
|
|
129
|
-
|
|
130
|
-
**`reset()`**
|
|
131
|
-
- Clear all subscriptions and registrations
|
|
132
|
-
- Resets to pristine state
|
|
133
|
-
- Essential for test isolation
|
|
134
|
-
|
|
135
|
-
## Dependencies & Integration
|
|
136
|
-
|
|
137
|
-
### Direct Dependencies
|
|
138
|
-
|
|
139
|
-
**stonyx** (file:../stonyx)
|
|
140
|
-
- Core Stonyx framework
|
|
141
|
-
- Provides base configuration and bootstrapping
|
|
142
|
-
- Required for module initialization
|
|
143
|
-
|
|
144
|
-
### Dev Dependencies
|
|
145
|
-
|
|
146
|
-
**@stonyx/utils** (file:../stonyx-utils)
|
|
147
|
-
- Utility functions (currently unused but available)
|
|
148
|
-
|
|
149
|
-
**qunit** (^2.24.1)
|
|
150
|
-
- Testing framework
|
|
151
|
-
- Runs via CLI with stonyx-bootstrap.cjs
|
|
152
|
-
|
|
153
|
-
**sinon** (^21.0.0)
|
|
154
|
-
- Mocking/stubbing library
|
|
155
|
-
- Available for advanced testing scenarios
|
|
156
|
-
|
|
157
|
-
### Modules That Depend on @stonyx/events
|
|
158
|
-
|
|
159
|
-
**@stonyx/orm**
|
|
160
|
-
- Uses Events for CRUD lifecycle hooks
|
|
161
|
-
- Fires events: create:before, create:after, update:before, update:after, delete:before, delete:after
|
|
162
|
-
- Provides `ormEvents` singleton instance
|
|
163
|
-
|
|
164
|
-
## Code Patterns & Conventions
|
|
165
|
-
|
|
166
|
-
### Module System
|
|
167
|
-
- ES Modules throughout
|
|
168
|
-
- Default export for Events class
|
|
169
|
-
- No named exports (single-purpose module)
|
|
170
|
-
|
|
171
|
-
### Error Handling
|
|
172
|
-
- Validation errors throw immediately
|
|
173
|
-
- Runtime errors in handlers are caught and logged
|
|
174
|
-
- No silent failures
|
|
175
|
-
|
|
176
|
-
### Logging
|
|
177
|
-
- Environment variable: `EVENTS_LOG` (currently unused in implementation)
|
|
178
|
-
- Configuration prepared in `config/environment.js`
|
|
179
|
-
- Future: Could add debug logging for emit/subscribe events
|
|
180
|
-
|
|
181
|
-
### Naming Conventions
|
|
182
|
-
- Event names: camelCase strings (e.g., 'userLogin', 'dataChange')
|
|
183
|
-
- Method names: lowercase verbs (setup, subscribe, emit)
|
|
184
|
-
- Private instance variables: None (all properties public for testing)
|
|
185
|
-
|
|
186
|
-
## Testing Guidelines
|
|
187
|
-
|
|
188
|
-
### Test Structure
|
|
189
|
-
- All tests in `test/unit/events-test.js`
|
|
190
|
-
- QUnit module: `[Unit] Events`
|
|
191
|
-
- 18 test cases covering all functionality
|
|
192
|
-
- Each test calls `events.reset()` before and after
|
|
193
|
-
|
|
194
|
-
### Test Patterns
|
|
195
|
-
|
|
196
|
-
**Singleton Isolation**
|
|
197
|
-
```javascript
|
|
198
|
-
const events = new Events();
|
|
199
|
-
events.reset(); // Clear any previous state
|
|
200
|
-
// ... test code ...
|
|
201
|
-
events.reset(); // Clean up after test
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
**Async Testing**
|
|
205
|
-
```javascript
|
|
206
|
-
test('description', async function (assert) {
|
|
207
|
-
// Use async/await for emit()
|
|
208
|
-
await events.emit('event');
|
|
209
|
-
assert.ok(condition);
|
|
210
|
-
});
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
**Error Suppression**
|
|
214
|
-
```javascript
|
|
215
|
-
const originalConsoleError = console.error;
|
|
216
|
-
console.error = () => {}; // Suppress expected errors
|
|
217
|
-
// ... test code ...
|
|
218
|
-
console.error = originalConsoleError; // Restore
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### Coverage Areas
|
|
222
|
-
1. Event registration (setup)
|
|
223
|
-
2. Subscription management (subscribe, unsubscribe)
|
|
224
|
-
3. Event emission (emit)
|
|
225
|
-
4. One-time subscriptions (once)
|
|
226
|
-
5. Error isolation
|
|
227
|
-
6. Async support
|
|
228
|
-
7. Singleton behavior
|
|
229
|
-
8. Edge cases (unregistered events, no subscribers)
|
|
230
|
-
|
|
231
|
-
## Extension Points
|
|
232
|
-
|
|
233
|
-
While the Events system is intentionally minimal, potential future enhancements include:
|
|
234
|
-
|
|
235
|
-
### Event Priorities
|
|
236
|
-
- Add priority levels for subscribers
|
|
237
|
-
- Execute high-priority handlers first
|
|
238
|
-
- Use case: Logging before business logic
|
|
239
|
-
|
|
240
|
-
### Wildcard Events
|
|
241
|
-
- Support pattern matching (e.g., 'user:*')
|
|
242
|
-
- Subscribe to multiple events at once
|
|
243
|
-
- Use case: Debugging, logging all events
|
|
244
|
-
|
|
245
|
-
### Event History
|
|
246
|
-
- Optional recording of emitted events
|
|
247
|
-
- Replay functionality for debugging
|
|
248
|
-
- Use case: Time-travel debugging, audit logs
|
|
249
|
-
|
|
250
|
-
### Middleware
|
|
251
|
-
- Pre/post-emit hooks
|
|
252
|
-
- Event transformation pipeline
|
|
253
|
-
- Use case: Validation, logging, metrics
|
|
254
|
-
|
|
255
|
-
## Configuration Reference
|
|
256
|
-
|
|
257
|
-
### Environment Variables
|
|
258
|
-
|
|
259
|
-
**EVENTS_LOG**
|
|
260
|
-
- Type: Boolean (truthy/falsy)
|
|
261
|
-
- Default: `false`
|
|
262
|
-
- Purpose: Enable debug logging (not yet implemented)
|
|
263
|
-
- Usage: `EVENTS_LOG=true npm test`
|
|
264
|
-
|
|
265
|
-
### config/environment.js
|
|
266
|
-
|
|
267
|
-
```javascript
|
|
268
|
-
{
|
|
269
|
-
log: EVENTS_LOG ?? false, // Debug logging flag
|
|
270
|
-
logColor: '#888', // Color for log output
|
|
271
|
-
}
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
Currently, these config values are prepared but not used in the Events implementation. They provide a foundation for future debug logging features.
|
|
275
|
-
|
|
276
|
-
## Package Exports
|
|
277
|
-
|
|
278
|
-
### Main Export
|
|
279
|
-
|
|
280
|
-
```javascript
|
|
281
|
-
import Events from '@stonyx/events';
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
The package exports a single default export: the Events class.
|
|
285
|
-
|
|
286
|
-
### Usage Pattern
|
|
287
|
-
|
|
288
|
-
```javascript
|
|
289
|
-
// Create/get singleton instance
|
|
290
|
-
const events = new Events();
|
|
291
|
-
|
|
292
|
-
// Register events
|
|
293
|
-
events.setup(['userLogin', 'userLogout']);
|
|
294
|
-
|
|
295
|
-
// Subscribe
|
|
296
|
-
events.subscribe('userLogin', (user) => {
|
|
297
|
-
console.log('User logged in:', user);
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
// Emit (fire-and-forget, don't await)
|
|
301
|
-
events.emit('userLogin', { id: 1, name: 'Alice' });
|
|
302
|
-
|
|
303
|
-
// Or await if you need to ensure all handlers complete
|
|
304
|
-
await events.emit('userLogin', { id: 1, name: 'Alice' });
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
## Development Workflow
|
|
308
|
-
|
|
309
|
-
### Local Development
|
|
310
|
-
|
|
311
|
-
1. **Install dependencies**
|
|
312
|
-
```bash
|
|
313
|
-
cd /Users/mstonepc/Repos/abofs
|
|
314
|
-
./linker.sh local # Link all local Stonyx modules
|
|
315
|
-
cd stonyx-events
|
|
316
|
-
npm install
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
2. **Run tests**
|
|
320
|
-
```bash
|
|
321
|
-
npm test
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
3. **Make changes**
|
|
325
|
-
- Edit `src/main.js` for implementation
|
|
326
|
-
- Edit `test/unit/events-test.js` for tests
|
|
327
|
-
- Follow TDD: Write failing test, implement feature, verify
|
|
328
|
-
|
|
329
|
-
### Test-Driven Development
|
|
330
|
-
|
|
331
|
-
The module follows TDD principles:
|
|
332
|
-
1. Write a failing test for new functionality
|
|
333
|
-
2. Implement the minimum code to pass the test
|
|
334
|
-
3. Refactor while keeping tests green
|
|
335
|
-
4. Ensure all tests pass before committing
|
|
336
|
-
|
|
337
|
-
### CI/CD Pipeline
|
|
338
|
-
|
|
339
|
-
**GitHub Actions** (`.github/workflows/ci.yml`)
|
|
340
|
-
- Triggers on PRs to `dev` and `main` branches
|
|
341
|
-
- Uses pnpm for package management
|
|
342
|
-
- Runs `pnpm test` to verify all tests pass
|
|
343
|
-
- Cancels previous runs on new commits
|
|
344
|
-
|
|
345
|
-
### Publishing Workflow
|
|
346
|
-
|
|
347
|
-
1. **Version bump**
|
|
348
|
-
```bash
|
|
349
|
-
npm version patch|minor|major
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
2. **Publish to NPM**
|
|
353
|
-
```bash
|
|
354
|
-
npm publish
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
3. **Update dependents**
|
|
358
|
-
- Update `@stonyx/orm` to use published version
|
|
359
|
-
- Update other modules as needed
|
|
360
|
-
|
|
361
|
-
## Common Pitfalls & Gotchas
|
|
362
|
-
|
|
363
|
-
### Singleton Behavior
|
|
364
|
-
- **Issue**: Creating new Events() always returns the same instance
|
|
365
|
-
- **Solution**: Don't rely on local variables; singleton ensures shared state
|
|
366
|
-
- **Testing**: Always call `reset()` between tests to clear state
|
|
367
|
-
|
|
368
|
-
### Async Handling
|
|
369
|
-
- **Issue**: Forgetting to await emit() can lead to race conditions
|
|
370
|
-
- **Solution**: Use `await events.emit()` when order matters
|
|
371
|
-
- **Note**: For fire-and-forget, omit await (e.g., in synchronous createRecord)
|
|
372
|
-
|
|
373
|
-
### Error Isolation
|
|
374
|
-
- **Issue**: One handler error doesn't stop other handlers, but logs to console
|
|
375
|
-
- **Solution**: Expect console.error output in tests with failing handlers
|
|
376
|
-
- **Testing**: Suppress console.error when testing error isolation
|
|
377
|
-
|
|
378
|
-
### Event Registration
|
|
379
|
-
- **Issue**: Subscribing to unregistered events throws an error
|
|
380
|
-
- **Solution**: Always call `setup()` with event names before subscribing
|
|
381
|
-
- **Why**: Prevents typos and ensures explicit event declarations
|
|
382
|
-
|
|
383
|
-
### Set-based Subscriptions
|
|
384
|
-
- **Issue**: Adding the same callback function twice only subscribes once
|
|
385
|
-
- **Solution**: Use different function instances for multiple subscriptions
|
|
386
|
-
- **Note**: This is by design to prevent accidental duplicate subscriptions
|
|
387
|
-
|
|
388
|
-
## Future Enhancement Opportunities
|
|
389
|
-
|
|
390
|
-
### Performance Optimizations
|
|
391
|
-
- Lazy initialization of event subscriber sets
|
|
392
|
-
- Debouncing/throttling for high-frequency events
|
|
393
|
-
- Event batching for bulk updates
|
|
394
|
-
|
|
395
|
-
### Developer Experience
|
|
396
|
-
- TypeScript definitions for type-safe event names and payloads
|
|
397
|
-
- Debug mode with detailed logging
|
|
398
|
-
- Event visualization/monitoring tools
|
|
399
|
-
|
|
400
|
-
### Advanced Features
|
|
401
|
-
- Event namespacing (e.g., 'user:login:success')
|
|
402
|
-
- Event bubbling/capturing (DOM-like event propagation)
|
|
403
|
-
- Async middleware pipeline
|
|
404
|
-
- Event replay for debugging
|
|
405
|
-
|
|
406
|
-
### Integration
|
|
407
|
-
- Automatic event logging to @stonyx/logger (when it exists)
|
|
408
|
-
- Metrics/telemetry integration
|
|
409
|
-
- Event persistence for audit trails
|
|
410
|
-
|
|
411
|
-
## Related Resources
|
|
412
|
-
|
|
413
|
-
- [Stonyx Framework](https://github.com/abofs/stonyx)
|
|
414
|
-
- [QUnit Documentation](https://qunitjs.com/)
|
|
415
|
-
- [Sinon.js Documentation](https://sinonjs.org/)
|
|
416
|
-
- [Node.js ES Modules](https://nodejs.org/api/esm.html)
|
|
417
|
-
- [Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0)
|
|
418
|
-
|
|
419
|
-
---
|
|
420
|
-
|
|
421
|
-
This document is maintained by the Stonyx team and should be updated whenever architectural changes are made to the @stonyx/events module.
|
package/.github/workflows/ci.yml
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
branches: [dev, main]
|
|
6
|
-
|
|
7
|
-
concurrency:
|
|
8
|
-
group: ci-${{ github.head_ref || github.ref }}
|
|
9
|
-
cancel-in-progress: true
|
|
10
|
-
|
|
11
|
-
permissions:
|
|
12
|
-
contents: read
|
|
13
|
-
|
|
14
|
-
jobs:
|
|
15
|
-
test:
|
|
16
|
-
uses: abofs/stonyx-workflows/.github/workflows/ci.yml@main
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
name: Publish to NPM
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
inputs:
|
|
6
|
-
version-type:
|
|
7
|
-
description: 'Version type'
|
|
8
|
-
required: true
|
|
9
|
-
type: choice
|
|
10
|
-
options:
|
|
11
|
-
- patch
|
|
12
|
-
- minor
|
|
13
|
-
- major
|
|
14
|
-
custom-version:
|
|
15
|
-
description: 'Custom version (optional, overrides version-type)'
|
|
16
|
-
required: false
|
|
17
|
-
type: string
|
|
18
|
-
pull_request:
|
|
19
|
-
types: [opened, synchronize, reopened]
|
|
20
|
-
branches: [main, dev]
|
|
21
|
-
push:
|
|
22
|
-
branches: [main]
|
|
23
|
-
|
|
24
|
-
permissions:
|
|
25
|
-
contents: write
|
|
26
|
-
id-token: write
|
|
27
|
-
pull-requests: write
|
|
28
|
-
|
|
29
|
-
jobs:
|
|
30
|
-
publish:
|
|
31
|
-
uses: abofs/stonyx-workflows/.github/workflows/npm-publish.yml@main
|
|
32
|
-
with:
|
|
33
|
-
version-type: ${{ github.event.inputs.version-type }}
|
|
34
|
-
custom-version: ${{ github.event.inputs.custom-version }}
|
|
35
|
-
secrets: inherit
|
package/.gitignore
DELETED
package/.npmignore
DELETED
package/pnpm-lock.yaml
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
lockfileVersion: '9.0'
|
|
2
|
-
|
|
3
|
-
settings:
|
|
4
|
-
autoInstallPeers: true
|
|
5
|
-
excludeLinksFromLockfile: false
|
|
6
|
-
|
|
7
|
-
importers:
|
|
8
|
-
|
|
9
|
-
.:
|
|
10
|
-
devDependencies:
|
|
11
|
-
'@stonyx/utils':
|
|
12
|
-
specifier: ^0.2.2
|
|
13
|
-
version: 0.2.2
|
|
14
|
-
qunit:
|
|
15
|
-
specifier: ^2.24.1
|
|
16
|
-
version: 2.25.0
|
|
17
|
-
sinon:
|
|
18
|
-
specifier: ^21.0.0
|
|
19
|
-
version: 21.0.1
|
|
20
|
-
|
|
21
|
-
packages:
|
|
22
|
-
|
|
23
|
-
'@sinonjs/commons@3.0.1':
|
|
24
|
-
resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==}
|
|
25
|
-
|
|
26
|
-
'@sinonjs/fake-timers@15.1.0':
|
|
27
|
-
resolution: {integrity: sha512-cqfapCxwTGsrR80FEgOoPsTonoefMBY7dnUEbQ+GRcved0jvkJLzvX6F4WtN+HBqbPX/SiFsIRUp+IrCW/2I2w==}
|
|
28
|
-
|
|
29
|
-
'@sinonjs/samsam@8.0.3':
|
|
30
|
-
resolution: {integrity: sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==}
|
|
31
|
-
|
|
32
|
-
'@stonyx/utils@0.2.2':
|
|
33
|
-
resolution: {integrity: sha512-z/pDbX3QPeVJ3kFpU1rQURj3+BLwvGkLHVJiSckmjaBZ/vQIZzaerkf6BTZnHbSmQuUwO0lFzJRwlKOTIaXp0g==}
|
|
34
|
-
|
|
35
|
-
commander@7.2.0:
|
|
36
|
-
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
|
|
37
|
-
engines: {node: '>= 10'}
|
|
38
|
-
|
|
39
|
-
diff@8.0.3:
|
|
40
|
-
resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==}
|
|
41
|
-
engines: {node: '>=0.3.1'}
|
|
42
|
-
|
|
43
|
-
globalyzer@0.1.0:
|
|
44
|
-
resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==}
|
|
45
|
-
|
|
46
|
-
globrex@0.1.2:
|
|
47
|
-
resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
|
|
48
|
-
|
|
49
|
-
has-flag@4.0.0:
|
|
50
|
-
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
|
51
|
-
engines: {node: '>=8'}
|
|
52
|
-
|
|
53
|
-
node-watch@0.7.3:
|
|
54
|
-
resolution: {integrity: sha512-3l4E8uMPY1HdMMryPRUAl+oIHtXtyiTlIiESNSVSNxcPfzAFzeTbXFQkZfAwBbo0B1qMSG8nUABx+Gd+YrbKrQ==}
|
|
55
|
-
engines: {node: '>=6'}
|
|
56
|
-
|
|
57
|
-
qunit@2.25.0:
|
|
58
|
-
resolution: {integrity: sha512-MONPKgjavgTqArCwZOEz8nEMbA19zNXIp5ZOW9rPYj5cbgQp0fiI36c9dPTSzTRRzx+KcfB5eggYB/ENqxi0+w==}
|
|
59
|
-
engines: {node: '>=10'}
|
|
60
|
-
hasBin: true
|
|
61
|
-
|
|
62
|
-
sinon@21.0.1:
|
|
63
|
-
resolution: {integrity: sha512-Z0NVCW45W8Mg5oC/27/+fCqIHFnW8kpkFOq0j9XJIev4Ld0mKmERaZv5DMLAb9fGCevjKwaEeIQz5+MBXfZcDw==}
|
|
64
|
-
|
|
65
|
-
supports-color@7.2.0:
|
|
66
|
-
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
|
67
|
-
engines: {node: '>=8'}
|
|
68
|
-
|
|
69
|
-
tiny-glob@0.2.9:
|
|
70
|
-
resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==}
|
|
71
|
-
|
|
72
|
-
type-detect@4.0.8:
|
|
73
|
-
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
|
|
74
|
-
engines: {node: '>=4'}
|
|
75
|
-
|
|
76
|
-
type-detect@4.1.0:
|
|
77
|
-
resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==}
|
|
78
|
-
engines: {node: '>=4'}
|
|
79
|
-
|
|
80
|
-
snapshots:
|
|
81
|
-
|
|
82
|
-
'@sinonjs/commons@3.0.1':
|
|
83
|
-
dependencies:
|
|
84
|
-
type-detect: 4.0.8
|
|
85
|
-
|
|
86
|
-
'@sinonjs/fake-timers@15.1.0':
|
|
87
|
-
dependencies:
|
|
88
|
-
'@sinonjs/commons': 3.0.1
|
|
89
|
-
|
|
90
|
-
'@sinonjs/samsam@8.0.3':
|
|
91
|
-
dependencies:
|
|
92
|
-
'@sinonjs/commons': 3.0.1
|
|
93
|
-
type-detect: 4.1.0
|
|
94
|
-
|
|
95
|
-
'@stonyx/utils@0.2.2': {}
|
|
96
|
-
|
|
97
|
-
commander@7.2.0: {}
|
|
98
|
-
|
|
99
|
-
diff@8.0.3: {}
|
|
100
|
-
|
|
101
|
-
globalyzer@0.1.0: {}
|
|
102
|
-
|
|
103
|
-
globrex@0.1.2: {}
|
|
104
|
-
|
|
105
|
-
has-flag@4.0.0: {}
|
|
106
|
-
|
|
107
|
-
node-watch@0.7.3: {}
|
|
108
|
-
|
|
109
|
-
qunit@2.25.0:
|
|
110
|
-
dependencies:
|
|
111
|
-
commander: 7.2.0
|
|
112
|
-
node-watch: 0.7.3
|
|
113
|
-
tiny-glob: 0.2.9
|
|
114
|
-
|
|
115
|
-
sinon@21.0.1:
|
|
116
|
-
dependencies:
|
|
117
|
-
'@sinonjs/commons': 3.0.1
|
|
118
|
-
'@sinonjs/fake-timers': 15.1.0
|
|
119
|
-
'@sinonjs/samsam': 8.0.3
|
|
120
|
-
diff: 8.0.3
|
|
121
|
-
supports-color: 7.2.0
|
|
122
|
-
|
|
123
|
-
supports-color@7.2.0:
|
|
124
|
-
dependencies:
|
|
125
|
-
has-flag: 4.0.0
|
|
126
|
-
|
|
127
|
-
tiny-glob@0.2.9:
|
|
128
|
-
dependencies:
|
|
129
|
-
globalyzer: 0.1.0
|
|
130
|
-
globrex: 0.1.2
|
|
131
|
-
|
|
132
|
-
type-detect@4.0.8: {}
|
|
133
|
-
|
|
134
|
-
type-detect@4.1.0: {}
|
package/stonyx-bootstrap.cjs
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* commonJS Bootstrap loading - Stonyx must be loaded first, prior to the rest of the application
|
|
3
|
-
*/
|
|
4
|
-
const { default:Stonyx } = require('stonyx');
|
|
5
|
-
const { default:config } = require('./config/environment.js');
|
|
6
|
-
|
|
7
|
-
new Stonyx(config, __dirname);
|
|
8
|
-
|
|
9
|
-
module.exports = Stonyx;
|