summaryrefslogtreecommitdiffhomepage
path: root/packages/console/core/src/actor.ts
blob: 0d13f7216f2aad13106a7f73c4de9d7aa846dcf6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import { Context } from "./context"
import { Log } from "./util/log"

export namespace Actor {
  interface Account {
    type: "account"
    properties: {
      accountID: string
      email: string
    }
  }

  interface Public {
    type: "public"
    properties: {}
  }

  interface User {
    type: "user"
    properties: {
      userID: string
      workspaceID: string
    }
  }

  interface System {
    type: "system"
    properties: {
      workspaceID: string
    }
  }

  export type Info = Account | Public | User | System

  const ctx = Context.create<Info>()
  export const use = ctx.use

  const log = Log.create().tag("namespace", "actor")

  export function provide<R, T extends Info["type"]>(
    type: T,
    properties: Extract<Info, { type: T }>["properties"],
    cb: () => R,
  ) {
    return ctx.provide(
      {
        type,
        properties,
      } as any,
      () => {
        return Log.provide({ ...properties }, () => {
          log.info("provided")
          return cb()
        })
      },
    )
  }

  export function assert<T extends Info["type"]>(type: T) {
    const actor = use()
    if (actor.type !== type) {
      throw new Error(`Expected actor type ${type}, got ${actor.type}`)
    }
    return actor as Extract<Info, { type: T }>
  }

  export function workspace() {
    const actor = use()
    if ("workspaceID" in actor.properties) {
      return actor.properties.workspaceID
    }
    throw new Error(`actor of type "${actor.type}" is not associated with a workspace`)
  }
}