@archiva/archiva-nextjs 0.2.7 → 0.2.81

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.
@@ -0,0 +1,275 @@
1
+ // src/types.ts
2
+ var ArchivaError = class extends Error {
3
+ constructor(params) {
4
+ super(params.message);
5
+ this.statusCode = params.statusCode;
6
+ this.code = params.code;
7
+ this.retryAfterSeconds = params.retryAfterSeconds;
8
+ this.details = params.details;
9
+ }
10
+ };
11
+
12
+ // src/client.ts
13
+ var DEFAULT_BASE_URL = "https://api.archiva.app";
14
+ function buildHeaders(apiKey, overrides) {
15
+ const headers = new Headers(overrides);
16
+ headers.set("X-Project-Key", apiKey);
17
+ return headers;
18
+ }
19
+ async function parseError(response) {
20
+ const retryAfterHeader = response.headers.get("Retry-After");
21
+ const retryAfterSeconds = retryAfterHeader ? Number(retryAfterHeader) : void 0;
22
+ let payload = void 0;
23
+ try {
24
+ payload = await response.json();
25
+ } catch {
26
+ payload = void 0;
27
+ }
28
+ const errorMessage = typeof payload === "object" && payload !== null && "error" in payload ? String(payload.error) : response.statusText;
29
+ let code = "HTTP_ERROR";
30
+ if (response.status === 401) {
31
+ code = "UNAUTHORIZED";
32
+ } else if (response.status === 403) {
33
+ code = "FORBIDDEN";
34
+ } else if (response.status === 413) {
35
+ code = "PAYLOAD_TOO_LARGE";
36
+ } else if (response.status === 429) {
37
+ code = "RATE_LIMITED";
38
+ } else if (response.status === 409) {
39
+ code = "IDEMPOTENCY_CONFLICT";
40
+ }
41
+ throw new ArchivaError({
42
+ statusCode: response.status,
43
+ code,
44
+ message: errorMessage,
45
+ retryAfterSeconds,
46
+ details: payload
47
+ });
48
+ }
49
+ function createRequestId() {
50
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
51
+ return crypto.randomUUID();
52
+ }
53
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
54
+ }
55
+ function createIdempotencyKey() {
56
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
57
+ return `idem_${crypto.randomUUID()}`;
58
+ }
59
+ return `idem_${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
60
+ }
61
+ async function loadEvents(apiKey, params, baseUrl = DEFAULT_BASE_URL) {
62
+ const url = new URL(`${baseUrl}/api/events`);
63
+ if (params.entityId) {
64
+ url.searchParams.set("entityId", params.entityId);
65
+ }
66
+ if (params.actorId) {
67
+ url.searchParams.set("actorId", params.actorId);
68
+ }
69
+ if (params.entityType) {
70
+ url.searchParams.set("entityType", params.entityType);
71
+ }
72
+ if (params.actorType) {
73
+ url.searchParams.set("actorType", params.actorType);
74
+ }
75
+ if (params.limit) {
76
+ url.searchParams.set("limit", String(params.limit));
77
+ }
78
+ if (params.cursor) {
79
+ url.searchParams.set("cursor", params.cursor);
80
+ }
81
+ const response = await fetch(url.toString(), {
82
+ headers: buildHeaders(apiKey)
83
+ });
84
+ if (!response.ok) {
85
+ await parseError(response);
86
+ }
87
+ const payload = await response.json();
88
+ if (!payload || typeof payload !== "object" || !Array.isArray(payload.items)) {
89
+ throw new ArchivaError({
90
+ statusCode: response.status,
91
+ code: "HTTP_ERROR",
92
+ message: "Invalid response format",
93
+ details: payload
94
+ });
95
+ }
96
+ const items = payload.items.map((item) => {
97
+ if (typeof item !== "object" || item === null) {
98
+ throw new ArchivaError({
99
+ statusCode: response.status,
100
+ code: "HTTP_ERROR",
101
+ message: "Invalid item format in response",
102
+ details: item
103
+ });
104
+ }
105
+ const event = item;
106
+ return {
107
+ id: String(event.id ?? ""),
108
+ receivedAt: String(event.receivedAt ?? ""),
109
+ action: String(event.action ?? ""),
110
+ entityType: String(event.entityType ?? ""),
111
+ entityId: String(event.entityId ?? ""),
112
+ actorId: event.actorId !== null && event.actorId !== void 0 ? String(event.actorId) : null,
113
+ actorType: event.actorType && (event.actorType === "user" || event.actorType === "service" || event.actorType === "system") ? event.actorType : void 0,
114
+ actorDisplay: event.actorDisplay !== null && event.actorDisplay !== void 0 ? String(event.actorDisplay) : void 0,
115
+ source: event.source !== null && event.source !== void 0 ? String(event.source) : null
116
+ };
117
+ });
118
+ return {
119
+ items,
120
+ nextCursor: typeof payload.nextCursor === "string" ? payload.nextCursor : void 0
121
+ };
122
+ }
123
+ async function createEvent(apiKey, event, options, baseUrl = DEFAULT_BASE_URL) {
124
+ const idempotencyKey = options?.idempotencyKey ?? createIdempotencyKey();
125
+ const requestId = options?.requestId ?? createRequestId();
126
+ const headers = buildHeaders(apiKey, {
127
+ "Content-Type": "application/json",
128
+ "Idempotency-Key": idempotencyKey,
129
+ "X-Request-Id": requestId
130
+ });
131
+ const response = await fetch(`${baseUrl}/api/ingest/event`, {
132
+ method: "POST",
133
+ headers,
134
+ body: JSON.stringify(event)
135
+ });
136
+ if (!response.ok) {
137
+ await parseError(response);
138
+ }
139
+ const payload = await response.json();
140
+ if (!payload || typeof payload !== "object" || typeof payload.eventId !== "string") {
141
+ throw new ArchivaError({
142
+ statusCode: response.status,
143
+ code: "HTTP_ERROR",
144
+ message: "Invalid response format",
145
+ details: payload
146
+ });
147
+ }
148
+ return {
149
+ eventId: payload.eventId,
150
+ replayed: response.status === 200
151
+ };
152
+ }
153
+ async function createEvents(apiKey, events, options, baseUrl = DEFAULT_BASE_URL) {
154
+ const results = await Promise.all(
155
+ events.map(
156
+ (event, index) => createEvent(
157
+ apiKey,
158
+ event,
159
+ {
160
+ ...options,
161
+ idempotencyKey: options?.idempotencyKey ? `${options.idempotencyKey}_${index}` : void 0
162
+ },
163
+ baseUrl
164
+ )
165
+ )
166
+ );
167
+ return {
168
+ eventIds: results.map((r) => r.eventId)
169
+ };
170
+ }
171
+
172
+ // src/actions.ts
173
+ var DEFAULT_BASE_URL2 = "https://api.archiva.app";
174
+ function getApiKey(apiKey) {
175
+ const resolvedKey = apiKey || process.env.ARCHIVA_SECRET_KEY;
176
+ if (!resolvedKey) {
177
+ throw new Error("ARCHIVA_SECRET_KEY environment variable is required, or provide apiKey prop to ArchivaProvider");
178
+ }
179
+ return resolvedKey;
180
+ }
181
+ async function loadEvents2(params, apiKey) {
182
+ const resolvedApiKey = getApiKey(apiKey);
183
+ return loadEvents(resolvedApiKey, params, DEFAULT_BASE_URL2);
184
+ }
185
+ async function createEvent2(event, options, apiKey) {
186
+ const resolvedApiKey = getApiKey(apiKey);
187
+ return createEvent(resolvedApiKey, event, options, DEFAULT_BASE_URL2);
188
+ }
189
+ async function createEvents2(events, options, apiKey) {
190
+ const resolvedApiKey = getApiKey(apiKey);
191
+ return createEvents(resolvedApiKey, events, options, DEFAULT_BASE_URL2);
192
+ }
193
+
194
+ // src/server/frontendTokens.ts
195
+ import "server-only";
196
+ var DEFAULT_API_BASE_URL = "https://api.archiva.app";
197
+ async function createFrontendTokenGET(projectId, apiBaseUrl = DEFAULT_API_BASE_URL) {
198
+ const secretKey = process.env.ARCHIVA_SECRET_KEY;
199
+ if (!secretKey || secretKey.trim().length === 0) {
200
+ const exists = process.env.ARCHIVA_SECRET_KEY !== void 0;
201
+ throw new Error(
202
+ `ARCHIVA_SECRET_KEY environment variable is ${exists ? "empty" : "not configured"}. Please set it in your .env.local file (or .env) with a valid value and restart your Next.js dev server. The variable must be in the project root directory and must not be empty.`
203
+ );
204
+ }
205
+ const keyPrefix = secretKey.substring(0, 10);
206
+ console.log("[Archiva] Using API key prefix:", keyPrefix + "...", "Length:", secretKey.length);
207
+ const url = new URL(`${apiBaseUrl}/api/v1/frontend-tokens`);
208
+ const response = await fetch(url.toString(), {
209
+ method: "POST",
210
+ headers: {
211
+ "Content-Type": "application/json",
212
+ "Authorization": `Bearer ${secretKey}`
213
+ },
214
+ body: JSON.stringify({
215
+ scopes: ["timeline:read"],
216
+ ...projectId && { projectId }
217
+ })
218
+ });
219
+ if (!response.ok) {
220
+ const error = await response.json().catch(() => ({ error: response.statusText }));
221
+ const errorMessage = error.error || `Failed to fetch frontend token: ${response.status}`;
222
+ if (errorMessage.includes("ARCHIVA_SECRET_KEY") || response.status === 401 || response.status === 403) {
223
+ throw new Error(
224
+ `Archiva API authentication failed. Check that your ARCHIVA_SECRET_KEY is valid and has the correct permissions. API error: ${errorMessage}`
225
+ );
226
+ }
227
+ throw new Error(errorMessage);
228
+ }
229
+ const data = await response.json();
230
+ if (!data.token || typeof data.expiresAt !== "number") {
231
+ throw new Error("Invalid token response format");
232
+ }
233
+ return {
234
+ token: data.token,
235
+ expiresAt: data.expiresAt
236
+ };
237
+ }
238
+
239
+ // src/server/handlers/createFrontendTokenRoute.ts
240
+ import "server-only";
241
+ import { NextResponse } from "next/server";
242
+ var DEFAULT_API_BASE_URL2 = "https://api.archiva.app";
243
+ function createFrontendTokenRoute(options) {
244
+ return async function GET2(request) {
245
+ try {
246
+ const searchParams = request.nextUrl.searchParams;
247
+ const projectId = searchParams.get("projectId") || void 0;
248
+ const apiBaseUrl = options?.apiBaseUrl || DEFAULT_API_BASE_URL2;
249
+ const tokenResponse = await createFrontendTokenGET(projectId, apiBaseUrl);
250
+ return NextResponse.json(tokenResponse);
251
+ } catch (error) {
252
+ console.error("Error fetching frontend token:", error);
253
+ const message = error instanceof Error ? error.message : "Internal server error";
254
+ const statusCode = message.includes("ARCHIVA_SECRET_KEY") ? 500 : 500;
255
+ return NextResponse.json(
256
+ { error: message },
257
+ { status: statusCode }
258
+ );
259
+ }
260
+ };
261
+ }
262
+ async function GET(request) {
263
+ const handler = createFrontendTokenRoute();
264
+ return handler(request);
265
+ }
266
+
267
+ export {
268
+ ArchivaError,
269
+ loadEvents2 as loadEvents,
270
+ createEvent2 as createEvent,
271
+ createEvents2 as createEvents,
272
+ createFrontendTokenGET,
273
+ createFrontendTokenRoute,
274
+ GET
275
+ };
package/dist/index.js CHANGED
@@ -299,6 +299,9 @@ async function loadEvents(apiKey, params, baseUrl = DEFAULT_BASE_URL) {
299
299
  if (params.entityType) {
300
300
  url.searchParams.set("entityType", params.entityType);
301
301
  }
302
+ if (params.actorType) {
303
+ url.searchParams.set("actorType", params.actorType);
304
+ }
302
305
  if (params.limit) {
303
306
  url.searchParams.set("limit", String(params.limit));
304
307
  }
@@ -320,8 +323,30 @@ async function loadEvents(apiKey, params, baseUrl = DEFAULT_BASE_URL) {
320
323
  details: payload
321
324
  });
322
325
  }
326
+ const items = payload.items.map((item) => {
327
+ if (typeof item !== "object" || item === null) {
328
+ throw new ArchivaError({
329
+ statusCode: response.status,
330
+ code: "HTTP_ERROR",
331
+ message: "Invalid item format in response",
332
+ details: item
333
+ });
334
+ }
335
+ const event = item;
336
+ return {
337
+ id: String(event.id ?? ""),
338
+ receivedAt: String(event.receivedAt ?? ""),
339
+ action: String(event.action ?? ""),
340
+ entityType: String(event.entityType ?? ""),
341
+ entityId: String(event.entityId ?? ""),
342
+ actorId: event.actorId !== null && event.actorId !== void 0 ? String(event.actorId) : null,
343
+ actorType: event.actorType && (event.actorType === "user" || event.actorType === "service" || event.actorType === "system") ? event.actorType : void 0,
344
+ actorDisplay: event.actorDisplay !== null && event.actorDisplay !== void 0 ? String(event.actorDisplay) : void 0,
345
+ source: event.source !== null && event.source !== void 0 ? String(event.source) : null
346
+ };
347
+ });
323
348
  return {
324
- items: payload.items,
349
+ items,
325
350
  nextCursor: typeof payload.nextCursor === "string" ? payload.nextCursor : void 0
326
351
  };
327
352
  }
package/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  createFrontendTokenGET,
10
10
  createFrontendTokenRoute,
11
11
  loadEvents
12
- } from "./chunk-WW7LXHTM.mjs";
12
+ } from "./chunk-SQG3CD5M.mjs";
13
13
  export {
14
14
  ArchivaError,
15
15
  ArchivaProvider,
@@ -118,34 +118,13 @@ var CloudCogIcon = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime2.js
118
118
  }
119
119
  );
120
120
  function eventToTimelineItem(event, getActorAvatar) {
121
- const actorId = event.actorId;
122
- const actorType = event.actorType || "user";
123
- let actorIdPart = actorId || "";
124
- if (actorId && actorId.includes(":")) {
125
- const [, ...rest] = actorId.split(":");
126
- actorIdPart = rest.join(":") || actorId;
127
- }
128
- let actorDisplay = event.actorDisplay || null;
129
- if (!actorDisplay && actorId) {
130
- if (actorId.includes(":")) {
131
- const [type, ...rest] = actorId.split(":");
132
- const idPart = rest.join(":");
133
- if (type === "service" || type === "system") {
134
- actorDisplay = `${type.charAt(0).toUpperCase() + type.slice(1)} ${idPart.charAt(0).toUpperCase() + idPart.slice(1)}`;
135
- } else {
136
- actorDisplay = idPart.charAt(0).toUpperCase() + idPart.slice(1);
137
- }
138
- } else {
139
- actorDisplay = actorId.charAt(0).toUpperCase() + actorId.slice(1);
140
- }
141
- }
142
- if (!actorDisplay) {
143
- actorDisplay = "Unknown Actor";
144
- }
145
- const userName = actorDisplay;
146
- const userHandle = actorIdPart || "unknown";
147
- const initials = userHandle.charAt(0).toUpperCase();
148
- const actorAvatarOrIcon = actorId && getActorAvatar ? getActorAvatar(actorId) : void 0;
121
+ const action = event.action.charAt(0).toUpperCase() + event.action.slice(1);
122
+ const description = action;
123
+ const actorId = event.actorId || "unknown";
124
+ const userName = actorId.includes(":") ? actorId.split(":")[1] || actorId : actorId;
125
+ const userHandle = userName;
126
+ const initials = userName.charAt(0).toUpperCase();
127
+ const actorAvatarOrIcon = getActorAvatar ? getActorAvatar(actorId) : void 0;
149
128
  let actorAvatar = void 0;
150
129
  let actorIcon = void 0;
151
130
  if (typeof actorAvatarOrIcon === "string") {
@@ -153,7 +132,8 @@ function eventToTimelineItem(event, getActorAvatar) {
153
132
  } else if (actorAvatarOrIcon) {
154
133
  actorIcon = actorAvatarOrIcon;
155
134
  }
156
- if (!actorAvatar && !actorIcon && actorId) {
135
+ const actorType = event.actorType ?? "user";
136
+ if (!actorAvatar && !actorIcon) {
157
137
  if (actorType === "user") {
158
138
  actorAvatar = "https://www.gravatar.com/avatar?d=mp";
159
139
  } else if (actorType === "system") {
@@ -162,21 +142,30 @@ function eventToTimelineItem(event, getActorAvatar) {
162
142
  actorIcon = CloudCogIcon;
163
143
  }
164
144
  }
165
- const action = event.action.charAt(0).toUpperCase() + event.action.slice(1);
166
145
  return {
167
146
  id: event.id,
168
147
  title: "",
169
- // Not used in activity layout
170
- description: action,
171
- timestamp: event.receivedAt,
172
- userName,
148
+ // Required by TimelineItem type, but not used in activity layout - matches ActivityLog.tsx line 352
149
+ userName: userName.charAt(0).toUpperCase() + userName.slice(1),
150
+ // Matches ActivityLog.tsx line 353
151
+ actorDisplay: event.actorDisplay ?? void 0,
152
+ // Matches ActivityLog.tsx line 354
173
153
  userHandle,
174
- actorDisplay,
154
+ // Matches ActivityLog.tsx line 355
155
+ description,
156
+ // Matches ActivityLog.tsx line 356
175
157
  entityType: event.entityType.toLowerCase(),
158
+ // Matches ActivityLog.tsx line 357
159
+ timestamp: new Date(event.receivedAt),
160
+ // Matches ActivityLog.tsx line 358 - ensure it's a Date object
176
161
  avatar: actorAvatar,
162
+ // Matches ActivityLog.tsx line 359
177
163
  icon: actorIcon,
164
+ // Matches ActivityLog.tsx line 360
178
165
  avatarFallback: initials,
166
+ // Matches ActivityLog.tsx line 361
179
167
  statusIndicator: false,
168
+ // Can be set to true for recent items - matches ActivityLog.tsx line 362
180
169
  data: event
181
170
  };
182
171
  }
@@ -221,8 +210,25 @@ async function fetchEventsWithRetry(apiBaseUrl, getToken, forceRefreshToken, par
221
210
  if (!payload || typeof payload !== "object" || !Array.isArray(payload.items)) {
222
211
  throw new Error("Invalid response format");
223
212
  }
213
+ const items = payload.items.map((item) => {
214
+ if (typeof item !== "object" || item === null) {
215
+ throw new Error("Invalid item format in response");
216
+ }
217
+ const event = item;
218
+ return {
219
+ id: String(event.id ?? ""),
220
+ receivedAt: String(event.receivedAt ?? ""),
221
+ action: String(event.action ?? ""),
222
+ entityType: String(event.entityType ?? ""),
223
+ entityId: String(event.entityId ?? ""),
224
+ actorId: event.actorId !== null && event.actorId !== void 0 ? String(event.actorId) : null,
225
+ actorType: event.actorType && (event.actorType === "user" || event.actorType === "service" || event.actorType === "system") ? event.actorType : void 0,
226
+ actorDisplay: event.actorDisplay !== null && event.actorDisplay !== void 0 ? String(event.actorDisplay) : void 0,
227
+ source: event.source !== null && event.source !== void 0 ? String(event.source) : null
228
+ };
229
+ });
224
230
  return {
225
- items: payload.items,
231
+ items,
226
232
  nextCursor: typeof payload.nextCursor === "string" ? payload.nextCursor : void 0
227
233
  };
228
234
  }
@@ -73,34 +73,13 @@ var CloudCogIcon = ({ className }) => /* @__PURE__ */ jsxs(
73
73
  }
74
74
  );
75
75
  function eventToTimelineItem(event, getActorAvatar) {
76
- const actorId = event.actorId;
77
- const actorType = event.actorType || "user";
78
- let actorIdPart = actorId || "";
79
- if (actorId && actorId.includes(":")) {
80
- const [, ...rest] = actorId.split(":");
81
- actorIdPart = rest.join(":") || actorId;
82
- }
83
- let actorDisplay = event.actorDisplay || null;
84
- if (!actorDisplay && actorId) {
85
- if (actorId.includes(":")) {
86
- const [type, ...rest] = actorId.split(":");
87
- const idPart = rest.join(":");
88
- if (type === "service" || type === "system") {
89
- actorDisplay = `${type.charAt(0).toUpperCase() + type.slice(1)} ${idPart.charAt(0).toUpperCase() + idPart.slice(1)}`;
90
- } else {
91
- actorDisplay = idPart.charAt(0).toUpperCase() + idPart.slice(1);
92
- }
93
- } else {
94
- actorDisplay = actorId.charAt(0).toUpperCase() + actorId.slice(1);
95
- }
96
- }
97
- if (!actorDisplay) {
98
- actorDisplay = "Unknown Actor";
99
- }
100
- const userName = actorDisplay;
101
- const userHandle = actorIdPart || "unknown";
102
- const initials = userHandle.charAt(0).toUpperCase();
103
- const actorAvatarOrIcon = actorId && getActorAvatar ? getActorAvatar(actorId) : void 0;
76
+ const action = event.action.charAt(0).toUpperCase() + event.action.slice(1);
77
+ const description = action;
78
+ const actorId = event.actorId || "unknown";
79
+ const userName = actorId.includes(":") ? actorId.split(":")[1] || actorId : actorId;
80
+ const userHandle = userName;
81
+ const initials = userName.charAt(0).toUpperCase();
82
+ const actorAvatarOrIcon = getActorAvatar ? getActorAvatar(actorId) : void 0;
104
83
  let actorAvatar = void 0;
105
84
  let actorIcon = void 0;
106
85
  if (typeof actorAvatarOrIcon === "string") {
@@ -108,7 +87,8 @@ function eventToTimelineItem(event, getActorAvatar) {
108
87
  } else if (actorAvatarOrIcon) {
109
88
  actorIcon = actorAvatarOrIcon;
110
89
  }
111
- if (!actorAvatar && !actorIcon && actorId) {
90
+ const actorType = event.actorType ?? "user";
91
+ if (!actorAvatar && !actorIcon) {
112
92
  if (actorType === "user") {
113
93
  actorAvatar = "https://www.gravatar.com/avatar?d=mp";
114
94
  } else if (actorType === "system") {
@@ -117,21 +97,30 @@ function eventToTimelineItem(event, getActorAvatar) {
117
97
  actorIcon = CloudCogIcon;
118
98
  }
119
99
  }
120
- const action = event.action.charAt(0).toUpperCase() + event.action.slice(1);
121
100
  return {
122
101
  id: event.id,
123
102
  title: "",
124
- // Not used in activity layout
125
- description: action,
126
- timestamp: event.receivedAt,
127
- userName,
103
+ // Required by TimelineItem type, but not used in activity layout - matches ActivityLog.tsx line 352
104
+ userName: userName.charAt(0).toUpperCase() + userName.slice(1),
105
+ // Matches ActivityLog.tsx line 353
106
+ actorDisplay: event.actorDisplay ?? void 0,
107
+ // Matches ActivityLog.tsx line 354
128
108
  userHandle,
129
- actorDisplay,
109
+ // Matches ActivityLog.tsx line 355
110
+ description,
111
+ // Matches ActivityLog.tsx line 356
130
112
  entityType: event.entityType.toLowerCase(),
113
+ // Matches ActivityLog.tsx line 357
114
+ timestamp: new Date(event.receivedAt),
115
+ // Matches ActivityLog.tsx line 358 - ensure it's a Date object
131
116
  avatar: actorAvatar,
117
+ // Matches ActivityLog.tsx line 359
132
118
  icon: actorIcon,
119
+ // Matches ActivityLog.tsx line 360
133
120
  avatarFallback: initials,
121
+ // Matches ActivityLog.tsx line 361
134
122
  statusIndicator: false,
123
+ // Can be set to true for recent items - matches ActivityLog.tsx line 362
135
124
  data: event
136
125
  };
137
126
  }
@@ -176,8 +165,25 @@ async function fetchEventsWithRetry(apiBaseUrl, getToken, forceRefreshToken, par
176
165
  if (!payload || typeof payload !== "object" || !Array.isArray(payload.items)) {
177
166
  throw new Error("Invalid response format");
178
167
  }
168
+ const items = payload.items.map((item) => {
169
+ if (typeof item !== "object" || item === null) {
170
+ throw new Error("Invalid item format in response");
171
+ }
172
+ const event = item;
173
+ return {
174
+ id: String(event.id ?? ""),
175
+ receivedAt: String(event.receivedAt ?? ""),
176
+ action: String(event.action ?? ""),
177
+ entityType: String(event.entityType ?? ""),
178
+ entityId: String(event.entityId ?? ""),
179
+ actorId: event.actorId !== null && event.actorId !== void 0 ? String(event.actorId) : null,
180
+ actorType: event.actorType && (event.actorType === "user" || event.actorType === "service" || event.actorType === "system") ? event.actorType : void 0,
181
+ actorDisplay: event.actorDisplay !== null && event.actorDisplay !== void 0 ? String(event.actorDisplay) : void 0,
182
+ source: event.source !== null && event.source !== void 0 ? String(event.source) : null
183
+ };
184
+ });
179
185
  return {
180
- items: payload.items,
186
+ items,
181
187
  nextCursor: typeof payload.nextCursor === "string" ? payload.nextCursor : void 0
182
188
  };
183
189
  }
@@ -173,6 +173,9 @@ async function loadEvents(apiKey, params, baseUrl = DEFAULT_BASE_URL) {
173
173
  if (params.entityType) {
174
174
  url.searchParams.set("entityType", params.entityType);
175
175
  }
176
+ if (params.actorType) {
177
+ url.searchParams.set("actorType", params.actorType);
178
+ }
176
179
  if (params.limit) {
177
180
  url.searchParams.set("limit", String(params.limit));
178
181
  }
@@ -194,8 +197,30 @@ async function loadEvents(apiKey, params, baseUrl = DEFAULT_BASE_URL) {
194
197
  details: payload
195
198
  });
196
199
  }
200
+ const items = payload.items.map((item) => {
201
+ if (typeof item !== "object" || item === null) {
202
+ throw new ArchivaError({
203
+ statusCode: response.status,
204
+ code: "HTTP_ERROR",
205
+ message: "Invalid item format in response",
206
+ details: item
207
+ });
208
+ }
209
+ const event = item;
210
+ return {
211
+ id: String(event.id ?? ""),
212
+ receivedAt: String(event.receivedAt ?? ""),
213
+ action: String(event.action ?? ""),
214
+ entityType: String(event.entityType ?? ""),
215
+ entityId: String(event.entityId ?? ""),
216
+ actorId: event.actorId !== null && event.actorId !== void 0 ? String(event.actorId) : null,
217
+ actorType: event.actorType && (event.actorType === "user" || event.actorType === "service" || event.actorType === "system") ? event.actorType : void 0,
218
+ actorDisplay: event.actorDisplay !== null && event.actorDisplay !== void 0 ? String(event.actorDisplay) : void 0,
219
+ source: event.source !== null && event.source !== void 0 ? String(event.source) : null
220
+ };
221
+ });
197
222
  return {
198
- items: payload.items,
223
+ items,
199
224
  nextCursor: typeof payload.nextCursor === "string" ? payload.nextCursor : void 0
200
225
  };
201
226
  }
@@ -5,7 +5,7 @@ import {
5
5
  createFrontendTokenGET,
6
6
  createFrontendTokenRoute,
7
7
  loadEvents
8
- } from "../chunk-WW7LXHTM.mjs";
8
+ } from "../chunk-SQG3CD5M.mjs";
9
9
  export {
10
10
  GET,
11
11
  createEvent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archiva/archiva-nextjs",
3
- "version": "0.2.07",
3
+ "version": "0.2.081",
4
4
  "description": "Archiva Next.js SDK - Server Actions and Timeline Component",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -30,6 +30,7 @@
30
30
  "files": ["dist"],
31
31
  "scripts": {
32
32
  "build": "tsup src/index.tsx src/react/index.ts src/react/client.ts src/server/index.ts --format esm,cjs --dts",
33
+ "dev": "tsup src/index.tsx src/react/index.ts src/react/client.ts src/server/index.ts --format esm,cjs --dts --watch",
33
34
  "test": "vitest run --config vitest.config.ts"
34
35
  },
35
36
  "peerDependencies": {