@archiva/archiva-nextjs 0.1.2 → 0.1.4
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/README.md +9 -4
- package/dist/chunk-ZQFVEHLS.mjs +398 -0
- package/dist/index.d.mts +24 -16
- package/dist/index.d.ts +24 -16
- package/dist/index.js +461 -35
- package/dist/index.mjs +66 -31
- package/dist/react/index.d.mts +52 -0
- package/dist/react/index.d.ts +52 -0
- package/dist/react/index.js +436 -0
- package/dist/react/index.mjs +10 -0
- package/dist/server/index.d.mts +48 -0
- package/dist/server/index.d.ts +48 -0
- package/dist/server/index.js +97 -0
- package/dist/server/index.mjs +68 -0
- package/package.json +13 -2
package/README.md
CHANGED
|
@@ -22,22 +22,25 @@ ARCHIVA_SECRET_KEY=pk_test_xxxxx
|
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
24
24
|
|
|
25
|
-
### ArchivaProvider (
|
|
25
|
+
### ArchivaProvider (Client Component)
|
|
26
26
|
|
|
27
|
-
Wrap your application (or specific routes) with the ArchivaProvider component:
|
|
27
|
+
Wrap your application (or specific routes) with the ArchivaProvider component. The provider makes the API key available to child components via React context:
|
|
28
28
|
|
|
29
29
|
```tsx
|
|
30
30
|
import { ArchivaProvider } from '@archiva/archiva-nextjs';
|
|
31
31
|
|
|
32
32
|
export default function Layout({ children }) {
|
|
33
|
+
// API key can be passed as prop, or it will use ARCHIVA_SECRET_KEY env var
|
|
33
34
|
return (
|
|
34
|
-
<ArchivaProvider>
|
|
35
|
+
<ArchivaProvider apiKey="pk_test_xxxxx">
|
|
35
36
|
{children}
|
|
36
37
|
</ArchivaProvider>
|
|
37
38
|
);
|
|
38
39
|
}
|
|
39
40
|
```
|
|
40
41
|
|
|
42
|
+
**Note:** If you don't pass an `apiKey` prop, the provider will use the `ARCHIVA_SECRET_KEY` environment variable. The Timeline component and server actions will automatically use the API key from the provider context.
|
|
43
|
+
|
|
41
44
|
### Server Actions
|
|
42
45
|
|
|
43
46
|
#### loadEvents
|
|
@@ -112,7 +115,7 @@ const result = await createEvents([
|
|
|
112
115
|
|
|
113
116
|
### Timeline Component (Client Component)
|
|
114
117
|
|
|
115
|
-
Display a timeline of audit events:
|
|
118
|
+
Display a timeline of audit events. The Timeline component automatically uses the API key from the ArchivaProvider context:
|
|
116
119
|
|
|
117
120
|
```tsx
|
|
118
121
|
'use client';
|
|
@@ -130,6 +133,8 @@ export function InvoiceTimeline({ invoiceId }: { invoiceId: string }) {
|
|
|
130
133
|
}
|
|
131
134
|
```
|
|
132
135
|
|
|
136
|
+
**Note:** The Timeline component must be used within an `ArchivaProvider`. It no longer requires an `apiKey` prop as it gets the API key from the provider context.
|
|
137
|
+
|
|
133
138
|
## API Reference
|
|
134
139
|
|
|
135
140
|
### LoadEventsParams
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
// src/react/ArchivaProvider.tsx
|
|
2
|
+
import "server-only";
|
|
3
|
+
|
|
4
|
+
// src/react/internal/ArchivaProviderClient.tsx
|
|
5
|
+
import * as React2 from "react";
|
|
6
|
+
|
|
7
|
+
// src/react/context.tsx
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
var ArchivaContext = React.createContext(void 0);
|
|
10
|
+
function useArchivaContext() {
|
|
11
|
+
const context = React.useContext(ArchivaContext);
|
|
12
|
+
if (context === void 0) {
|
|
13
|
+
throw new Error("useArchivaContext must be used within an ArchivaProvider");
|
|
14
|
+
}
|
|
15
|
+
return context;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/react/internal/ArchivaProviderClient.tsx
|
|
19
|
+
import { jsx } from "react/jsx-runtime";
|
|
20
|
+
function ArchivaProviderClient({
|
|
21
|
+
children,
|
|
22
|
+
apiBaseUrl,
|
|
23
|
+
tokenEndpoint,
|
|
24
|
+
projectId
|
|
25
|
+
}) {
|
|
26
|
+
const [tokenCache, setTokenCache] = React2.useState(null);
|
|
27
|
+
const [isRefreshing, setIsRefreshing] = React2.useState(false);
|
|
28
|
+
const refreshTimeoutRef = React2.useRef(null);
|
|
29
|
+
React2.useEffect(() => {
|
|
30
|
+
return () => {
|
|
31
|
+
if (refreshTimeoutRef.current) {
|
|
32
|
+
clearTimeout(refreshTimeoutRef.current);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}, []);
|
|
36
|
+
const fetchToken = React2.useCallback(async () => {
|
|
37
|
+
const baseUrl = tokenEndpoint.startsWith("http") ? tokenEndpoint : typeof window !== "undefined" ? `${window.location.origin}${tokenEndpoint}` : `${apiBaseUrl}${tokenEndpoint}`;
|
|
38
|
+
const url = new URL(baseUrl);
|
|
39
|
+
if (projectId) {
|
|
40
|
+
url.searchParams.set("projectId", projectId);
|
|
41
|
+
}
|
|
42
|
+
const response = await fetch(url.toString(), {
|
|
43
|
+
method: "GET",
|
|
44
|
+
credentials: "include"
|
|
45
|
+
});
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
const error = await response.json().catch(() => ({ error: "Failed to fetch token" }));
|
|
48
|
+
throw new Error(error.error || "Failed to fetch frontend token");
|
|
49
|
+
}
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
if (!data.token || !data.expiresAt) {
|
|
52
|
+
throw new Error("Invalid token response");
|
|
53
|
+
}
|
|
54
|
+
return data.token;
|
|
55
|
+
}, [tokenEndpoint, projectId, apiBaseUrl]);
|
|
56
|
+
const getToken = React2.useCallback(async () => {
|
|
57
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
58
|
+
if (tokenCache && tokenCache.expiresAt > now + 30) {
|
|
59
|
+
return tokenCache.token;
|
|
60
|
+
}
|
|
61
|
+
if (isRefreshing) {
|
|
62
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
63
|
+
return getToken();
|
|
64
|
+
}
|
|
65
|
+
setIsRefreshing(true);
|
|
66
|
+
try {
|
|
67
|
+
const token = await fetchToken();
|
|
68
|
+
const expiresAt = getTokenExpiry(token);
|
|
69
|
+
if (!expiresAt) {
|
|
70
|
+
throw new Error("Failed to parse token expiry");
|
|
71
|
+
}
|
|
72
|
+
const newCache = { token, expiresAt };
|
|
73
|
+
setTokenCache(newCache);
|
|
74
|
+
const refreshIn = Math.max(0, expiresAt - now - 30) * 1e3;
|
|
75
|
+
if (refreshTimeoutRef.current) {
|
|
76
|
+
clearTimeout(refreshTimeoutRef.current);
|
|
77
|
+
}
|
|
78
|
+
refreshTimeoutRef.current = setTimeout(() => {
|
|
79
|
+
setTokenCache(null);
|
|
80
|
+
}, refreshIn);
|
|
81
|
+
return token;
|
|
82
|
+
} finally {
|
|
83
|
+
setIsRefreshing(false);
|
|
84
|
+
}
|
|
85
|
+
}, [tokenCache, isRefreshing, fetchToken]);
|
|
86
|
+
const forceRefreshToken = React2.useCallback(async () => {
|
|
87
|
+
setTokenCache(null);
|
|
88
|
+
if (refreshTimeoutRef.current) {
|
|
89
|
+
clearTimeout(refreshTimeoutRef.current);
|
|
90
|
+
refreshTimeoutRef.current = null;
|
|
91
|
+
}
|
|
92
|
+
setIsRefreshing(true);
|
|
93
|
+
try {
|
|
94
|
+
const token = await fetchToken();
|
|
95
|
+
const expiresAt = getTokenExpiry(token);
|
|
96
|
+
if (!expiresAt) {
|
|
97
|
+
throw new Error("Failed to parse token expiry");
|
|
98
|
+
}
|
|
99
|
+
const newCache = { token, expiresAt };
|
|
100
|
+
setTokenCache(newCache);
|
|
101
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
102
|
+
const refreshIn = Math.max(0, expiresAt - now - 30) * 1e3;
|
|
103
|
+
if (refreshTimeoutRef.current) {
|
|
104
|
+
clearTimeout(refreshTimeoutRef.current);
|
|
105
|
+
}
|
|
106
|
+
refreshTimeoutRef.current = setTimeout(() => {
|
|
107
|
+
setTokenCache(null);
|
|
108
|
+
}, refreshIn);
|
|
109
|
+
return token;
|
|
110
|
+
} finally {
|
|
111
|
+
setIsRefreshing(false);
|
|
112
|
+
}
|
|
113
|
+
}, [fetchToken]);
|
|
114
|
+
const value = React2.useMemo(
|
|
115
|
+
() => ({
|
|
116
|
+
apiBaseUrl,
|
|
117
|
+
getToken,
|
|
118
|
+
forceRefreshToken,
|
|
119
|
+
projectId
|
|
120
|
+
}),
|
|
121
|
+
[apiBaseUrl, getToken, forceRefreshToken, projectId]
|
|
122
|
+
);
|
|
123
|
+
return /* @__PURE__ */ jsx(ArchivaContext.Provider, { value, children });
|
|
124
|
+
}
|
|
125
|
+
function getTokenExpiry(token) {
|
|
126
|
+
try {
|
|
127
|
+
const parts = token.split(".");
|
|
128
|
+
if (parts.length !== 3) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
const payload = JSON.parse(
|
|
132
|
+
atob(parts[1].replace(/-/g, "+").replace(/_/g, "/"))
|
|
133
|
+
);
|
|
134
|
+
return payload.exp;
|
|
135
|
+
} catch {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/react/ArchivaProvider.tsx
|
|
141
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
142
|
+
function ArchivaProvider({
|
|
143
|
+
children,
|
|
144
|
+
apiBaseUrl = "https://api.archiva.app",
|
|
145
|
+
tokenEndpoint = "/api/archiva/frontend-token",
|
|
146
|
+
projectId
|
|
147
|
+
}) {
|
|
148
|
+
if (!process.env.ARCHIVA_SECRET_KEY) {
|
|
149
|
+
throw new Error(
|
|
150
|
+
"ARCHIVA_SECRET_KEY environment variable is required. Set it in your .env.local file."
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
return /* @__PURE__ */ jsx2(
|
|
154
|
+
ArchivaProviderClient,
|
|
155
|
+
{
|
|
156
|
+
apiBaseUrl,
|
|
157
|
+
tokenEndpoint,
|
|
158
|
+
projectId,
|
|
159
|
+
children
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/react/Timeline.tsx
|
|
165
|
+
import * as React3 from "react";
|
|
166
|
+
|
|
167
|
+
// src/react/useArchiva.ts
|
|
168
|
+
function useArchiva() {
|
|
169
|
+
return useArchivaContext();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/react/Timeline.tsx
|
|
173
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
174
|
+
function formatTimestamp(timestamp) {
|
|
175
|
+
const date = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
|
|
176
|
+
return date.toLocaleDateString(void 0, {
|
|
177
|
+
month: "short",
|
|
178
|
+
day: "numeric",
|
|
179
|
+
year: "numeric",
|
|
180
|
+
hour: "numeric",
|
|
181
|
+
minute: "2-digit"
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
function eventToTimelineItem(event) {
|
|
185
|
+
return {
|
|
186
|
+
id: event.id,
|
|
187
|
+
title: event.action,
|
|
188
|
+
description: `${event.entityType} ${event.entityId}`,
|
|
189
|
+
timestamp: event.receivedAt,
|
|
190
|
+
badge: event.actorId ?? void 0,
|
|
191
|
+
data: event
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
async function fetchEventsWithRetry(apiBaseUrl, getToken, forceRefreshToken, params) {
|
|
195
|
+
const url = new URL(`${apiBaseUrl}/api/events`);
|
|
196
|
+
if (params.entityId) {
|
|
197
|
+
url.searchParams.set("entityId", params.entityId);
|
|
198
|
+
}
|
|
199
|
+
if (params.actorId) {
|
|
200
|
+
url.searchParams.set("actorId", params.actorId);
|
|
201
|
+
}
|
|
202
|
+
if (params.entityType) {
|
|
203
|
+
url.searchParams.set("entityType", params.entityType);
|
|
204
|
+
}
|
|
205
|
+
if (params.limit) {
|
|
206
|
+
url.searchParams.set("limit", String(params.limit));
|
|
207
|
+
}
|
|
208
|
+
if (params.cursor) {
|
|
209
|
+
url.searchParams.set("cursor", params.cursor);
|
|
210
|
+
}
|
|
211
|
+
const makeRequest = async (token2) => {
|
|
212
|
+
return fetch(url.toString(), {
|
|
213
|
+
headers: {
|
|
214
|
+
Authorization: `Bearer ${token2}`
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
};
|
|
218
|
+
const token = await getToken();
|
|
219
|
+
let response = await makeRequest(token);
|
|
220
|
+
if (response.status === 401 || response.status === 403) {
|
|
221
|
+
const newToken = await forceRefreshToken();
|
|
222
|
+
response = await makeRequest(newToken);
|
|
223
|
+
}
|
|
224
|
+
if (!response.ok) {
|
|
225
|
+
const error = await response.json().catch(() => ({ error: response.statusText }));
|
|
226
|
+
throw new Error(error.error || `HTTP ${response.status}`);
|
|
227
|
+
}
|
|
228
|
+
const payload = await response.json();
|
|
229
|
+
if (!payload || typeof payload !== "object" || !Array.isArray(payload.items)) {
|
|
230
|
+
throw new Error("Invalid response format");
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
items: payload.items,
|
|
234
|
+
nextCursor: typeof payload.nextCursor === "string" ? payload.nextCursor : void 0
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function Timeline({
|
|
238
|
+
entityId,
|
|
239
|
+
actorId,
|
|
240
|
+
entityType,
|
|
241
|
+
initialLimit = 25,
|
|
242
|
+
className,
|
|
243
|
+
emptyMessage = "No events yet."
|
|
244
|
+
}) {
|
|
245
|
+
const { apiBaseUrl, getToken, forceRefreshToken } = useArchiva();
|
|
246
|
+
const [items, setItems] = React3.useState([]);
|
|
247
|
+
const [cursor, setCursor] = React3.useState(void 0);
|
|
248
|
+
const [loading, setLoading] = React3.useState(false);
|
|
249
|
+
const [error, setError] = React3.useState(null);
|
|
250
|
+
const [hasMore, setHasMore] = React3.useState(false);
|
|
251
|
+
const load = React3.useCallback(
|
|
252
|
+
async (options) => {
|
|
253
|
+
setLoading(true);
|
|
254
|
+
setError(null);
|
|
255
|
+
try {
|
|
256
|
+
const params = {
|
|
257
|
+
entityId,
|
|
258
|
+
actorId,
|
|
259
|
+
entityType,
|
|
260
|
+
limit: initialLimit,
|
|
261
|
+
cursor: options?.reset ? void 0 : options?.currentCursor ?? cursor
|
|
262
|
+
};
|
|
263
|
+
const response = await fetchEventsWithRetry(
|
|
264
|
+
apiBaseUrl,
|
|
265
|
+
getToken,
|
|
266
|
+
forceRefreshToken,
|
|
267
|
+
params
|
|
268
|
+
);
|
|
269
|
+
const newItems = response.items.map(eventToTimelineItem);
|
|
270
|
+
setItems((prev) => options?.reset ? newItems : [...prev, ...newItems]);
|
|
271
|
+
setCursor(response.nextCursor);
|
|
272
|
+
setHasMore(Boolean(response.nextCursor));
|
|
273
|
+
} catch (err) {
|
|
274
|
+
setError(err.message);
|
|
275
|
+
} finally {
|
|
276
|
+
setLoading(false);
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
[entityId, actorId, entityType, initialLimit, apiBaseUrl, getToken, forceRefreshToken, cursor]
|
|
280
|
+
);
|
|
281
|
+
React3.useEffect(() => {
|
|
282
|
+
setCursor(void 0);
|
|
283
|
+
setItems([]);
|
|
284
|
+
void load({ reset: true });
|
|
285
|
+
}, [entityId, actorId, entityType]);
|
|
286
|
+
if (loading && items.length === 0) {
|
|
287
|
+
return /* @__PURE__ */ jsx3("div", { className: className || "", children: /* @__PURE__ */ jsx3("div", { children: "Loading events..." }) });
|
|
288
|
+
}
|
|
289
|
+
if (error) {
|
|
290
|
+
return /* @__PURE__ */ jsx3("div", { className: className || "", children: /* @__PURE__ */ jsxs("div", { style: { color: "red" }, children: [
|
|
291
|
+
"Error: ",
|
|
292
|
+
error
|
|
293
|
+
] }) });
|
|
294
|
+
}
|
|
295
|
+
if (items.length === 0) {
|
|
296
|
+
return /* @__PURE__ */ jsx3("div", { className: className || "", children: /* @__PURE__ */ jsx3("div", { children: emptyMessage }) });
|
|
297
|
+
}
|
|
298
|
+
return /* @__PURE__ */ jsxs("div", { className: className || "", style: { width: "100%" }, children: [
|
|
299
|
+
/* @__PURE__ */ jsx3("div", { style: { position: "relative" }, children: items.map((item, index) => /* @__PURE__ */ jsxs(
|
|
300
|
+
"div",
|
|
301
|
+
{
|
|
302
|
+
style: {
|
|
303
|
+
position: "relative",
|
|
304
|
+
display: "flex",
|
|
305
|
+
gap: "1rem",
|
|
306
|
+
paddingBottom: index < items.length - 1 ? "2rem" : "0"
|
|
307
|
+
},
|
|
308
|
+
children: [
|
|
309
|
+
index < items.length - 1 && /* @__PURE__ */ jsx3(
|
|
310
|
+
"div",
|
|
311
|
+
{
|
|
312
|
+
style: {
|
|
313
|
+
position: "absolute",
|
|
314
|
+
left: "1.25rem",
|
|
315
|
+
top: "3rem",
|
|
316
|
+
height: "calc(100% - 3rem)",
|
|
317
|
+
width: "2px",
|
|
318
|
+
backgroundColor: "#e5e7eb"
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
),
|
|
322
|
+
/* @__PURE__ */ jsx3(
|
|
323
|
+
"div",
|
|
324
|
+
{
|
|
325
|
+
style: {
|
|
326
|
+
position: "relative",
|
|
327
|
+
zIndex: 10,
|
|
328
|
+
width: "2.5rem",
|
|
329
|
+
height: "2.5rem",
|
|
330
|
+
borderRadius: "50%",
|
|
331
|
+
backgroundColor: "#f3f4f6",
|
|
332
|
+
border: "2px solid #fff",
|
|
333
|
+
display: "flex",
|
|
334
|
+
alignItems: "center",
|
|
335
|
+
justifyContent: "center",
|
|
336
|
+
flexShrink: 0
|
|
337
|
+
},
|
|
338
|
+
children: /* @__PURE__ */ jsx3(
|
|
339
|
+
"div",
|
|
340
|
+
{
|
|
341
|
+
style: {
|
|
342
|
+
width: "0.75rem",
|
|
343
|
+
height: "0.75rem",
|
|
344
|
+
borderRadius: "50%",
|
|
345
|
+
backgroundColor: "#6b7280"
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
)
|
|
349
|
+
}
|
|
350
|
+
),
|
|
351
|
+
/* @__PURE__ */ jsx3("div", { style: { flex: 1, paddingBottom: "2rem" }, children: /* @__PURE__ */ jsx3("div", { style: { display: "flex", alignItems: "start", justifyContent: "space-between", gap: "0.5rem" }, children: /* @__PURE__ */ jsxs("div", { style: { flex: 1 }, children: [
|
|
352
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
|
|
353
|
+
/* @__PURE__ */ jsx3("h4", { style: { fontWeight: 600, margin: 0 }, children: item.title }),
|
|
354
|
+
item.badge && /* @__PURE__ */ jsx3(
|
|
355
|
+
"span",
|
|
356
|
+
{
|
|
357
|
+
style: {
|
|
358
|
+
fontSize: "0.75rem",
|
|
359
|
+
padding: "0.125rem 0.5rem",
|
|
360
|
+
borderRadius: "0.375rem",
|
|
361
|
+
backgroundColor: "#f3f4f6"
|
|
362
|
+
},
|
|
363
|
+
children: item.badge
|
|
364
|
+
}
|
|
365
|
+
)
|
|
366
|
+
] }),
|
|
367
|
+
/* @__PURE__ */ jsx3("p", { style: { fontSize: "0.875rem", color: "#6b7280", margin: "0.25rem 0 0 0" }, children: formatTimestamp(item.timestamp) }),
|
|
368
|
+
item.description && /* @__PURE__ */ jsx3("p", { style: { fontSize: "0.875rem", color: "#6b7280", margin: "0.5rem 0 0 0" }, children: item.description })
|
|
369
|
+
] }) }) })
|
|
370
|
+
]
|
|
371
|
+
},
|
|
372
|
+
item.id
|
|
373
|
+
)) }),
|
|
374
|
+
hasMore && /* @__PURE__ */ jsx3("div", { style: { marginTop: "1rem" }, children: /* @__PURE__ */ jsx3(
|
|
375
|
+
"button",
|
|
376
|
+
{
|
|
377
|
+
type: "button",
|
|
378
|
+
onClick: () => load(),
|
|
379
|
+
disabled: loading,
|
|
380
|
+
style: {
|
|
381
|
+
padding: "0.5rem 1rem",
|
|
382
|
+
backgroundColor: loading ? "#d1d5db" : "#3b82f6",
|
|
383
|
+
color: "white",
|
|
384
|
+
border: "none",
|
|
385
|
+
borderRadius: "0.375rem",
|
|
386
|
+
cursor: loading ? "not-allowed" : "pointer"
|
|
387
|
+
},
|
|
388
|
+
children: loading ? "Loading..." : "Load more"
|
|
389
|
+
}
|
|
390
|
+
) })
|
|
391
|
+
] });
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export {
|
|
395
|
+
ArchivaProvider,
|
|
396
|
+
useArchiva,
|
|
397
|
+
Timeline
|
|
398
|
+
};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,19 +1,7 @@
|
|
|
1
|
+
export { ArchivaProvider, ArchivaProviderProps, Timeline, TimelineItem, TimelineProps, useArchiva } from './react/index.mjs';
|
|
1
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
3
|
import { ReactNode } from 'react';
|
|
3
4
|
|
|
4
|
-
type ArchivaProviderProps = {
|
|
5
|
-
children: ReactNode;
|
|
6
|
-
apiKey?: string;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Server-only provider component for Archiva.
|
|
10
|
-
* This component validates the API key format and provides configuration
|
|
11
|
-
* for server actions (loadEvents, createEvents).
|
|
12
|
-
*
|
|
13
|
-
* The API key should be passed via props or set as ARCHIVA_SECRET_KEY environment variable.
|
|
14
|
-
*/
|
|
15
|
-
declare function ArchivaProvider({ children }: ArchivaProviderProps): react_jsx_runtime.JSX.Element;
|
|
16
|
-
|
|
17
5
|
type EventChange = {
|
|
18
6
|
op: "set" | "unset" | "add" | "remove" | "replace" | string;
|
|
19
7
|
path: string;
|
|
@@ -70,6 +58,27 @@ declare class ArchivaError extends Error {
|
|
|
70
58
|
});
|
|
71
59
|
}
|
|
72
60
|
|
|
61
|
+
type ArchivaProviderProps = {
|
|
62
|
+
children: ReactNode;
|
|
63
|
+
apiKey?: string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Server component wrapper that reads ARCHIVA_SECRET_KEY from environment
|
|
67
|
+
* and passes it to the client provider.
|
|
68
|
+
*
|
|
69
|
+
* The API key can be:
|
|
70
|
+
* - Passed via props (takes precedence)
|
|
71
|
+
* - Set as ARCHIVA_SECRET_KEY environment variable (automatically read)
|
|
72
|
+
*
|
|
73
|
+
* Child components like Timeline will automatically use the API key from this context.
|
|
74
|
+
*/
|
|
75
|
+
declare function ArchivaProvider({ children, apiKey }: ArchivaProviderProps): react_jsx_runtime.JSX.Element;
|
|
76
|
+
|
|
77
|
+
type ArchivaContextValue = {
|
|
78
|
+
apiKey: string | undefined;
|
|
79
|
+
};
|
|
80
|
+
declare function useArchivaContext(): ArchivaContextValue;
|
|
81
|
+
|
|
73
82
|
/**
|
|
74
83
|
* Server action to load audit events
|
|
75
84
|
*
|
|
@@ -118,8 +127,7 @@ type TimelineProps = {
|
|
|
118
127
|
initialLimit?: number;
|
|
119
128
|
className?: string;
|
|
120
129
|
emptyMessage?: string;
|
|
121
|
-
apiKey?: string;
|
|
122
130
|
};
|
|
123
|
-
declare function Timeline({ entityId, actorId, entityType, initialLimit, className, emptyMessage,
|
|
131
|
+
declare function Timeline({ entityId, actorId, entityType, initialLimit, className, emptyMessage, }: TimelineProps): react_jsx_runtime.JSX.Element;
|
|
124
132
|
|
|
125
|
-
export { ArchivaError, ArchivaProvider, type ArchivaProviderProps, type AuditEventListItem, type CreateEventInput, type CreateEventOptions, type EventChange, type LoadEventsParams, type PageResult,
|
|
133
|
+
export { ArchivaError, ArchivaProvider as ArchivaProviderLegacy, type ArchivaProviderProps as ArchivaProviderPropsLegacy, type AuditEventListItem, type CreateEventInput, type CreateEventOptions, type EventChange, type LoadEventsParams, type PageResult, type TimelineItem as TimelineItemLegacy, Timeline as TimelineLegacy, type TimelineProps as TimelinePropsLegacy, createEvent, createEvents, loadEvents, useArchivaContext };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,7 @@
|
|
|
1
|
+
export { ArchivaProvider, ArchivaProviderProps, Timeline, TimelineItem, TimelineProps, useArchiva } from './react/index.js';
|
|
1
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
3
|
import { ReactNode } from 'react';
|
|
3
4
|
|
|
4
|
-
type ArchivaProviderProps = {
|
|
5
|
-
children: ReactNode;
|
|
6
|
-
apiKey?: string;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Server-only provider component for Archiva.
|
|
10
|
-
* This component validates the API key format and provides configuration
|
|
11
|
-
* for server actions (loadEvents, createEvents).
|
|
12
|
-
*
|
|
13
|
-
* The API key should be passed via props or set as ARCHIVA_SECRET_KEY environment variable.
|
|
14
|
-
*/
|
|
15
|
-
declare function ArchivaProvider({ children }: ArchivaProviderProps): react_jsx_runtime.JSX.Element;
|
|
16
|
-
|
|
17
5
|
type EventChange = {
|
|
18
6
|
op: "set" | "unset" | "add" | "remove" | "replace" | string;
|
|
19
7
|
path: string;
|
|
@@ -70,6 +58,27 @@ declare class ArchivaError extends Error {
|
|
|
70
58
|
});
|
|
71
59
|
}
|
|
72
60
|
|
|
61
|
+
type ArchivaProviderProps = {
|
|
62
|
+
children: ReactNode;
|
|
63
|
+
apiKey?: string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Server component wrapper that reads ARCHIVA_SECRET_KEY from environment
|
|
67
|
+
* and passes it to the client provider.
|
|
68
|
+
*
|
|
69
|
+
* The API key can be:
|
|
70
|
+
* - Passed via props (takes precedence)
|
|
71
|
+
* - Set as ARCHIVA_SECRET_KEY environment variable (automatically read)
|
|
72
|
+
*
|
|
73
|
+
* Child components like Timeline will automatically use the API key from this context.
|
|
74
|
+
*/
|
|
75
|
+
declare function ArchivaProvider({ children, apiKey }: ArchivaProviderProps): react_jsx_runtime.JSX.Element;
|
|
76
|
+
|
|
77
|
+
type ArchivaContextValue = {
|
|
78
|
+
apiKey: string | undefined;
|
|
79
|
+
};
|
|
80
|
+
declare function useArchivaContext(): ArchivaContextValue;
|
|
81
|
+
|
|
73
82
|
/**
|
|
74
83
|
* Server action to load audit events
|
|
75
84
|
*
|
|
@@ -118,8 +127,7 @@ type TimelineProps = {
|
|
|
118
127
|
initialLimit?: number;
|
|
119
128
|
className?: string;
|
|
120
129
|
emptyMessage?: string;
|
|
121
|
-
apiKey?: string;
|
|
122
130
|
};
|
|
123
|
-
declare function Timeline({ entityId, actorId, entityType, initialLimit, className, emptyMessage,
|
|
131
|
+
declare function Timeline({ entityId, actorId, entityType, initialLimit, className, emptyMessage, }: TimelineProps): react_jsx_runtime.JSX.Element;
|
|
124
132
|
|
|
125
|
-
export { ArchivaError, ArchivaProvider, type ArchivaProviderProps, type AuditEventListItem, type CreateEventInput, type CreateEventOptions, type EventChange, type LoadEventsParams, type PageResult,
|
|
133
|
+
export { ArchivaError, ArchivaProvider as ArchivaProviderLegacy, type ArchivaProviderProps as ArchivaProviderPropsLegacy, type AuditEventListItem, type CreateEventInput, type CreateEventOptions, type EventChange, type LoadEventsParams, type PageResult, type TimelineItem as TimelineItemLegacy, Timeline as TimelineLegacy, type TimelineProps as TimelinePropsLegacy, createEvent, createEvents, loadEvents, useArchivaContext };
|