share.ts 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import { App } from "../app/app"
  2. import { Bus } from "../bus"
  3. import { Session } from "../session"
  4. import { Storage } from "../storage/storage"
  5. import { Log } from "../util/log"
  6. export namespace Share {
  7. const log = Log.create({ service: "share" })
  8. let queue: Promise<void> = Promise.resolve()
  9. const pending = new Map<string, any>()
  10. const state = App.state("share", async () => {
  11. Bus.subscribe(Storage.Event.Write, async (payload) => {
  12. await sync(payload.properties.key, payload.properties.content)
  13. })
  14. })
  15. export async function sync(key: string, content: any) {
  16. const [root, ...splits] = key.split("/")
  17. if (root !== "session") return
  18. const [, sessionID] = splits
  19. const session = await Session.get(sessionID)
  20. if (!session.share) return
  21. const { secret } = session.share
  22. pending.set(key, content)
  23. queue = queue
  24. .then(async () => {
  25. const content = pending.get(key)
  26. if (content === undefined) return
  27. pending.delete(key)
  28. return fetch(`${URL}/share_sync`, {
  29. method: "POST",
  30. body: JSON.stringify({
  31. sessionID: sessionID,
  32. secret,
  33. key: key,
  34. content,
  35. }),
  36. })
  37. })
  38. .then((x) => {
  39. if (x) {
  40. log.info("synced", {
  41. key: key,
  42. status: x.status,
  43. })
  44. }
  45. })
  46. }
  47. export async function init() {
  48. await state()
  49. }
  50. export const URL =
  51. process.env["OPENCODE_API"] ?? "https://api.dev.opencode.ai"
  52. export async function create(sessionID: string) {
  53. return fetch(`${URL}/share_create`, {
  54. method: "POST",
  55. body: JSON.stringify({ sessionID: sessionID }),
  56. })
  57. .then((x) => x.json())
  58. .then((x) => x as { url: string; secret: string })
  59. }
  60. }