Skip to content

Commit

Permalink
fix: removed unused code. Convert Effects to a class
Browse files Browse the repository at this point in the history
  • Loading branch information
tdreyno committed Apr 16, 2022
1 parent 3277933 commit 2fd5a6a
Show file tree
Hide file tree
Showing 15 changed files with 1,687 additions and 2,236 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ import { createMachine } from "@tdreyno/fizz/svelte"
const machine = createMachine(states, actions, initialState)

$: {
console.log($machine.currentState);
console.log($machine.currentState)
}
```
Expand All @@ -196,15 +196,15 @@ import { state, Enter } from "@tdreyno/fizz"
const MyState = state<Enter>({
Enter: () => log("Entered state MyState."),
})
````
```
In this case, `log` is a side-effect which will log to the console. It is implemented like so:
```javascript
// The side-effect generating function.
function log(msg) {
// A representation of the effect, but not the execution.
return internalEffect(
return effect(
// An effect name. Helps when writing tests and middleware.
"log",

Expand Down
15 changes: 2 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,9 @@
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^8.0.4",
"@testing-library/jest-dom": "^5.16.1",
"@testing-library/react": "^12.1.3",
"@testing-library/svelte": "^3.1.0",
"@types/jest": "^27.4.0",
"@types/lodash.flatten": "^4.4.6",
"@types/lodash.isfunction": "^3.0.6",
"@types/lodash.isplainobject": "^4.0.6",
"@types/lodash.mapvalues": "^4.6.6",
"@types/node": "^17.0.23",
"@types/react": "^17.0.39",
"@types/node": "^16.11.7",
"@types/serialize-javascript": "^5.0.1",
"@typescript-eslint/eslint-plugin": "^5.10.2",
"@typescript-eslint/parser": "^5.17.0",
Expand All @@ -57,8 +51,6 @@
"jest": "^27.5.1",
"lint-staged": "^12.3.7",
"prettier": "^2.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"semantic-release": "^19.0.0",
"serialize-javascript": "^6.0.0",
"svelte": "^3.46",
Expand All @@ -67,11 +59,8 @@
"ts-jest": "^27.0.7",
"typescript": "^4.6.3"
},
"dependencies": {
"lodash.isfunction": "^3.0.9"
},
"dependencies": {},
"peerDependencies": {
"react": ">=16.0.0",
"svelte": "^3.46"
},
"lint-staged": {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/runtime.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ describe("Runtime", () => {

function serializeContext(c: Context) {
return serializeJavascript(
c.history.map(({ data, name }) => ({
c.history.toArray().map(({ data, name }) => ({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
data,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Expand Down
16 changes: 5 additions & 11 deletions src/action.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
export class Action_<T extends string, P> {
export class Action<T extends string, P> {
constructor(public type: T, public payload: P) {}
}

export const Action = <T extends string, P>(type: T, payload: P) =>
new Action_(type, payload)
export type Action<T extends string, P> = Action_<T, P>
export const action = <T extends string, P>(type: T, payload: P) =>
new Action(type, payload)

export type ActionName<
A extends Action<any, any>,
Expand All @@ -14,12 +13,7 @@ export type ActionName<
export type ActionPayload<A extends Action<any, any>> = A["payload"]

export const isAction = <T extends string>(a: unknown): a is Action<T, any> =>
a instanceof Action_

export const isActions = (
actions: unknown,
): actions is Array<Action<any, any>> =>
Array.isArray(actions) && actions.every(isAction)
a instanceof Action

export interface MatchAction<T extends string, P> {
is(action: Action<any, any>): action is Action<T, P>
Expand All @@ -34,7 +28,7 @@ export type ActionCreatorType<F extends ActionCreator<any, any>> = ReturnType<F>
export const createAction = <T extends string, P = undefined>(
type: T,
): ActionCreator<T, P> & MatchAction<T, P> => {
const fn = (payload?: P) => Action(type, payload)
const fn = (payload?: P) => action(type, payload)

fn.is = (action: Action<any, any>): action is Action<T, P> =>
action.type === type
Expand Down
25 changes: 1 addition & 24 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,13 @@ export class History<
return this.items.shift()
}

removePrevious(): void {
if (this.length <= 1) {
return
}

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const head = this.pop()!

this.pop()

this.push(head)
}

toArray(): Array<T> {
return [...this.items]
}

map<B>(fn: (item: T) => B): Array<B> {
return this.toArray().map(fn)
return this.items
}
}

interface Options {
maxHistory: number
onAsyncEnterExit: "throw" | "warn" | "silent"
enableLogging: boolean
customLogger?:
| undefined
Expand All @@ -73,10 +55,6 @@ export class Context {
private options_: Omit<Options, "maxHistory">,
) {}

get onAsyncEnterExit() {
return this.options_.onAsyncEnterExit
}

get enableLogging() {
return this.options_.enableLogging
}
Expand All @@ -95,7 +73,6 @@ export const createInitialContext = (
options?: Partial<Options>,
) =>
new Context(new History(history, options?.maxHistory ?? Infinity), {
onAsyncEnterExit: options?.onAsyncEnterExit ?? "warn",
enableLogging: options?.enableLogging ?? false,
customLogger: options?.customLogger,
})
60 changes: 17 additions & 43 deletions src/effect.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,24 @@
import type { Action } from "./action.js"
import type { Context } from "./context.js"

export interface Effect<T = any> {
label: string
data: T
isEffect: true
executor: (context: Context) => void
export class Effect<T = unknown> {
constructor(
public label: string,
public data: T | undefined,
public executor: (context: Context) => void,
) {}
}

export const isEffect = (e: unknown): e is Effect =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
(e as any)?.isEffect
export const isEffect = (e: unknown): e is Effect => e instanceof Effect

export const isEffects = (effects: unknown): effects is Array<Effect> =>
Array.isArray(effects) && effects.every(isEffect)

const RESERVED_EFFECTS = ["goBack", "log", "error", "warn", "noop", "timeout"]

export const __internalEffect = <D, F extends (context: Context) => void>(
label: string,
data: D,
executor: F,
): Effect<D> => ({
label,
data,
executor,
isEffect: true,
})

export const effect = <D, F extends (context: Context) => void>(
export const effect = <D>(
label: string,
data: D,
executor?: F,
): Effect<D> => {
if (RESERVED_EFFECTS.includes(label)) {
throw new Error(
`${label} is a reserved effect label, please change the label of your custom effect`,
)
}

return __internalEffect(label, data, executor || (() => void 0))
}
data?: D,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
executor: (context: Context) => void = (_context: Context) => void 0,
) => new Effect(label, data, executor)

export const goBack = (): Effect<void> =>
__internalEffect("goBack", undefined, () => void 0)
export const goBack = (): Effect<void> => effect("goBack")

const handleLog =
<T extends Array<any>>(
Expand All @@ -60,16 +35,15 @@ const handleLog =
}

export const log = <T extends Array<any>>(...msgs: T): Effect<T> =>
__internalEffect("log", msgs, handleLog(msgs, "log", console.log))
effect("log", msgs, handleLog(msgs, "log", console.log))

export const error = <T extends Array<any>>(...msgs: T): Effect<T> =>
__internalEffect("error", msgs, handleLog(msgs, "error", console.error))
effect("error", msgs, handleLog(msgs, "error", console.error))

export const warn = <T extends Array<any>>(...msgs: T): Effect<T> =>
__internalEffect("warn", msgs, handleLog(msgs, "warn", console.warn))
effect("warn", msgs, handleLog(msgs, "warn", console.warn))

export const noop = (): Effect<void> =>
__internalEffect("noop", undefined, () => void 0)
export const noop = (): Effect<void> => effect("noop")

export const timeout = <A extends Action<any, any>>(
ms: number,
Expand Down
74 changes: 36 additions & 38 deletions src/errors.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,42 @@
import type { Action } from "./action.js"
import type { StateTransition } from "./state.js"

export class StateDidNotRespondToAction extends Error {
constructor(
public state: StateTransition<any, any, any>,
public action: Action<any, any>,
) {
super()
}

override toString() {
return `State "${this.state.name as string}" could not respond to action: ${
this.action.type as string
}`
}
}

export class NoStatesRespondToAction extends Error {
constructor(
public states: Array<StateTransition<any, any, any>>,
public action: Action<any, any>,
) {
super()
}

override toString() {
return `The states ${this.states
.map(s => s.name as string)
.join(", ")} were unable to respond to action: ${
this.action.type as string
}`
}
}

export class NoMatchingActionTargets extends Error {}
// import type { Action } from "./action.js"
// import type { StateTransition } from "./state.js"

// class StateDidNotRespondToAction extends Error {
// constructor(
// public state: StateTransition<any, any, any>,
// public action: Action<any, any>,
// ) {
// super()
// }

// override toString() {
// return `State "${this.state.name as string}" could not respond to action: ${
// this.action.type as string
// }`
// }
// }

// class NoStatesRespondToAction extends Error {
// constructor(
// public states: Array<StateTransition<any, any, any>>,
// public action: Action<any, any>,
// ) {
// super()
// }

// override toString() {
// return `The states ${this.states
// .map(s => s.name as string)
// .join(", ")} were unable to respond to action: ${
// this.action.type as string
// }`
// }
// }

// class NoMatchingActionTargets extends Error {}

export class MissingCurrentState extends Error {}

export class EnterExitMustBeSynchronous extends Error {}

export class UnknownStateReturnType<
T extends { toString(): string },
> extends Error {
Expand Down
Loading

0 comments on commit 2fd5a6a

Please sign in to comment.