Skip to content

Commit

Permalink
feat(@rallie/block): bind the trigger name of event and methods on th…
Browse files Browse the repository at this point in the history
…e `this` object of the listener
  • Loading branch information
run-nan committed Mar 4, 2023
1 parent f580951 commit 4957c54
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 14 deletions.
16 changes: 9 additions & 7 deletions packages/block/src/base-block.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Socket } from '@rallie/core'
import { constant, errors } from './utils'
import { constant, errors, enhancedEventsTrigger, enhancedEventsListener } from './utils'

export type BlockType = {
state?: Record<string, unknown>
events?: Record<string, Function>
methods?: Record<string, Function>
events?: Record<string, (this: { trigger: string }, ...args: any[]) => any>
methods?: Record<string, (this: { trigger: string }, ...args: any[]) => any>
}

export class BaseBlock<T extends BlockType> {
Expand All @@ -15,11 +15,13 @@ export class BaseBlock<T extends BlockType> {

#socket: Socket

constructor(name: string, socket: Socket) {
constructor(name: string, triggerName: string, socket: Socket) {
this.name = name
this.#socket = socket
this.events = this.#socket.createBroadcaster()
this.methods = this.#socket.createUnicaster()
const broadcaster = this.#socket.createBroadcaster()
const unicaster = this.#socket.createUnicaster()
this.events = enhancedEventsTrigger(broadcaster, triggerName) as T['events']
this.methods = enhancedEventsTrigger(unicaster, triggerName) as T['methods']
Reflect.defineProperty(this, 'state', {
get: () => this.#socket.getState<T['state'], T['state']>(constant.stateNamespace(this.name)),
set: () => {
Expand All @@ -45,6 +47,6 @@ export class BaseBlock<T extends BlockType> {
}

public listenEvents(events: Partial<T['events']>) {
return this.#socket.onBroadcast(events)
return this.#socket.onBroadcast(enhancedEventsListener(events))
}
}
8 changes: 4 additions & 4 deletions packages/block/src/created-block.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Bus, Socket, MiddlewareFnType, ConfType, touchBus, App } from '@rallie/core'
import { constant } from './utils'
import { constant, enhancedEventsListener } from './utils'
import { BaseBlock, type BlockType } from './base-block'

export interface Env {
Expand All @@ -22,7 +22,7 @@ export class CreatedBlock<T extends BlockType> extends BaseBlock<T> {
constructor(name: string, globalBus: Bus, globalSocket: Socket, isEntry: boolean) {
const [bus] = touchBus(constant.privateBus(name))
const socket = bus.createSocket()
super(name, socket)
super(name, name, socket)
this.#socket = socket
this.#globalBus = globalBus
this.#globalSocket = globalSocket
Expand All @@ -36,7 +36,7 @@ export class CreatedBlock<T extends BlockType> extends BaseBlock<T> {
}

public addMethods(methods: Partial<T['methods']>) {
return this.#socket.onUnicast(methods)
return this.#socket.onUnicast(enhancedEventsListener(methods))
}

public relyOn(dependencies: string[]) {
Expand All @@ -58,7 +58,7 @@ export class CreatedBlock<T extends BlockType> extends BaseBlock<T> {
if (!this.#connectedBlocks[name]) {
const [bus] = touchBus(constant.privateBus(name))
const socket = bus.createSocket()
this.#connectedBlocks[name] = new BaseBlock<P>(name, socket)
this.#connectedBlocks[name] = new BaseBlock<P>(name, this.name, socket)
}
return this.#connectedBlocks[name] as BaseBlock<P>
}
Expand Down
27 changes: 25 additions & 2 deletions packages/block/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export type ConstraintedType<T, P, Default> = T extends P ? T : Default

export const constant = {
privateBus: (blockName: string) => `${blockName}.bus`,
stateNamespace: (blockName: string) => `${blockName}.state`,
Expand All @@ -19,3 +17,28 @@ export const errors = {
message(`the block ${blockName} is already registered before, please rename your block`),
stateIsReadonly: (blockName: string) => message(`the state of ${blockName} is readonly`),
}

export const enhancedEventsTrigger = <T extends Record<string, Function>>(
events: T,
trigger: string,
) => {
return new Proxy<T>(events, {
get: (target, eventName) => {
return (...args: any[]) => {
const fn = target[eventName as string]
return fn(args, trigger)
}
},
set: () => false,
})
}

export const enhancedEventsListener = <T extends Record<string, Function>>(listeners: T) => {
const result: Record<string, Function> = {}
Object.entries(listeners).forEach(([eventName, listener]) => {
result[eventName] = (args: any[], trigger: string) => {
return listener.call({ trigger }, ...args)
}
})
return result
}
34 changes: 34 additions & 0 deletions packages/block/test/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,38 @@ describe('Test errors and warnings', () => {
}
}).toThrowError(errors.stateIsReadonly('case2'))
})

test('#case3: trigger', () => {
let normalFuncMethodTrigger = ''
let normalFuncEventTrigger = ''
type BlockType = {
methods: {
normalFunc: () => void
}
events: {
normalFunc: () => void
}
}
const block = createBlock<BlockType>('case3')
block.addMethods({
normalFunc(this: { trigger: string }) {
normalFuncMethodTrigger = this.trigger
},
})
block.listenEvents({
normalFunc(this: { trigger: string }) {
normalFuncEventTrigger = this.trigger
},
})
const tester = createBlock('tester')
const connectedBlock = tester.connect<BlockType>(block.name)
connectedBlock.methods.normalFunc()
expect(normalFuncMethodTrigger).toEqual('tester')
connectedBlock.events.normalFunc()
expect(normalFuncEventTrigger).toEqual('tester')
block.methods.normalFunc()
expect(normalFuncMethodTrigger).toEqual('case3')
block.events.normalFunc()
expect(normalFuncEventTrigger).toEqual('case3')
})
})
3 changes: 2 additions & 1 deletion playground/apps/host-app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { hostApp } from './block'
import { NButton, create } from 'naive-ui'

hostApp.addMethods({
useNaiveUI: () => {
useNaiveUI(this: { trigger: string }) {
console.log(this.trigger)
const naive = create({
components: [NButton],
})
Expand Down

0 comments on commit 4957c54

Please sign in to comment.