command.ts 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. export * as CommandV2 from "./command"
  2. import { makeLocationNode } from "./effect/app-node"
  3. import { Context, Effect, Layer, Types } from "effect"
  4. import { Command } from "@kirincode-ai/schema/command"
  5. import { State } from "./state"
  6. export const Info = Command.Info
  7. export type Info = Command.Info
  8. export type Data = {
  9. commands: Map<string, Types.DeepMutable<Info>>
  10. }
  11. export type Draft = {
  12. list: () => readonly Info[]
  13. get: (name: string) => Info | undefined
  14. update: (name: string, update: (command: Types.DeepMutable<Info>) => void) => void
  15. remove: (name: string) => void
  16. }
  17. export interface Interface extends State.Transformable<Draft> {
  18. readonly get: (name: string) => Effect.Effect<Info | undefined>
  19. readonly list: () => Effect.Effect<Info[]>
  20. }
  21. export class Service extends Context.Service<Service, Interface>()("@kirincode/v2/Command") {}
  22. const layer = Layer.effect(
  23. Service,
  24. Effect.sync(() => {
  25. const state = State.create<Data, Draft>({
  26. initial: () => ({ commands: new Map() }),
  27. draft: (draft) => ({
  28. list: () => Array.from(draft.commands.values()) as Info[],
  29. get: (name) => draft.commands.get(name),
  30. update: (name, update) => {
  31. const current = draft.commands.get(name) ?? ({ name, template: "" } as Types.DeepMutable<Info>)
  32. if (!draft.commands.has(name)) draft.commands.set(name, current)
  33. update(current)
  34. current.name = name
  35. },
  36. remove: (name) => {
  37. draft.commands.delete(name)
  38. },
  39. }),
  40. })
  41. return Service.of({
  42. reload: state.reload,
  43. transform: state.transform,
  44. get: Effect.fn("CommandV2.get")(function* (name) {
  45. return state.get().commands.get(name)
  46. }),
  47. list: Effect.fn("CommandV2.list")(function* () {
  48. return Array.from(state.get().commands.values())
  49. }),
  50. })
  51. }),
  52. )
  53. export const locationLayer = layer
  54. export const node = makeLocationNode({ service: Service, layer, deps: [] })