|
20 | 20 | PartialFailureError, |
21 | 21 | ) |
22 | 22 | from bubble_data_api_client.transport import Transport |
23 | | -from bubble_data_api_client.types import BubbleField, CreateOrUpdateResult, OnMultiple |
| 23 | +from bubble_data_api_client.types import ( |
| 24 | + BubbleField, |
| 25 | + BulkCreateItemResult, |
| 26 | + CreateOrUpdateResult, |
| 27 | + OnMultiple, |
| 28 | +) |
24 | 29 |
|
25 | 30 |
|
26 | 31 | # https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/data-api-requests#sorting |
@@ -48,7 +53,7 @@ class RawClient: |
48 | 53 | These handle response parsing and return typed values. Use these when you |
49 | 54 | don't need raw HTTP access. |
50 | 55 |
|
51 | | - count, exists, create_or_update |
| 56 | + count, exists, create_or_update, bulk_create_parsed |
52 | 57 |
|
53 | 58 | For ORM-style access with model classes, use BubbleModel instead. |
54 | 59 |
|
@@ -89,13 +94,36 @@ async def create(self, typename: str, data: typing.Any) -> httpx.Response: |
89 | 94 | async def bulk_create(self, typename: str, data: list[typing.Any]) -> httpx.Response: |
90 | 95 | """Create multiple things in a single request using newline-delimited JSON. |
91 | 96 |
|
92 | | - Response is text/plain with one JSON object per line: {"status":"success","id":"..."} |
| 97 | + Response is text/plain with one JSON object per line, in the same order as input: |
| 98 | + Success: {"status":"success","id":"1234x5678"} |
| 99 | + Error: {"status":"error","message":"Could not parse as JSON: ..."} |
| 100 | +
|
| 101 | + Partial failures are possible where some items succeed and others fail. |
93 | 102 | """ |
94 | 103 | return await self._transport.post_text( |
95 | 104 | url=f"/{typename}/bulk", |
96 | 105 | content="\n".join(json.dumps(item) for item in data), |
97 | 106 | ) |
98 | 107 |
|
| 108 | + async def bulk_create_parsed(self, typename: str, data: list[typing.Any]) -> list[BulkCreateItemResult]: |
| 109 | + """Create multiple things and return parsed results for each item. |
| 110 | +
|
| 111 | + Returns a list of results in the same order as input data. Each result |
| 112 | + contains status, id (on success), and message (on error). |
| 113 | + """ |
| 114 | + response = await self.bulk_create(typename=typename, data=data) |
| 115 | + results: list[BulkCreateItemResult] = [] |
| 116 | + for line in response.text.strip().split("\n"): |
| 117 | + parsed = json.loads(line) |
| 118 | + results.append( |
| 119 | + BulkCreateItemResult( |
| 120 | + status=parsed["status"], |
| 121 | + id=parsed.get("id"), |
| 122 | + message=parsed.get("message"), |
| 123 | + ) |
| 124 | + ) |
| 125 | + return results |
| 126 | + |
99 | 127 | async def delete(self, typename: str, uid: str) -> httpx.Response: |
100 | 128 | """Delete a thing by its unique ID.""" |
101 | 129 | return await self._transport.delete(f"/{typename}/{uid}") |
|
0 commit comments