@opendatalabs/vana-sdk 3.3.0 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.js +12 -6
- package/dist/index.browser.js.map +2 -2
- package/dist/index.node.cjs +12 -6
- package/dist/index.node.cjs.map +2 -2
- package/dist/index.node.d.ts +1 -1
- package/dist/index.node.js +12 -6
- package/dist/index.node.js.map +2 -2
- package/dist/protocol/gateway.cjs +12 -6
- package/dist/protocol/gateway.cjs.map +1 -1
- package/dist/protocol/gateway.d.ts +30 -1
- package/dist/protocol/gateway.js +12 -6
- package/dist/protocol/gateway.js.map +1 -1
- package/package.json +1 -1
|
@@ -33,7 +33,8 @@ function createGatewayClient(baseUrl) {
|
|
|
33
33
|
owner: record.owner ?? record.ownerAddress ?? "",
|
|
34
34
|
url: record.url,
|
|
35
35
|
schemaId: record.schemaId,
|
|
36
|
-
createdAt: record.createdAt ?? record.addedAt ?? ""
|
|
36
|
+
createdAt: record.createdAt ?? record.addedAt ?? "",
|
|
37
|
+
deletedAt: record.deletedAt ?? null
|
|
37
38
|
};
|
|
38
39
|
}
|
|
39
40
|
function getMutationId(body, key) {
|
|
@@ -93,19 +94,24 @@ function createGatewayClient(baseUrl) {
|
|
|
93
94
|
}
|
|
94
95
|
return normalizeFileRecord(await unwrapEnvelope(res));
|
|
95
96
|
},
|
|
96
|
-
async listFilesSince(owner, cursor) {
|
|
97
|
+
async listFilesSince(owner, cursor, options) {
|
|
97
98
|
const params = new URLSearchParams({ user: owner });
|
|
98
99
|
if (cursor !== null) {
|
|
99
|
-
params.set("
|
|
100
|
+
params.set("cursor", cursor);
|
|
101
|
+
}
|
|
102
|
+
if (options?.includeDeleted) {
|
|
103
|
+
params.set("includeDeleted", "true");
|
|
100
104
|
}
|
|
101
105
|
const res = await fetch(`${base}/v1/files?${params.toString()}`);
|
|
102
106
|
if (!res.ok) {
|
|
103
107
|
throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
|
|
104
108
|
}
|
|
105
|
-
const
|
|
109
|
+
const envelope = await res.json();
|
|
110
|
+
const { pagination } = envelope;
|
|
111
|
+
const nextCursor = pagination?.hasMore === false ? null : pagination?.nextCursor ?? envelope.data.cursor ?? null;
|
|
106
112
|
return {
|
|
107
|
-
files: data.files.map(normalizeFileRecord),
|
|
108
|
-
cursor:
|
|
113
|
+
files: envelope.data.files.map(normalizeFileRecord),
|
|
114
|
+
cursor: nextCursor
|
|
109
115
|
};
|
|
110
116
|
},
|
|
111
117
|
async getSchema(schemaId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"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\nexport interface FileListResult {\n files: FileRecord[];\n cursor: string | null;\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}\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(owner: string, cursor: string | null): 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 };\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 ): Promise<FileListResult> {\n const params = new URLSearchParams({ user: owner });\n if (cursor !== null) {\n params.set(\"since\", cursor);\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"]}
|
|
1
|
+
{"version":3,"sources":["../../src/protocol/gateway.ts"],"sourcesContent":["export interface GatewayEnvelope<T> {\n data: T;\n proof: GatewayProof;\n /**\n * Cursor-based pagination metadata, present on list endpoints (e.g.\n * `GET /v1/files`). A sibling of `data`, not nested inside it — so callers\n * that need it must read the full envelope rather than going through\n * `unwrapEnvelope`, which intentionally returns only `data`.\n */\n pagination?: GatewayPagination;\n}\n\nexport interface GatewayPagination {\n limit: number;\n hasMore: boolean;\n /**\n * Opaque cursor for the NEXT page; pass back as the `cursor` query param.\n * Null when there are no further pages.\n */\n nextCursor: string | null;\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(\"cursor\", 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 // The next-page cursor lives in the envelope's `pagination.nextCursor`\n // (a sibling of `data`), so read the full envelope rather than going\n // through `unwrapEnvelope`, which returns only `data`. Fall back to a\n // legacy `data.cursor` for older gateways that nested it there.\n const envelope = (await res.json()) as GatewayEnvelope<{\n files: GatewayFileRecord[];\n cursor?: string | null;\n }>;\n const { pagination } = envelope;\n const nextCursor =\n pagination?.hasMore === false\n ? null\n : (pagination?.nextCursor ?? envelope.data.cursor ?? null);\n return {\n files: envelope.data.files.map(normalizeFileRecord),\n cursor: nextCursor,\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"]}
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
export interface GatewayEnvelope<T> {
|
|
2
2
|
data: T;
|
|
3
3
|
proof: GatewayProof;
|
|
4
|
+
/**
|
|
5
|
+
* Cursor-based pagination metadata, present on list endpoints (e.g.
|
|
6
|
+
* `GET /v1/files`). A sibling of `data`, not nested inside it — so callers
|
|
7
|
+
* that need it must read the full envelope rather than going through
|
|
8
|
+
* `unwrapEnvelope`, which intentionally returns only `data`.
|
|
9
|
+
*/
|
|
10
|
+
pagination?: GatewayPagination;
|
|
11
|
+
}
|
|
12
|
+
export interface GatewayPagination {
|
|
13
|
+
limit: number;
|
|
14
|
+
hasMore: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Opaque cursor for the NEXT page; pass back as the `cursor` query param.
|
|
17
|
+
* Null when there are no further pages.
|
|
18
|
+
*/
|
|
19
|
+
nextCursor: string | null;
|
|
4
20
|
}
|
|
5
21
|
export interface GatewayProof {
|
|
6
22
|
signature: string;
|
|
@@ -64,11 +80,24 @@ export interface FileRecord {
|
|
|
64
80
|
url: string;
|
|
65
81
|
schemaId: string;
|
|
66
82
|
createdAt: string;
|
|
83
|
+
/**
|
|
84
|
+
* Soft-deletion timestamp (ISO 8601), or null if the file is active. Always present
|
|
85
|
+
* (`normalizeFileRecord` populates it); non-null only when the gateway returns deletion state
|
|
86
|
+
* (e.g. listed with `includeDeleted`). Drives the PS sync delete-reconciliation.
|
|
87
|
+
*/
|
|
88
|
+
deletedAt: string | null;
|
|
67
89
|
}
|
|
68
90
|
export interface FileListResult {
|
|
69
91
|
files: FileRecord[];
|
|
70
92
|
cursor: string | null;
|
|
71
93
|
}
|
|
94
|
+
export interface ListFilesOptions {
|
|
95
|
+
/**
|
|
96
|
+
* Include soft-deleted files in the result (each carries a non-null `deletedAt`). Default false.
|
|
97
|
+
* Used by the PS sync download worker to reconcile deletions of files it already holds locally.
|
|
98
|
+
*/
|
|
99
|
+
includeDeleted?: boolean;
|
|
100
|
+
}
|
|
72
101
|
export interface RegisterFileParams {
|
|
73
102
|
ownerAddress: string;
|
|
74
103
|
url: string;
|
|
@@ -112,7 +141,7 @@ export interface GatewayClient {
|
|
|
112
141
|
getSchemaForScope(scope: string): Promise<Schema | null>;
|
|
113
142
|
getServer(address: string): Promise<ServerInfo | null>;
|
|
114
143
|
getFile(fileId: string): Promise<FileRecord | null>;
|
|
115
|
-
listFilesSince(owner: string, cursor: string | null): Promise<FileListResult>;
|
|
144
|
+
listFilesSince(owner: string, cursor: string | null, options?: ListFilesOptions): Promise<FileListResult>;
|
|
116
145
|
getSchema(schemaId: string): Promise<Schema | null>;
|
|
117
146
|
registerServer(params: RegisterServerParams): Promise<RegisterServerResult>;
|
|
118
147
|
registerFile(params: RegisterFileParams): Promise<{
|
package/dist/protocol/gateway.js
CHANGED
|
@@ -10,7 +10,8 @@ function createGatewayClient(baseUrl) {
|
|
|
10
10
|
owner: record.owner ?? record.ownerAddress ?? "",
|
|
11
11
|
url: record.url,
|
|
12
12
|
schemaId: record.schemaId,
|
|
13
|
-
createdAt: record.createdAt ?? record.addedAt ?? ""
|
|
13
|
+
createdAt: record.createdAt ?? record.addedAt ?? "",
|
|
14
|
+
deletedAt: record.deletedAt ?? null
|
|
14
15
|
};
|
|
15
16
|
}
|
|
16
17
|
function getMutationId(body, key) {
|
|
@@ -70,19 +71,24 @@ function createGatewayClient(baseUrl) {
|
|
|
70
71
|
}
|
|
71
72
|
return normalizeFileRecord(await unwrapEnvelope(res));
|
|
72
73
|
},
|
|
73
|
-
async listFilesSince(owner, cursor) {
|
|
74
|
+
async listFilesSince(owner, cursor, options) {
|
|
74
75
|
const params = new URLSearchParams({ user: owner });
|
|
75
76
|
if (cursor !== null) {
|
|
76
|
-
params.set("
|
|
77
|
+
params.set("cursor", cursor);
|
|
78
|
+
}
|
|
79
|
+
if (options?.includeDeleted) {
|
|
80
|
+
params.set("includeDeleted", "true");
|
|
77
81
|
}
|
|
78
82
|
const res = await fetch(`${base}/v1/files?${params.toString()}`);
|
|
79
83
|
if (!res.ok) {
|
|
80
84
|
throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
|
|
81
85
|
}
|
|
82
|
-
const
|
|
86
|
+
const envelope = await res.json();
|
|
87
|
+
const { pagination } = envelope;
|
|
88
|
+
const nextCursor = pagination?.hasMore === false ? null : pagination?.nextCursor ?? envelope.data.cursor ?? null;
|
|
83
89
|
return {
|
|
84
|
-
files: data.files.map(normalizeFileRecord),
|
|
85
|
-
cursor:
|
|
90
|
+
files: envelope.data.files.map(normalizeFileRecord),
|
|
91
|
+
cursor: nextCursor
|
|
86
92
|
};
|
|
87
93
|
},
|
|
88
94
|
async getSchema(schemaId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"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\nexport interface FileListResult {\n files: FileRecord[];\n cursor: string | null;\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}\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(owner: string, cursor: string | null): 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 };\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 ): Promise<FileListResult> {\n const params = new URLSearchParams({ user: owner });\n if (cursor !== null) {\n params.set(\"since\", cursor);\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"]}
|
|
1
|
+
{"version":3,"sources":["../../src/protocol/gateway.ts"],"sourcesContent":["export interface GatewayEnvelope<T> {\n data: T;\n proof: GatewayProof;\n /**\n * Cursor-based pagination metadata, present on list endpoints (e.g.\n * `GET /v1/files`). A sibling of `data`, not nested inside it — so callers\n * that need it must read the full envelope rather than going through\n * `unwrapEnvelope`, which intentionally returns only `data`.\n */\n pagination?: GatewayPagination;\n}\n\nexport interface GatewayPagination {\n limit: number;\n hasMore: boolean;\n /**\n * Opaque cursor for the NEXT page; pass back as the `cursor` query param.\n * Null when there are no further pages.\n */\n nextCursor: string | null;\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(\"cursor\", 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 // The next-page cursor lives in the envelope's `pagination.nextCursor`\n // (a sibling of `data`), so read the full envelope rather than going\n // through `unwrapEnvelope`, which returns only `data`. Fall back to a\n // legacy `data.cursor` for older gateways that nested it there.\n const envelope = (await res.json()) as GatewayEnvelope<{\n files: GatewayFileRecord[];\n cursor?: string | null;\n }>;\n const { pagination } = envelope;\n const nextCursor =\n pagination?.hasMore === false\n ? null\n : (pagination?.nextCursor ?? envelope.data.cursor ?? null);\n return {\n files: envelope.data.files.map(normalizeFileRecord),\n cursor: nextCursor,\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"]}
|