Skip to content

Commit

Permalink
feat(@rallie/block): remove the method registerBlock
Browse files Browse the repository at this point in the history
  • Loading branch information
run-nan committed Feb 25, 2023
1 parent 7109baf commit 92e4ff0
Show file tree
Hide file tree
Showing 45 changed files with 214 additions and 365 deletions.
50 changes: 50 additions & 0 deletions packages/block/src/base-block.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { Socket } from '@rallie/core'
import { constant, errors } from './utils'

export type BlockType = {
state?: Record<string, unknown>
events?: Record<string, Function>
methods?: Record<string, Function>
}

export class BaseBlock<T extends BlockType> {
public name: string
public state: T['state']
public events: T['events']
public methods: T['methods']

#socket: Socket

constructor(name: string, socket: Socket) {
this.name = name
this.#socket = socket
this.events = this.#socket.createBroadcaster()
this.methods = this.#socket.createUnicaster()
Reflect.defineProperty(this, 'state', {
get: () => this.#socket.getState<T['state'], T['state']>(constant.stateNamespace(this.name)),
set: () => {
throw new Error(errors.stateIsReadonly(this.name))
},
})
}

public setState(action: string, setter: (state: T['state']) => void | Promise<void>) {
if (this.#socket.existState(constant.stateNamespace(this.name))) {
return this.#socket.setState(constant.stateNamespace(this.name), action, setter)
} else {
throw new Error(errors.stateNotInitialized(this.name))
}
}

public watchState<P = any>(getter: (state: T['state']) => undefined | P) {
if (this.#socket.existState(constant.stateNamespace(this.name))) {
return this.#socket.watchState<T['state'], P>(constant.stateNamespace(this.name), getter)
} else {
throw new Error(errors.stateNotInitialized(this.name))
}
}

public listenEvents(events: Partial<T['events']>) {
return this.#socket.onBroadcast<Partial<T['events']>>(events)
}
}
52 changes: 0 additions & 52 deletions packages/block/src/block.ts

This file was deleted.

19 changes: 0 additions & 19 deletions packages/block/src/connected-block.ts

This file was deleted.

91 changes: 54 additions & 37 deletions packages/block/src/created-block.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { ConnectedBlock } from './connected-block'
import type { Bus, Socket, MiddlewareFnType, ConfType } from '@rallie/core'
import { constant, errors, SYMBOLS } from './utils'
import { Block, type BlockService } from './block'
import { socketsPool } from './sockets-pool'
import { Bus, Socket, MiddlewareFnType, ConfType, touchBus, App } from '@rallie/core'
import { constant } from './utils'
import { BaseBlock, type BlockType } from './base-block'

