Skip to content

Commit fbc2dee

Browse files
fix(api): return list of events from insert endpoint (match aw-server-rust)
The POST /api/0/buckets/{id}/events endpoint previously returned either a single event dict or null, inconsistent with aw-server-rust which always returns a list of events with server-assigned IDs. Changes: - api.py: create_events() now returns List[Event], using insert_one for single events (to get ID) and insert_many for bulk - rest.py: Always serialize response as a list of event dicts - tests: Add test_insert_event_returns_list and test_insert_events_returns_list This enables aw-client to use response.json()[0] uniformly against both server implementations (see ActivityWatch/aw-client#103).
1 parent 153e7fd commit fbc2dee

3 files changed

Lines changed: 57 additions & 5 deletions

File tree

aw_server/api.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,19 @@ def get_events(
228228
return events
229229

230230
@check_bucket_exists
231-
def create_events(self, bucket_id: str, events: List[Event]) -> Optional[Event]:
231+
def create_events(self, bucket_id: str, events: List[Event]) -> List[Event]:
232232
"""Create events for a bucket. Can handle both single events and multiple ones.
233233
234-
Returns the inserted event when a single event was inserted, otherwise None."""
235-
return self.db[bucket_id].insert(events)
234+
Always returns a list of inserted events (matching aw-server-rust behavior).
235+
For single events, the returned event includes the server-assigned ID.
236+
For bulk inserts, events may not have IDs due to storage limitations."""
237+
if len(events) == 1:
238+
# Pass as single Event so Bucket.insert uses insert_one (returns Event with ID)
239+
inserted = self.db[bucket_id].insert(events[0])
240+
return [inserted]
241+
else:
242+
self.db[bucket_id].insert(events)
243+
return events
236244

237245
@check_bucket_exists
238246
def get_eventcount(

aw_server/rest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,8 @@ def post(self, bucket_id):
225225
else:
226226
raise BadRequest("Invalid POST data", "")
227227

228-
event = current_app.api.create_events(bucket_id, events)
229-
return event.to_json_dict() if event else None, 200
228+
events = current_app.api.create_events(bucket_id, events)
229+
return [e.to_json_dict() for e in events], 200
230230

231231

232232
@api.route("/0/buckets/<string:bucket_id>/events/count")

tests/test_server.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,48 @@ def get_events():
8888
assert len(r.json) == n_events
8989

9090

91+
def test_insert_event_returns_list(flask_client, bucket):
92+
"""Test that POST /events returns a list of events with IDs (matching aw-server-rust)."""
93+
now = datetime.now()
94+
event_data = {"timestamp": now.isoformat(), "duration": 0, "data": {"label": "test"}}
95+
96+
# Single event as list
97+
r = flask_client.post(
98+
f"/api/0/buckets/{bucket}/events",
99+
json=[event_data],
100+
)
101+
assert r.status_code == 200
102+
assert isinstance(r.json, list), f"Expected list, got {type(r.json)}"
103+
assert len(r.json) == 1
104+
assert r.json[0]["id"] is not None
105+
assert r.json[0]["data"] == {"label": "test"}
106+
107+
# Single event as dict (legacy format)
108+
r = flask_client.post(
109+
f"/api/0/buckets/{bucket}/events",
110+
json=event_data,
111+
)
112+
assert r.status_code == 200
113+
assert isinstance(r.json, list), f"Expected list, got {type(r.json)}"
114+
assert len(r.json) == 1
115+
assert r.json[0]["id"] is not None
116+
117+
118+
def test_insert_events_returns_list(flask_client, bucket):
119+
"""Test that POST /events with multiple events returns a list."""
120+
now = datetime.now()
121+
events_data = [
122+
{"timestamp": (now - timedelta(hours=i)).isoformat(), "duration": 0, "data": {"label": f"test-{i}"}}
123+
for i in range(3)
124+
]
125+
126+
r = flask_client.post(
127+
f"/api/0/buckets/{bucket}/events",
128+
json=events_data,
129+
)
130+
assert r.status_code == 200
131+
assert isinstance(r.json, list), f"Expected list, got {type(r.json)}"
132+
assert len(r.json) == 3
133+
134+
91135
# TODO: Add benchmark for basic AFK-filtering query

0 commit comments

Comments
 (0)