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()

storage/framework/server-auto-imports.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
"Error": true,
2424
"ErrorJsonResponse": true,
2525
"ErrorModel": true,
26-
"ErrorRequest": true,
2726
"ErrorType": true,
2827
"ErrorUpdate": true,
2928
"ErrorsTable": true,
@@ -140,7 +139,6 @@
140139
"activityRequest": true,
141140
"default": true,
142141
"deploymentRequest": true,
143-
"errorRequest": true,
144142
"failedjobRequest": true,
145143
"jobRequest": true,
146144
"paymentmethodRequest": true,

storage/framework/types/attributes.ts

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +0,0 @@
1-
export interface Attributes {
2-
name: string
3-
description: string
4-
url: string
5-
status: string
6-
email: string
7-
token: string
8-
plain_text_token: string
9-
abilities: string[]
10-
company_name: string
11-
billing_email: string
12-
path: string
13-
is_personal: boolean
14-
title: string
15-
address: string
16-
latlng: string
17-
info_source: string[]
18-
were_detained: boolean
19-
subscribed: boolean
20-
commit_sha: string
21-
commit_message: string
22-
branch: string
23-
execution_time: number
24-
deploy_script: string
25-
terminal_output: string
26-
version: string
27-
job_title: string
28-
password: string
29-
body: string
30-
connection: string
31-
queue: string
32-
payload: string
33-
exception: string
34-
failed_at: Date | string
35-
key: number
36-
unit_price: number
37-
image: string
38-
provider_id: string
39-
type: string
40-
last_four: number
41-
brand: string
42-
exp_month: number
43-
exp_year: number
44-
is_default: boolean
45-
amount: number
46-
attempts: number
47-
available_at: number
48-
reserved_at: Date | string
49-
provider_status: string
50-
provider_type: string
51-
provider_price_id: string
52-
quantity: number
53-
trial_ends_at: string
54-
ends_at: string
55-
last_used_at: string
56-
message: string
57-
stack: string
58-
additional_info: string
59-
}

storage/framework/types/events.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import type { UserModel } from '../orm/src/models/User'
22

33
export interface ModelEvents {
44

5-
'user:created': Partial<UserModel>
6-
'user:updated': Partial<UserModel>
7-
'user:deleted': Partial<UserModel>
5+
'user:created': UserModel
6+
'user:updated': UserModel
7+
'user:deleted': UserModel
88

99
}

0 commit comments

Comments
 (0)