{"version":3,"file":"EdvClient.mjs","names":["code: string | undefined","description: string | undefined","parts: string[]"],"sources":["../../src/edv/EdvClient.ts"],"sourcesContent":["/**\n * EDV HTTP client. The data plane lives here — DIDComm messages never\n * carry encrypted blob bytes per spec § EDV Usage.\n *\n *   * `Authorization: ZcapLD <b64-no-padding>,<b64-no-padding>,...`\n *     (child-to-root capability chain)\n *   * `Content-Type: application/json` request bodies\n *   * Response codes: 200/201/204 success; 401 cap-unauthorized;\n *     404 doc-not-found / vault-not-found; 409 concurrency-conflict\n *\n * Uses the global `fetch` so no extra HTTP dep is needed.\n */\n\nimport { b64uEncode } from '../jwe/b64url'\nimport type { Capability } from '../zcap'\n\nimport {\n  EdvClientError,\n  type EncryptedDocument,\n  type QueryRequest,\n  type QueryResponse,\n} from './types'\n\nexport interface EdvClientOptions {\n  /**\n   * Optional `fetch` override. Defaults to `globalThis.fetch`. Useful\n   * for injecting a tracing wrapper or a test stub.\n   */\n  fetch?: typeof globalThis.fetch\n}\n\nexport class EdvClient {\n  private fetchFn: typeof globalThis.fetch\n\n  public constructor(opts: EdvClientOptions = {}) {\n    this.fetchFn = opts.fetch ?? globalThis.fetch\n    if (!this.fetchFn) {\n      throw new Error('EdvClient: no global `fetch` available; pass one via options')\n    }\n  }\n\n  // ─────────────────────────────────────────────────────────────────\n  // CRUD\n  // ─────────────────────────────────────────────────────────────────\n\n  /**\n   * `POST /edvs/{vault_id}/documents`. Server enforces `sequence === 0`\n   * on create and that `Authorization: ZcapLD` includes write.\n   */\n  public async createDocument(args: {\n    baseUrl: string\n    document: EncryptedDocument\n    chain: Capability[]\n  }): Promise<EncryptedDocument> {\n    const url = `${stripTrailingSlash(args.baseUrl)}/documents`\n    const res = await this.fetchFn(url, {\n      method: 'POST',\n      headers: this.headers(args.chain),\n      body: JSON.stringify(args.document),\n    })\n    return this.parseJson(res, 201)\n  }\n\n  /**\n   * `GET /edvs/{vault_id}/documents/{doc_id}`. Returns the\n   * `EncryptedDocument` whose `jwe` field the caller then decrypts\n   * locally via the JWE module.\n   */\n  public async getDocument(args: {\n    baseUrl: string\n    docId: string\n    chain: Capability[]\n  }): Promise<EncryptedDocument> {\n    const url = `${stripTrailingSlash(args.baseUrl)}/documents/${encodeURIComponent(args.docId)}`\n    const res = await this.fetchFn(url, {\n      method: 'GET',\n      headers: this.headers(args.chain),\n    })\n    return this.parseJson(res, 200)\n  }\n\n  /**\n   * `PUT /edvs/{vault_id}/documents/{doc_id}`. Server enforces\n   * `sequence == stored.sequence + 1` (RFC 7517 OCC).\n   */\n  public async updateDocument(args: {\n    baseUrl: string\n    document: EncryptedDocument\n    chain: Capability[]\n  }): Promise<EncryptedDocument> {\n    const url = `${stripTrailingSlash(args.baseUrl)}/documents/${encodeURIComponent(args.document.id)}`\n    const res = await this.fetchFn(url, {\n      method: 'PUT',\n      headers: this.headers(args.chain),\n      body: JSON.stringify(args.document),\n    })\n    return this.parseJson(res, 200)\n  }\n\n  /**\n   * `DELETE /edvs/{vault_id}/documents/{doc_id}`. Server returns 204.\n   */\n  public async deleteDocument(args: {\n    baseUrl: string\n    docId: string\n    chain: Capability[]\n  }): Promise<void> {\n    const url = `${stripTrailingSlash(args.baseUrl)}/documents/${encodeURIComponent(args.docId)}`\n    const res = await this.fetchFn(url, {\n      method: 'DELETE',\n      headers: this.headers(args.chain),\n    })\n    if (res.status !== 204) {\n      await this.raiseFromResponse(res)\n    }\n  }\n\n  /**\n   * `POST /edvs/{vault_id}/query`. Equality-only HMAC indexes per\n   * spec § EDV Usage § Indexes.\n   */\n  public async query(args: {\n    baseUrl: string\n    request: QueryRequest\n    chain: Capability[]\n  }): Promise<QueryResponse> {\n    const url = `${stripTrailingSlash(args.baseUrl)}/query`\n    const res = await this.fetchFn(url, {\n      method: 'POST',\n      headers: this.headers(args.chain),\n      body: JSON.stringify(args.request),\n    })\n    return this.parseJson(res, 200)\n  }\n\n  // ─────────────────────────────────────────────────────────────────\n  // helpers\n  // ─────────────────────────────────────────────────────────────────\n\n  private headers(chain: Capability[]): Record<string, string> {\n    return {\n      Authorization: encodeChainHeader(chain),\n      'Content-Type': 'application/json',\n      Accept: 'application/json',\n    }\n  }\n\n  private async parseJson<T>(res: Response, expectedStatus: number): Promise<T> {\n    if (res.status !== expectedStatus) {\n      await this.raiseFromResponse(res)\n    }\n    return (await res.json()) as T\n  }\n\n  private async raiseFromResponse(res: Response): Promise<never> {\n    let code: string | undefined\n    let description: string | undefined\n    try {\n      const body = (await res.json()) as { code?: string; description?: string }\n      code = body.code\n      description = body.description\n    } catch {\n      // Non-JSON body — surface status only.\n    }\n    throw new EdvClientError(\n      description ?? `EDV HTTP ${res.status} ${res.statusText}`,\n      res.status,\n      code\n    )\n  }\n}\n\nconst textEncoder = new TextEncoder()\n\n/** Encode a capability chain into the `Authorization: ZcapLD ...` value. */\nexport function encodeChainHeader(chain: Capability[]): string {\n  const parts: string[] = []\n  for (const cap of chain) {\n    const raw = textEncoder.encode(JSON.stringify(cap.toDict()))\n    parts.push(b64uEncode(raw))\n  }\n  return 'ZcapLD ' + parts.join(',')\n}\n\nfunction stripTrailingSlash(s: string): string {\n  return s.endsWith('/') ? s.slice(0, -1) : s\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA+BA,IAAa,YAAb,MAAuB;CAGrB,AAAO,YAAY,OAAyB,EAAE,EAAE;AAC9C,OAAK,UAAU,KAAK,SAAS,WAAW;AACxC,MAAI,CAAC,KAAK,QACR,OAAM,IAAI,MAAM,+DAA+D;;;;;;CAYnF,MAAa,eAAe,MAIG;EAC7B,MAAM,MAAM,GAAG,mBAAmB,KAAK,QAAQ,CAAC;EAChD,MAAM,MAAM,MAAM,KAAK,QAAQ,KAAK;GAClC,QAAQ;GACR,SAAS,KAAK,QAAQ,KAAK,MAAM;GACjC,MAAM,KAAK,UAAU,KAAK,SAAS;GACpC,CAAC;AACF,SAAO,KAAK,UAAU,KAAK,IAAI;;;;;;;CAQjC,MAAa,YAAY,MAIM;EAC7B,MAAM,MAAM,GAAG,mBAAmB,KAAK,QAAQ,CAAC,aAAa,mBAAmB,KAAK,MAAM;EAC3F,MAAM,MAAM,MAAM,KAAK,QAAQ,KAAK;GAClC,QAAQ;GACR,SAAS,KAAK,QAAQ,KAAK,MAAM;GAClC,CAAC;AACF,SAAO,KAAK,UAAU,KAAK,IAAI;;;;;;CAOjC,MAAa,eAAe,MAIG;EAC7B,MAAM,MAAM,GAAG,mBAAmB,KAAK,QAAQ,CAAC,aAAa,mBAAmB,KAAK,SAAS,GAAG;EACjG,MAAM,MAAM,MAAM,KAAK,QAAQ,KAAK;GAClC,QAAQ;GACR,SAAS,KAAK,QAAQ,KAAK,MAAM;GACjC,MAAM,KAAK,UAAU,KAAK,SAAS;GACpC,CAAC;AACF,SAAO,KAAK,UAAU,KAAK,IAAI;;;;;CAMjC,MAAa,eAAe,MAIV;EAChB,MAAM,MAAM,GAAG,mBAAmB,KAAK,QAAQ,CAAC,aAAa,mBAAmB,KAAK,MAAM;EAC3F,MAAM,MAAM,MAAM,KAAK,QAAQ,KAAK;GAClC,QAAQ;GACR,SAAS,KAAK,QAAQ,KAAK,MAAM;GAClC,CAAC;AACF,MAAI,IAAI,WAAW,IACjB,OAAM,KAAK,kBAAkB,IAAI;;;;;;CAQrC,MAAa,MAAM,MAIQ;EACzB,MAAM,MAAM,GAAG,mBAAmB,KAAK,QAAQ,CAAC;EAChD,MAAM,MAAM,MAAM,KAAK,QAAQ,KAAK;GAClC,QAAQ;GACR,SAAS,KAAK,QAAQ,KAAK,MAAM;GACjC,MAAM,KAAK,UAAU,KAAK,QAAQ;GACnC,CAAC;AACF,SAAO,KAAK,UAAU,KAAK,IAAI;;CAOjC,AAAQ,QAAQ,OAA6C;AAC3D,SAAO;GACL,eAAe,kBAAkB,MAAM;GACvC,gBAAgB;GAChB,QAAQ;GACT;;CAGH,MAAc,UAAa,KAAe,gBAAoC;AAC5E,MAAI,IAAI,WAAW,eACjB,OAAM,KAAK,kBAAkB,IAAI;AAEnC,SAAQ,MAAM,IAAI,MAAM;;CAG1B,MAAc,kBAAkB,KAA+B;EAC7D,IAAIA;EACJ,IAAIC;AACJ,MAAI;GACF,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,UAAO,KAAK;AACZ,iBAAc,KAAK;UACb;AAGR,QAAM,IAAI,eACR,eAAe,YAAY,IAAI,OAAO,GAAG,IAAI,cAC7C,IAAI,QACJ,KACD;;;AAIL,MAAM,cAAc,IAAI,aAAa;;AAGrC,SAAgB,kBAAkB,OAA6B;CAC7D,MAAMC,QAAkB,EAAE;AAC1B,MAAK,MAAM,OAAO,OAAO;EACvB,MAAM,MAAM,YAAY,OAAO,KAAK,UAAU,IAAI,QAAQ,CAAC,CAAC;AAC5D,QAAM,KAAK,WAAW,IAAI,CAAC;;AAE7B,QAAO,YAAY,MAAM,KAAK,IAAI;;AAGpC,SAAS,mBAAmB,GAAmB;AAC7C,QAAO,EAAE,SAAS,IAAI,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG"}