{"version":3,"sources":["../../src/protocol/gateway.ts"],"sourcesContent":["export interface GatewayEnvelope<T> {\n  data: T;\n  proof: GatewayProof;\n}\n\nexport interface GatewayProof {\n  signature: string;\n  timestamp: string;\n  gatewayAddress: string;\n  requestHash: string;\n  responseHash: string;\n  userSignature: string;\n  status: string;\n  chainBlockHeight: number;\n}\n\nexport interface Builder {\n  id: string;\n  ownerAddress: string;\n  granteeAddress: string;\n  publicKey: string;\n  appUrl: string;\n  addedAt: string;\n}\n\nexport interface Schema {\n  id: string;\n  ownerAddress: string;\n  name: string;\n  definitionUrl: string;\n  scope: string;\n  addedAt: string;\n}\n\nexport interface ServerInfo {\n  id: string;\n  ownerAddress: string;\n  serverAddress: string;\n  publicKey: string;\n  serverUrl: string;\n  addedAt: string;\n}\n\nexport interface GatewayGrantResponse {\n  id: string;\n  grantorAddress: string;\n  granteeId: string;\n  grant: string;\n  fileIds: string[];\n  status: \"pending\" | \"confirmed\";\n  addedAt: string;\n  revokedAt: string | null;\n  revocationSignature: string | null;\n}\n\nexport interface GrantListItem {\n  id: string;\n  grantorAddress: string;\n  granteeId: string;\n  grant: string;\n  fileIds: string[];\n  status: \"pending\" | \"confirmed\";\n  addedAt: string;\n  revokedAt: string | null;\n  revocationSignature: string | null;\n}\n\nexport interface FileRecord {\n  fileId: string;\n  owner: string;\n  url: string;\n  schemaId: string;\n  createdAt: string;\n  /**\n   * Soft-deletion timestamp (ISO 8601), or null if the file is active. Always present\n   * (`normalizeFileRecord` populates it); non-null only when the gateway returns deletion state\n   * (e.g. listed with `includeDeleted`). Drives the PS sync delete-reconciliation.\n   */\n  deletedAt: string | null;\n}\n\nexport interface FileListResult {\n  files: FileRecord[];\n  cursor: string | null;\n}\n\nexport interface ListFilesOptions {\n  /**\n   * Include soft-deleted files in the result (each carries a non-null `deletedAt`). Default false.\n   * Used by the PS sync download worker to reconcile deletions of files it already holds locally.\n   */\n  includeDeleted?: boolean;\n}\n\ninterface GatewayFileRecord {\n  id?: string;\n  fileId?: string;\n  ownerAddress?: string;\n  owner?: string;\n  url: string;\n  schemaId: string;\n  addedAt?: string;\n  createdAt?: string;\n  deletedAt?: string | null;\n}\n\nexport interface RegisterFileParams {\n  ownerAddress: string;\n  url: string;\n  schemaId: string;\n  signature: string;\n}\n\nexport interface CreateGrantParams {\n  grantorAddress: string;\n  granteeId: string;\n  grant: string;\n  fileIds: string[];\n  signature: string;\n}\n\nexport interface RevokeGrantParams {\n  grantId: string;\n  grantorAddress: string;\n  signature: string;\n}\n\nexport interface DeleteFileParams {\n  fileId: string;\n  ownerAddress: string;\n  /** EIP-712 FileDeletion signature, signed by the owner or the owner's registered server. */\n  signature: string;\n}\n\nexport interface RegisterServerParams {\n  ownerAddress: string;\n  serverAddress: string;\n  publicKey: string;\n  serverUrl: string;\n  signature: string;\n}\n\nexport interface RegisterServerResult {\n  serverId?: string;\n  alreadyRegistered: boolean;\n}\n\nexport interface GatewayClient {\n  isRegisteredBuilder(address: string): Promise<boolean>;\n  getBuilder(address: string): Promise<Builder | null>;\n  getGrant(grantId: string): Promise<GatewayGrantResponse | null>;\n  listGrantsByUser(userAddress: string): Promise<GrantListItem[]>;\n  getSchemaForScope(scope: string): Promise<Schema | null>;\n  getServer(address: string): Promise<ServerInfo | null>;\n  getFile(fileId: string): Promise<FileRecord | null>;\n  listFilesSince(\n    owner: string,\n    cursor: string | null,\n    options?: ListFilesOptions,\n  ): Promise<FileListResult>;\n  getSchema(schemaId: string): Promise<Schema | null>;\n  registerServer(params: RegisterServerParams): Promise<RegisterServerResult>;\n  registerFile(params: RegisterFileParams): Promise<{ fileId?: string }>;\n  createGrant(params: CreateGrantParams): Promise<{ grantId?: string }>;\n  revokeGrant(params: RevokeGrantParams): Promise<void>;\n  /**\n   * Soft-deletes (de-registers) a file at the gateway. Resolves on 200 and on 409\n   * (already deleted) — 409 is treated as idempotent success. Other non-2xx, including\n   * 404 (file not registered), throw; the PS delete cascade decides whether a 404 is\n   * benign (blob already gone) or a hard failure.\n   */\n  deleteFile(params: DeleteFileParams): Promise<void>;\n}\n\nexport function createGatewayClient(baseUrl: string): GatewayClient {\n  const base = baseUrl.replace(/\\/+$/, \"\");\n\n  async function unwrapEnvelope<T>(res: Response): Promise<T> {\n    const envelope = (await res.json()) as GatewayEnvelope<T>;\n    return envelope.data;\n  }\n\n  function normalizeFileRecord(record: GatewayFileRecord): FileRecord {\n    return {\n      fileId: record.fileId ?? record.id ?? \"\",\n      owner: record.owner ?? record.ownerAddress ?? \"\",\n      url: record.url,\n      schemaId: record.schemaId,\n      createdAt: record.createdAt ?? record.addedAt ?? \"\",\n      deletedAt: record.deletedAt ?? null,\n    };\n  }\n\n  function getMutationId(\n    body: Record<string, unknown>,\n    key: string,\n  ): string | undefined {\n    const value = body[key] ?? body[\"id\"];\n    return typeof value === \"string\" ? value : undefined;\n  }\n\n  return {\n    async isRegisteredBuilder(address: string): Promise<boolean> {\n      const builder = await this.getBuilder(address);\n      return builder !== null;\n    },\n\n    async getBuilder(address: string): Promise<Builder | null> {\n      const res = await fetch(`${base}/v1/builders/${address}`);\n      if (res.status === 404) return null;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return unwrapEnvelope<Builder>(res);\n    },\n\n    async getGrant(grantId: string): Promise<GatewayGrantResponse | null> {\n      const res = await fetch(`${base}/v1/grants/${grantId}`);\n      if (res.status === 404) return null;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return unwrapEnvelope<GatewayGrantResponse>(res);\n    },\n\n    async listGrantsByUser(userAddress: string): Promise<GrantListItem[]> {\n      const res = await fetch(`${base}/v1/grants?user=${userAddress}`);\n      if (res.status === 404) return [];\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return unwrapEnvelope<GrantListItem[]>(res);\n    },\n\n    async getSchemaForScope(scope: string): Promise<Schema | null> {\n      const res = await fetch(`${base}/v1/schemas?scope=${scope}`);\n      if (res.status === 404) return null;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return unwrapEnvelope<Schema>(res);\n    },\n\n    async getServer(address: string): Promise<ServerInfo | null> {\n      const res = await fetch(`${base}/v1/servers/${address}`);\n      if (res.status === 404) return null;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return unwrapEnvelope<ServerInfo>(res);\n    },\n\n    async getFile(fileId: string): Promise<FileRecord | null> {\n      const res = await fetch(`${base}/v1/files/${fileId}`);\n      if (res.status === 404) return null;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return normalizeFileRecord(await unwrapEnvelope<GatewayFileRecord>(res));\n    },\n\n    async listFilesSince(\n      owner: string,\n      cursor: string | null,\n      options?: ListFilesOptions,\n    ): Promise<FileListResult> {\n      const params = new URLSearchParams({ user: owner });\n      if (cursor !== null) {\n        params.set(\"since\", cursor);\n      }\n      if (options?.includeDeleted) {\n        params.set(\"includeDeleted\", \"true\");\n      }\n      const res = await fetch(`${base}/v1/files?${params.toString()}`);\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      const data = await unwrapEnvelope<{\n        files: GatewayFileRecord[];\n        cursor: string | null;\n      }>(res);\n      return {\n        files: data.files.map(normalizeFileRecord),\n        cursor: data.cursor,\n      };\n    },\n\n    async getSchema(schemaId: string): Promise<Schema | null> {\n      const res = await fetch(`${base}/v1/schemas/${schemaId}`);\n      if (res.status === 404) return null;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      return unwrapEnvelope<Schema>(res);\n    },\n\n    async registerServer(\n      params: RegisterServerParams,\n    ): Promise<RegisterServerResult> {\n      const res = await fetch(`${base}/v1/servers`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify({\n          ownerAddress: params.ownerAddress,\n          serverAddress: params.serverAddress,\n          publicKey: params.publicKey,\n          serverUrl: params.serverUrl,\n        }),\n      });\n      if (res.status === 409) {\n        const body = await res.json().catch(() => ({}));\n        return {\n          serverId: getMutationId(body as Record<string, unknown>, \"serverId\"),\n          alreadyRegistered: true,\n        };\n      }\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      const body = await res.json().catch(() => ({}));\n      return {\n        serverId: getMutationId(body as Record<string, unknown>, \"serverId\"),\n        alreadyRegistered: false,\n      };\n    },\n\n    async registerFile(\n      params: RegisterFileParams,\n    ): Promise<{ fileId?: string }> {\n      const res = await fetch(`${base}/v1/files`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify({\n          ownerAddress: params.ownerAddress,\n          url: params.url,\n          schemaId: params.schemaId,\n        }),\n      });\n      if (res.status === 409) {\n        const body = await res.json().catch(() => ({}));\n        return {\n          fileId: getMutationId(body as Record<string, unknown>, \"fileId\"),\n        };\n      }\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      const body = await res.json();\n      return {\n        fileId: getMutationId(body as Record<string, unknown>, \"fileId\"),\n      };\n    },\n\n    async createGrant(\n      params: CreateGrantParams,\n    ): Promise<{ grantId?: string }> {\n      const res = await fetch(`${base}/v1/grants`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify({\n          grantorAddress: params.grantorAddress,\n          granteeId: params.granteeId,\n          grant: params.grant,\n          fileIds: params.fileIds,\n        }),\n      });\n      if (res.status === 409) {\n        const body = await res.json().catch(() => ({}));\n        return {\n          grantId: getMutationId(body as Record<string, unknown>, \"grantId\"),\n        };\n      }\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n      const body = await res.json();\n      return {\n        grantId: getMutationId(body as Record<string, unknown>, \"grantId\"),\n      };\n    },\n\n    async revokeGrant(params: RevokeGrantParams): Promise<void> {\n      const res = await fetch(`${base}/v1/grants/${params.grantId}`, {\n        method: \"DELETE\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify({\n          grantorAddress: params.grantorAddress,\n        }),\n      });\n      if (res.status === 409) return;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n    },\n\n    async deleteFile(params: DeleteFileParams): Promise<void> {\n      const res = await fetch(`${base}/v1/files/${params.fileId}`, {\n        method: \"DELETE\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          Authorization: `Web3Signed ${params.signature}`,\n        },\n        body: JSON.stringify({\n          ownerAddress: params.ownerAddress,\n        }),\n      });\n      // 409 = already deleted; treat as success (idempotent), same as revokeGrant.\n      if (res.status === 409) return;\n      if (!res.ok) {\n        throw new Error(`Gateway error: ${res.status} ${res.statusText}`);\n      }\n    },\n  };\n}\n"],"mappings":"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","names":["body"]}