instance.ts 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. import { Context } from "../util/context"
  2. import { Project } from "./project"
  3. import { State } from "./state"
  4. interface Context {
  5. directory: string
  6. worktree: string
  7. project: Project.Info
  8. }
  9. const context = Context.create<Context>("instance")
  10. const cache = new Map<string, Context>()
  11. export const Instance = {
  12. async provide<R>(input: { directory: string; init?: () => Promise<any>; fn: () => R }): Promise<R> {
  13. let existing = cache.get(input.directory)
  14. if (!existing) {
  15. const project = await Project.fromDirectory(input.directory)
  16. existing = {
  17. directory: input.directory,
  18. worktree: project.worktree,
  19. project,
  20. }
  21. }
  22. return context.provide(existing, async () => {
  23. if (!cache.has(input.directory)) {
  24. await input.init?.()
  25. cache.set(input.directory, existing)
  26. }
  27. return input.fn()
  28. })
  29. },
  30. get directory() {
  31. return context.use().directory
  32. },
  33. get worktree() {
  34. return context.use().worktree
  35. },
  36. get project() {
  37. return context.use().project
  38. },
  39. state<S>(init: () => S, dispose?: (state: Awaited<S>) => Promise<void>): () => S {
  40. return State.create(() => Instance.directory, init, dispose)
  41. },
  42. async dispose() {
  43. await State.dispose(Instance.directory)
  44. },
  45. }