export interface Env {
isEntry: boolean
Expand All @@ -13,53 +11,72 @@ export interface Env {
unfreeze: () => void
}

export class CreatedBlock<T extends BlockService> extends Block<T> {
private globalBus: Bus
private globalSocket: Socket
private isEntry: boolean
private connectedBlocks: Record<string, BlockService> = {}
public exports: T['exports']
public symbol = SYMBOLS.CREATED_BLOCK
export class CreatedBlock<T extends BlockType> extends BaseBlock<T> {
#globalBus: Bus
#globalSocket: Socket
#isEntry: boolean
#socket: Socket
#app: App
#connectedBlocks: Record<string, BlockType> = {}

constructor(name: string, globalBus: Bus, globalSocket: Socket, isEntry: boolean) {
super(name)
this.globalBus = globalBus
this.globalSocket = globalSocket
this.isEntry = isEntry
socketsPool.set(name, this.socket)
const [bus] = touchBus(constant.privateBus(name))
const socket = bus.createSocket()
super(name, socket)
this.#socket = socket
this.#globalBus = globalBus
this.#globalSocket = globalSocket
this.#app = globalBus.createApp(name)
this.#isEntry = isEntry
}

public initState(state: T['state'], isPrivate?: boolean) {
this.#socket.initState(constant.stateNamespace(this.name), state as object, isPrivate)
return this
}

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

public relyOn(dependencies: string[]) {
this.#app.relyOn(dependencies)
return this
}

public relateTo(relatedApps: string[]) {
this.#app.relateTo(relatedApps)
return this
}

public onActivate(callback: () => void | Promise<void>) {
this.#app.onActivate(callback)
return this
}

public connect<P extends BlockService>(name: string) {
if (!this.connectedBlocks[name]) {
this.connectedBlocks[name] = new ConnectedBlock<P>(name)
public connect<P extends BlockType>(name: string) {
if (!this.#connectedBlocks[name]) {
const [bus] = touchBus(constant.privateBus(name))
const socket = bus.createSocket()
this.#connectedBlocks[name] = new BaseBlock<P>(name, socket)
}
return this.connectedBlocks[name] as ConnectedBlock<P>
return this.#connectedBlocks[name] as BaseBlock<P>
}

public load(name: string) {
if (this.globalBus.existApp(this.name)) {
return this.globalBus.loadApp(name)
}
throw new Error(errors.operateBeforeRegister(this.name, 'load'))
return this.#globalBus.loadApp(name)
}

public activate(name: string) {
if (this.globalBus.existApp(this.name)) {
return this.globalBus.activateApp(name)
}
throw new Error(errors.operateBeforeRegister(this.name, 'activate'))
return this.#globalBus.activateApp(name)
}

public async run(callback: (env: Env) => void | Promise<void>) {
const isBusAccessible =
this.isEntry || this.globalSocket.getState(constant.isGlobalBusAccessible)?.value
this.#isEntry || this.#globalSocket.getState(constant.isGlobalBusAccessible)?.value
const setBusAccessible = (isAccessible: boolean) => {
if (this.isEntry) {
this.globalSocket.setState(
if (this.#isEntry) {
this.#globalSocket.setState(
constant.isGlobalBusAccessible,
isAccessible ? 'unfreeze the enviroment' : 'freeze the enviroment',
(state) => {
Expand All @@ -69,15 +86,15 @@ export class CreatedBlock<T extends BlockService> extends Block<T> {
}
}
const env: Omit<Env, 'conf'> = {
isEntry: this.isEntry,
isEntry: this.#isEntry,
use: (middleware) => {
if (isBusAccessible) {
this.globalBus.use(middleware)
this.#globalBus.use(middleware)
}
},
config: (conf) => {
if (isBusAccessible) {
this.globalBus.config(conf)
this.#globalBus.config(conf)
}
},
freeze: () => {
Expand All @@ -91,7 +108,7 @@ export class CreatedBlock<T extends BlockService> extends Block<T> {
new Proxy(env as Env, {
get: (target, prop: keyof Env, receiver) => {
if (prop === 'conf') {
return JSON.parse(JSON.stringify(this.globalBus.conf))
return JSON.parse(JSON.stringify(this.#globalBus.conf))
}
return Reflect.get(target, prop, receiver)
},
Expand Down
19 changes: 4 additions & 15 deletions packages/block/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { CreatedBlock } from './created-block'
import type { BlockService } from './block'
import { BlockType } from './base-block'
import { touchBus } from '@rallie/core'
import { errors, constant, SYMBOLS } from './utils'
import { RegisteredBlock } from './registered-block'
import { errors, constant } from './utils'

export function createBlock<T extends BlockService = {}>(name: string) {
export function createBlock<T extends BlockType = {}>(name: string) {
const [globalBus, isEntry] = touchBus()
if (globalBus.existApp(name)) {
throw new Error(errors.duplicatedBlockName(name))
Expand All @@ -16,18 +15,8 @@ export function createBlock<T extends BlockService = {}>(name: string) {
return new CreatedBlock<T>(name, globalBus, globalSocket, isEntry)
}

export function registerBlock<T extends CreatedBlock<unknown>>(block: T) {
if (block.symbol === SYMBOLS.CREATED_BLOCK) {
return new RegisteredBlock<T>(block)
} else {
throw new Error(errors.invalidBlock(block.name))
}
}

export type { Block } from './block'
export type { BlockType, BaseBlock } from './base-block'
export type { CreatedBlock, Env } from './created-block'
export type { ConnectedBlock } from './connected-block'
export type { RegisteredBlock } from './registered-block'

export type {
ScriptType,
Expand Down
53 changes: 0 additions & 53 deletions packages/block/src/registered-block.ts

This file was deleted.

3 changes: 0 additions & 3 deletions packages/block/src/sockets-pool.ts

This file was deleted.

14 changes: 0 additions & 14 deletions packages/block/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
export type ConstraintedType<T, P, Default> = T extends P ? T : Default

export const SYMBOLS = {
CREATED_BLOCK: Symbol('createBlock'),
CONNECTED_BLOCK: Symbol('connectedBlock'),
}

export const constant = {
privateBus: (blockName: string) => `${blockName}.bus`,
stateNamespace: (blockName: string) => `${blockName}.state`,
Expand All @@ -22,14 +17,5 @@ export const errors = {
),
duplicatedBlockName: (blockName: string) =>
message(`the block ${blockName} is already registered before, please rename your block`),
invalidBlock: (name: string) =>
message(`failed to register the block ${name} because it is not a valid created block`),
stateIsReadonly: (blockName: string) => message(`the state of ${blockName} is readonly`),
operateBeforeRegister: (blockName: string, operate: 'activate' | 'load') =>
message(`the block ${blockName} can not ${operate} any other block unless it's registered`),
}

export const warnings = {
duplicatedExports: (blockName: string) =>
message(`you can only export once in the block ${blockName}`),
}
6 changes: 2 additions & 4 deletions packages/block/test/blocks/connect-testers/events.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { createBlock, registerBlock } from '../../../src'
import { createBlock } from '../../../src'

const block = createBlock<{
events: {
log: (text: string) => void
cancelListen: () => void
}
}>('connect-testers/events')

registerBlock(block).onActivate(() => {
}>('connect-testers/events').onActivate(() => {
const cancelListen = block.listenEvents({
log: (text) => console.log(text),
cancelListen: () => {
Expand Down
Loading

0 comments on commit 92e4ff0

Please sign in to comment.