Skip to content

Commit b617ace

Browse files
chore: wip
1 parent 7843c9f commit b617ace

File tree

15 files changed

+52
-592
lines changed

15 files changed

+52
-592
lines changed

app/Actions/NotifyUser.ts

Whitespace-only changes.
File renamed without changes.

app/Events.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ import type { Events } from '@stacksjs/types'
1010
export default {
1111
// eventName: ['Listener1', 'Listener2'] -> listeners default to ./app/actions/*
1212
'user:registered': ['SendWelcomeEmail'],
13+
'user:created': ['NotifyUser'],
1314
} satisfies Events

app/Listener.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,30 @@
1-
import { listen } from '@stacksjs/events'
1+
import type { StacksEvents, WildcardHandler } from '@stacksjs/events'
2+
import { handleError } from '@stacksjs/error-handling'
3+
import { emitter } from '@stacksjs/events'
24
import { path as p } from '@stacksjs/path'
35
import events from './Events'
46

57
export async function handleEvents() {
6-
for (const key in events) {
7-
if (Object.hasOwn(events, key)) {
8-
const eventKey = key
9-
const eventListeners = events[key]
8+
emitter.on('*', listenEvents as WildcardHandler<StacksEvents>)
9+
}
1010

11-
for (const eventListener of eventListeners) {
12-
const modulePath = eventListener
11+
async function listenEvents(type: keyof typeof events, event: any) {
12+
const eventListeners = events[type]
1313

14-
if (isFunction(modulePath)) {
15-
await modulePath()
16-
}
17-
else {
18-
try {
19-
const actionModule = await import(p.projectPath(`Actions/${modulePath}.ts`))
14+
if (!eventListeners)
15+
return
2016

21-
listen(eventKey, e => actionModule.default.handle(e))
22-
}
23-
catch (error) {
24-
handleError(`Module not found: ${modulePath}`, error)
25-
}
26-
}
17+
for (const eventListener of eventListeners) {
18+
if (isFunction(eventListener)) {
19+
await eventListener(event)
20+
}
21+
else {
22+
try {
23+
const actionModule = await import(p.projectPath(`Actions/${eventListener}.ts`))
24+
await actionModule.default.handle(event)
25+
}
26+
catch (error) {
27+
handleError(`Module not found: ${eventListener}`, error)
2728
}
2829
}
2930
}

app/storage/logs/stacks.log

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[2025-02-17T13:07:26.478Z] DEBUG: Using database driver: sqlite
2+
[2025-02-17T13:07:37.907Z] DEBUG: Using database driver: sqlite
3+
[2025-02-17T13:08:09.939Z] DEBUG: Using database driver: sqlite
4+
[2025-02-17T13:08:19.049Z] DEBUG: Using database driver: sqlite
5+
[2025-02-17T13:08:39.004Z] DEBUG: Using database driver: sqlite
6+
[2025-02-17T13:27:47.210Z] DEBUG: Using database driver: sqlite

storage/framework/actions/src/UserShowOrmAction.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { UserRequestType } from '@stacksjs/orm'
22
import { Action } from '@stacksjs/actions'
33
import { response } from '@stacksjs/router'
4-
import User from '../../orm/src/models/User'
54

65
export default new Action({
76
name: 'User Show',

storage/framework/api/dev.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { log, runCommandSync } from '@stacksjs/cli'
55
import { app, ports } from '@stacksjs/config'
66
import { join, path } from '@stacksjs/path'
77
import { serve } from '@stacksjs/router'
8+
import { handleEvents } from '../../../app/Listener'
89

910
declare global {
1011
let counter: number
@@ -66,6 +67,8 @@ serve({
6667
timezone: app.timezone || 'UTC',
6768
})
6869

70+
await handleEvents()
71+
6972
process.on('SIGINT', () => {
7073
log.info(`Exited using Ctrl-C`)
7174
process.exit()

storage/framework/core/events/src/index.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,15 @@ export default function mitt<Events extends Record<EventType, unknown>>(
104104
*/
105105
emit<Key extends keyof Events>(type: Key, evt?: Events[Key]) {
106106
let handlers = (all as EventHandlerMap<Events>).get(type)
107+
107108
if (handlers) {
108109
;(handlers as EventHandlerList<Events[keyof Events]>).slice().forEach((handler) => {
109110
if (evt !== undefined)
110111
handler(evt)
111112
})
112113
}
113114
handlers = (all as EventHandlerMap<Events>).get('*')
115+
114116
if (handlers) {
115117
;(handlers as WildCardEventHandlerList<Events>).slice().forEach((handler) => {
116118
if (evt !== undefined)
@@ -144,7 +146,7 @@ export default function mitt<Events extends Record<EventType, unknown>>(
144146
*/
145147

146148
// TODO: need to create an action that auto generates this Events type from the ./app/Events
147-
interface StacksEvents extends ModelEvents {
149+
export interface StacksEvents extends ModelEvents, Record<EventType, unknown> {
148150
'user:registered': UserModel
149151
'user:logged-in': UserModel
150152
'user:logged-out': UserModel
@@ -153,13 +155,19 @@ interface StacksEvents extends ModelEvents {
153155
}
154156

155157
const events: Emitter<StacksEvents> = mitt<StacksEvents>()
158+
159+
// Export clean, typed methods
160+
type Dispatch = <Key extends keyof StacksEvents>(type: Key, event: StacksEvents[Key]) => void
161+
type Listen = <Key extends keyof StacksEvents>(type: Key, handler: Handler<StacksEvents[Key]>) => void
162+
type Off = <Key extends keyof StacksEvents>(type: Key, handler?: Handler<StacksEvents[Key]>) => void
163+
156164
const emitter: Emitter<StacksEvents> = events
157-
const useEvent: typeof emitter.emit = emitter.emit.bind(emitter)
158-
const useEvents: any = events
159-
const dispatch: typeof emitter.emit = emitter.emit.bind(emitter)
160165

161-
const listen: typeof emitter.on = emitter.on.bind(emitter)
162-
const off: typeof emitter.off = emitter.off.bind(emitter)
163-
const all: typeof emitter.all = emitter.all
166+
const useEvents: Emitter<StacksEvents> = events
167+
const dispatch: Dispatch = emitter.emit
168+
const all: EventHandlerMap<StacksEvents> = emitter.all
169+
const listen: Listen = emitter.on
170+
const useListen: Listen = emitter.on
171+
const off: Off = emitter.off
164172

165-
export { all, dispatch, events, listen, mitt, off, useEvent, useEvents }
173+
export { all, dispatch, emitter, events, listen, mitt, off, useEvents, useListen }

storage/framework/core/orm/src/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -416,9 +416,9 @@ export async function writeModelEvents(): Promise<void> {
416416

417417
if (typeof observer === 'boolean') {
418418
if (observer) {
419-
observerString += `'${formattedModelName}:created': Partial<${modelName}Model>\n`
420-
observerString += `'${formattedModelName}:updated': Partial<${modelName}Model>\n`
421-
observerString += `'${formattedModelName}:deleted': Partial<${modelName}Model>\n`
419+
observerString += `'${formattedModelName}:created': ${modelName}Model\n`
420+
observerString += `'${formattedModelName}:updated': ${modelName}Model\n`
421+
observerString += `'${formattedModelName}:deleted': ${modelName}Model\n`
422422

423423
observerImports += `import type { ${modelName}Model } from '../orm/src/models/${modelName}'`
424424
}
Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +0,0 @@
1-
import type { ErrorRequestType } from '../types/requests'
2-
import { Request } from '@stacksjs/router'
3-
import { customValidate, type schema, validateField } from '@stacksjs/validation'
4-
5-
interface ValidationField {
6-
rule: ReturnType<typeof schema.string>
7-
message: Record<string, string>
8-
}
9-
10-
interface CustomAttributes {
11-
[key: string]: ValidationField
12-
}
13-
interface RequestDataError {
14-
id: number
15-
type: string
16-
message: string
17-
stack: string
18-
status: number
19-
additional_info: string
20-
created_at?: Date
21-
updated_at?: Date
22-
}
23-
export class ErrorRequest extends Request<RequestDataError> implements ErrorRequestType {
24-
public id = 1
25-
public type = ''
26-
public message = ''
27-
public stack = ''
28-
public status = 0
29-
public additional_info = ''
30-
public created_at = new Date()
31-
public updated_at = new Date()
32-
33-
public async validate(attributes?: CustomAttributes): Promise<void> {
34-
if (attributes === undefined || attributes === null) {
35-
await validateField('Error', this.all())
36-
}
37-
else {
38-
await customValidate(attributes, this.all())
39-
}
40-
}
41-
}
42-
43-
export const errorRequest = new ErrorRequest()

0 commit comments

Comments
 (0)