@archiva/archiva-nextjs 0.1.5 → 0.1.6

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,11 @@
1
+ "use client";
2
+ import {
3
+ ArchivaContext,
4
+ ArchivaProviderClient,
5
+ useArchivaContext
6
+ } from "./chunk-H4TGL57C.mjs";
7
+ export {
8
+ ArchivaContext,
9
+ ArchivaProviderClient,
10
+ useArchivaContext
11
+ };
@@ -0,0 +1,136 @@
1
+ // src/react/internal/ArchivaProviderClient.tsx
2
+ import * as React from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ var ArchivaContext = React.createContext(void 0);
5
+ function ArchivaProviderClient({
6
+ children,
7
+ apiBaseUrl,
8
+ tokenEndpoint,
9
+ projectId
10
+ }) {
11
+ const [tokenCache, setTokenCache] = React.useState(null);
12
+ const [isRefreshing, setIsRefreshing] = React.useState(false);
13
+ const refreshTimeoutRef = React.useRef(null);
14
+ React.useEffect(() => {
15
+ return () => {
16
+ if (refreshTimeoutRef.current) {
17
+ clearTimeout(refreshTimeoutRef.current);
18
+ }
19
+ };
20
+ }, []);
21
+ const fetchToken = React.useCallback(async () => {
22
+ const baseUrl = tokenEndpoint.startsWith("http") ? tokenEndpoint : typeof window !== "undefined" ? `${window.location.origin}${tokenEndpoint}` : `${apiBaseUrl}${tokenEndpoint}`;
23
+ const url = new URL(baseUrl);
24
+ if (projectId) {
25
+ url.searchParams.set("projectId", projectId);
26
+ }
27
+ const response = await fetch(url.toString(), {
28
+ method: "GET",
29
+ credentials: "include"
30
+ });
31
+ if (!response.ok) {
32
+ const error = await response.json().catch(() => ({ error: "Failed to fetch token" }));
33
+ throw new Error(error.error || "Failed to fetch frontend token");
34
+ }
35
+ const data = await response.json();
36
+ if (!data.token || !data.expiresAt) {
37
+ throw new Error("Invalid token response");
38
+ }
39
+ return data.token;
40
+ }, [tokenEndpoint, projectId, apiBaseUrl]);
41
+ const getToken = React.useCallback(async () => {
42
+ const now = Math.floor(Date.now() / 1e3);
43
+ if (tokenCache && tokenCache.expiresAt > now + 30) {
44
+ return tokenCache.token;
45
+ }
46
+ if (isRefreshing) {
47
+ await new Promise((resolve) => setTimeout(resolve, 100));
48
+ return getToken();
49
+ }
50
+ setIsRefreshing(true);
51
+ try {
52
+ const token = await fetchToken();
53
+ const expiresAt = getTokenExpiry(token);
54
+ if (!expiresAt) {
55
+ throw new Error("Failed to parse token expiry");
56
+ }
57
+ const newCache = { token, expiresAt };
58
+ setTokenCache(newCache);
59
+ const refreshIn = Math.max(0, expiresAt - now - 30) * 1e3;
60
+ if (refreshTimeoutRef.current) {
61
+ clearTimeout(refreshTimeoutRef.current);
62
+ }
63
+ refreshTimeoutRef.current = setTimeout(() => {
64
+ setTokenCache(null);
65
+ }, refreshIn);
66
+ return token;
67
+ } finally {
68
+ setIsRefreshing(false);
69
+ }
70
+ }, [tokenCache, isRefreshing, fetchToken]);
71
+ const forceRefreshToken = React.useCallback(async () => {
72
+ setTokenCache(null);
73
+ if (refreshTimeoutRef.current) {
74
+ clearTimeout(refreshTimeoutRef.current);
75
+ refreshTimeoutRef.current = null;
76
+ }
77
+ setIsRefreshing(true);
78
+ try {
79
+ const token = await fetchToken();
80
+ const expiresAt = getTokenExpiry(token);
81
+ if (!expiresAt) {
82
+ throw new Error("Failed to parse token expiry");
83
+ }
84
+ const newCache = { token, expiresAt };
85
+ setTokenCache(newCache);
86
+ const now = Math.floor(Date.now() / 1e3);
87
+ const refreshIn = Math.max(0, expiresAt - now - 30) * 1e3;
88
+ if (refreshTimeoutRef.current) {
89
+ clearTimeout(refreshTimeoutRef.current);
90
+ }
91
+ refreshTimeoutRef.current = setTimeout(() => {
92
+ setTokenCache(null);
93
+ }, refreshIn);
94
+ return token;
95
+ } finally {
96
+ setIsRefreshing(false);
97
+ }
98
+ }, [fetchToken]);
99
+ const value = React.useMemo(
100
+ () => ({
101
+ apiBaseUrl,
102
+ getToken,
103
+ forceRefreshToken,
104
+ projectId
105
+ }),
106
+ [apiBaseUrl, getToken, forceRefreshToken, projectId]
107
+ );
108
+ return /* @__PURE__ */ jsx(ArchivaContext.Provider, { value, children });
109
+ }
110
+ function useArchivaContext() {
111
+ const context = React.useContext(ArchivaContext);
112
+ if (context === void 0) {
113
+ throw new Error("useArchivaContext must be used within an ArchivaProvider");
114
+ }
115
+ return context;
116
+ }
117
+ function getTokenExpiry(token) {
118
+ try {
119
+ const parts = token.split(".");
120
+ if (parts.length !== 3) {
121
+ return null;
122
+ }
123
+ const payload = JSON.parse(
124
+ atob(parts[1].replace(/-/g, "+").replace(/_/g, "/"))
125
+ );
126
+ return payload.exp;
127
+ } catch {
128
+ return null;
129
+ }
130
+ }
131
+
132
+ export {
133
+ ArchivaContext,
134
+ ArchivaProviderClient,
135
+ useArchivaContext
136
+ };
@@ -0,0 +1,41 @@
1
+ // src/react/ArchivaProvider.tsx
2
+ import "server-only";
3
+
4
+ // src/react/internal/ArchivaProviderWrapper.tsx
5
+ import { use } from "react";
6
+ import { jsx } from "react/jsx-runtime";
7
+ var ArchivaProviderClientPromise = import("./ArchivaProviderClient-FQAPZXQF.mjs").then(
8
+ (mod) => mod.ArchivaProviderClient
9
+ );
10
+ function ArchivaProviderWrapper(props) {
11
+ const ArchivaProviderClient = use(ArchivaProviderClientPromise);
12
+ return /* @__PURE__ */ jsx(ArchivaProviderClient, { ...props });
13
+ }
14
+
15
+ // src/react/ArchivaProvider.tsx
16
+ import { jsx as jsx2 } from "react/jsx-runtime";
17
+ function ArchivaProvider({
18
+ children,
19
+ apiBaseUrl = "https://api.archiva.app",
20
+ tokenEndpoint = "/api/archiva/frontend-token",
21
+ projectId
22
+ }) {
23
+ if (!process.env.ARCHIVA_SECRET_KEY) {
24
+ throw new Error(
25
+ "ARCHIVA_SECRET_KEY environment variable is required. Set it in your .env.local file."
26
+ );
27
+ }
28
+ return /* @__PURE__ */ jsx2(
29
+ ArchivaProviderWrapper,
30
+ {
31
+ apiBaseUrl,
32
+ tokenEndpoint,
33
+ projectId,
34
+ children
35
+ }
36
+ );
37
+ }
38
+
39
+ export {
40
+ ArchivaProvider
41
+ };
package/dist/index.js CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,43 +30,30 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
30
- // src/index.tsx
31
- var index_exports = {};
32
- __export(index_exports, {
33
- ArchivaError: () => ArchivaError,
34
- ArchivaProvider: () => ArchivaProvider
35
- });
36
- module.exports = __toCommonJS(index_exports);
37
-
38
- // src/react/ArchivaProvider.tsx
39
- var import_server_only = require("server-only");
40
-
41
- // src/react/internal/ArchivaProviderClient.tsx
42
- var React2 = __toESM(require("react"));
43
-
44
- // src/react/context.tsx
45
- var React = __toESM(require("react"));
46
- var ArchivaContext = React.createContext(void 0);
47
-
48
33
  // src/react/internal/ArchivaProviderClient.tsx
49
- var import_jsx_runtime = require("react/jsx-runtime");
34
+ var ArchivaProviderClient_exports = {};
35
+ __export(ArchivaProviderClient_exports, {
36
+ ArchivaContext: () => ArchivaContext,
37
+ ArchivaProviderClient: () => ArchivaProviderClient,
38
+ useArchivaContext: () => useArchivaContext
39
+ });
50
40
  function ArchivaProviderClient({
51
41
  children,
52
42
  apiBaseUrl,
53
43
  tokenEndpoint,
54
44
  projectId
55
45
  }) {
56
- const [tokenCache, setTokenCache] = React2.useState(null);
57
- const [isRefreshing, setIsRefreshing] = React2.useState(false);
58
- const refreshTimeoutRef = React2.useRef(null);
59
- React2.useEffect(() => {
46
+ const [tokenCache, setTokenCache] = React.useState(null);
47
+ const [isRefreshing, setIsRefreshing] = React.useState(false);
48
+ const refreshTimeoutRef = React.useRef(null);
49
+ React.useEffect(() => {
60
50
  return () => {
61
51
  if (refreshTimeoutRef.current) {
62
52
  clearTimeout(refreshTimeoutRef.current);
63
53
  }
64
54
  };
65
55
  }, []);
66
- const fetchToken = React2.useCallback(async () => {
56
+ const fetchToken = React.useCallback(async () => {
67
57
  const baseUrl = tokenEndpoint.startsWith("http") ? tokenEndpoint : typeof window !== "undefined" ? `${window.location.origin}${tokenEndpoint}` : `${apiBaseUrl}${tokenEndpoint}`;
68
58
  const url = new URL(baseUrl);
69
59
  if (projectId) {
@@ -83,7 +73,7 @@ function ArchivaProviderClient({
83
73
  }
84
74
  return data.token;
85
75
  }, [tokenEndpoint, projectId, apiBaseUrl]);
86
- const getToken = React2.useCallback(async () => {
76
+ const getToken = React.useCallback(async () => {
87
77
  const now = Math.floor(Date.now() / 1e3);
88
78
  if (tokenCache && tokenCache.expiresAt > now + 30) {
89
79
  return tokenCache.token;
@@ -113,7 +103,7 @@ function ArchivaProviderClient({
113
103
  setIsRefreshing(false);
114
104
  }
115
105
  }, [tokenCache, isRefreshing, fetchToken]);
116
- const forceRefreshToken = React2.useCallback(async () => {
106
+ const forceRefreshToken = React.useCallback(async () => {
117
107
  setTokenCache(null);
118
108
  if (refreshTimeoutRef.current) {
119
109
  clearTimeout(refreshTimeoutRef.current);
@@ -141,7 +131,7 @@ function ArchivaProviderClient({
141
131
  setIsRefreshing(false);
142
132
  }
143
133
  }, [fetchToken]);
144
- const value = React2.useMemo(
134
+ const value = React.useMemo(
145
135
  () => ({
146
136
  apiBaseUrl,
147
137
  getToken,
@@ -152,6 +142,13 @@ function ArchivaProviderClient({
152
142
  );
153
143
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchivaContext.Provider, { value, children });
154
144
  }
145
+ function useArchivaContext() {
146
+ const context = React.useContext(ArchivaContext);
147
+ if (context === void 0) {
148
+ throw new Error("useArchivaContext must be used within an ArchivaProvider");
149
+ }
150
+ return context;
151
+ }
155
152
  function getTokenExpiry(token) {
156
153
  try {
157
154
  const parts = token.split(".");
@@ -166,9 +163,41 @@ function getTokenExpiry(token) {
166
163
  return null;
167
164
  }
168
165
  }
166
+ var React, import_jsx_runtime, ArchivaContext;
167
+ var init_ArchivaProviderClient = __esm({
168
+ "src/react/internal/ArchivaProviderClient.tsx"() {
169
+ "use strict";
170
+ "use client";
171
+ React = __toESM(require("react"));
172
+ import_jsx_runtime = require("react/jsx-runtime");
173
+ ArchivaContext = React.createContext(void 0);
174
+ }
175
+ });
176
+
177
+ // src/index.tsx
178
+ var index_exports = {};
179
+ __export(index_exports, {
180
+ ArchivaError: () => ArchivaError,
181
+ ArchivaProvider: () => ArchivaProvider
182
+ });
183
+ module.exports = __toCommonJS(index_exports);
169
184
 
170
185
  // src/react/ArchivaProvider.tsx
186
+ var import_server_only = require("server-only");
187
+
188
+ // src/react/internal/ArchivaProviderWrapper.tsx
189
+ var import_react = require("react");
171
190
  var import_jsx_runtime2 = require("react/jsx-runtime");
191
+ var ArchivaProviderClientPromise = Promise.resolve().then(() => (init_ArchivaProviderClient(), ArchivaProviderClient_exports)).then(
192
+ (mod) => mod.ArchivaProviderClient
193
+ );
194
+ function ArchivaProviderWrapper(props) {
195
+ const ArchivaProviderClient2 = (0, import_react.use)(ArchivaProviderClientPromise);
196
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ArchivaProviderClient2, { ...props });
197
+ }
198
+
199
+ // src/react/ArchivaProvider.tsx
200
+ var import_jsx_runtime3 = require("react/jsx-runtime");
172
201
  function ArchivaProvider({
173
202
  children,
174
203
  apiBaseUrl = "https://api.archiva.app",
@@ -180,8 +209,8 @@ function ArchivaProvider({
180
209
  "ARCHIVA_SECRET_KEY environment variable is required. Set it in your .env.local file."
181
210
  );
182
211
  }
183
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
184
- ArchivaProviderClient,
212
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
213
+ ArchivaProviderWrapper,
185
214
  {
186
215
  apiBaseUrl,
187
216
  tokenEndpoint,
package/dist/index.mjs CHANGED
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  ArchivaProvider
3
- } from "./chunk-OSBJW2ZH.mjs";
4
- import "./chunk-XZUDW4PU.mjs";
3
+ } from "./chunk-IUNSB4PF.mjs";
5
4
 
6
5
  // src/types.ts
7
6
  var ArchivaError = class extends Error {
@@ -39,8 +39,9 @@ module.exports = __toCommonJS(client_exports);
39
39
  // src/react/Timeline.tsx
40
40
  var React2 = __toESM(require("react"));
41
41
 
42
- // src/react/context.tsx
42
+ // src/react/internal/ArchivaProviderClient.tsx
43
43
  var React = __toESM(require("react"));
44
+ var import_jsx_runtime = require("react/jsx-runtime");
44
45
  var ArchivaContext = React.createContext(void 0);
45
46
  function useArchivaContext() {
46
47
  const context = React.useContext(ArchivaContext);
@@ -56,7 +57,7 @@ function useArchiva() {
56
57
  }
57
58
 
58
59
  // src/react/Timeline.tsx
59
- var import_jsx_runtime = require("react/jsx-runtime");
60
+ var import_jsx_runtime2 = require("react/jsx-runtime");
60
61
  function formatTimestamp(timestamp) {
61
62
  const date = typeof timestamp === "string" ? new Date(timestamp) : timestamp;
62
63
  return date.toLocaleDateString(void 0, {
@@ -170,19 +171,19 @@ function Timeline({
170
171
  void load({ reset: true });
171
172
  }, [entityId, actorId, entityType]);
172
173
  if (loading && items.length === 0) {
173
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: className || "", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: "Loading events..." }) });
174
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: className || "", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: "Loading events..." }) });
174
175
  }
175
176
  if (error) {
176
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: className || "", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { color: "red" }, children: [
177
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: className || "", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { color: "red" }, children: [
177
178
  "Error: ",
178
179
  error
179
180
  ] }) });
180
181
  }
181
182
  if (items.length === 0) {
182
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: className || "", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: emptyMessage }) });
183
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: className || "", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: emptyMessage }) });
183
184
  }
184
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: className || "", style: { width: "100%" }, children: [
185
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "relative" }, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
185
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: className || "", style: { width: "100%" }, children: [
186
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { position: "relative" }, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
186
187
  "div",
187
188
  {
188
189
  style: {
@@ -192,7 +193,7 @@ function Timeline({
192
193
  paddingBottom: index < items.length - 1 ? "2rem" : "0"
193
194
  },
194
195
  children: [
195
- index < items.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
196
+ index < items.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
196
197
  "div",
197
198
  {
198
199
  style: {
@@ -205,7 +206,7 @@ function Timeline({
205
206
  }
206
207
  }
207
208
  ),
208
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
209
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
209
210
  "div",
210
211
  {
211
212
  style: {
@@ -221,7 +222,7 @@ function Timeline({
221
222
  justifyContent: "center",
222
223
  flexShrink: 0
223
224
  },
224
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
225
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
225
226
  "div",
226
227
  {
227
228
  style: {
@@ -234,10 +235,10 @@ function Timeline({
234
235
  )
235
236
  }
236
237
  ),
237
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, paddingBottom: "2rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", alignItems: "start", justifyContent: "space-between", gap: "0.5rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { flex: 1 }, children: [
238
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
239
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", { style: { fontWeight: 600, margin: 0 }, children: item.title }),
240
- item.badge && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
238
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { flex: 1, paddingBottom: "2rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", alignItems: "start", justifyContent: "space-between", gap: "0.5rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { flex: 1 }, children: [
239
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
240
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { style: { fontWeight: 600, margin: 0 }, children: item.title }),
241
+ item.badge && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
241
242
  "span",
242
243
  {
243
244
  style: {
@@ -250,14 +251,14 @@ function Timeline({
250
251
  }
251
252
  )
252
253
  ] }),
253
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: "0.875rem", color: "#6b7280", margin: "0.25rem 0 0 0" }, children: formatTimestamp(item.timestamp) }),
254
- item.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: "0.875rem", color: "#6b7280", margin: "0.5rem 0 0 0" }, children: item.description })
254
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: "0.875rem", color: "#6b7280", margin: "0.25rem 0 0 0" }, children: formatTimestamp(item.timestamp) }),
255
+ item.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: "0.875rem", color: "#6b7280", margin: "0.5rem 0 0 0" }, children: item.description })
255
256
  ] }) }) })
256
257
  ]
257
258
  },
258
259
  item.id
259
260
  )) }),
260
- hasMore && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginTop: "1rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
261
+ hasMore && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { marginTop: "1rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
261
262
  "button",
262
263
  {
263
264
  type: "button",
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  useArchivaContext
4
- } from "../chunk-XZUDW4PU.mjs";
4
+ } from "../chunk-H4TGL57C.mjs";
5
5
 
6
6
  // src/react/Timeline.tsx
7
7
  import * as React from "react";
@@ -12,6 +12,9 @@ type ArchivaProviderProps = {
12
12
  *
13
13
  * Validates ARCHIVA_SECRET_KEY exists and renders the client provider.
14
14
  * Never exposes secrets to the client.
15
+ *
16
+ * The wrapper uses dynamic import internally to prevent createContext
17
+ * evaluation during server module loading.
15
18
  */
16
19
  declare function ArchivaProvider({ children, apiBaseUrl, tokenEndpoint, projectId, }: ArchivaProviderProps): react_jsx_runtime.JSX.Element;
17
20
 
@@ -12,6 +12,9 @@ type ArchivaProviderProps = {
12
12
  *
13
13
  * Validates ARCHIVA_SECRET_KEY exists and renders the client provider.
14
14
  * Never exposes secrets to the client.
15
+ *
16
+ * The wrapper uses dynamic import internally to prevent createContext
17
+ * evaluation during server module loading.
15
18
  */
16
19
  declare function ArchivaProvider({ children, apiBaseUrl, tokenEndpoint, projectId, }: ArchivaProviderProps): react_jsx_runtime.JSX.Element;
17
20
 
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,42 +30,30 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
30
- // src/react/index.ts
31
- var react_exports = {};
32
- __export(react_exports, {
33
- ArchivaProvider: () => ArchivaProvider
34
- });
35
- module.exports = __toCommonJS(react_exports);
36
-
37
- // src/react/ArchivaProvider.tsx
38
- var import_server_only = require("server-only");
39
-
40
- // src/react/internal/ArchivaProviderClient.tsx
41
- var React2 = __toESM(require("react"));
42
-
43
- // src/react/context.tsx
44
- var React = __toESM(require("react"));
45
- var ArchivaContext = React.createContext(void 0);
46
-
47
33
  // src/react/internal/ArchivaProviderClient.tsx
48
- var import_jsx_runtime = require("react/jsx-runtime");
34
+ var ArchivaProviderClient_exports = {};
35
+ __export(ArchivaProviderClient_exports, {
36
+ ArchivaContext: () => ArchivaContext,
37
+ ArchivaProviderClient: () => ArchivaProviderClient,
38
+ useArchivaContext: () => useArchivaContext
39
+ });
49
40
  function ArchivaProviderClient({
50
41
  children,
51
42
  apiBaseUrl,
52
43
  tokenEndpoint,
53
44
  projectId
54
45
  }) {
55
- const [tokenCache, setTokenCache] = React2.useState(null);
56
- const [isRefreshing, setIsRefreshing] = React2.useState(false);
57
- const refreshTimeoutRef = React2.useRef(null);
58
- React2.useEffect(() => {
46
+ const [tokenCache, setTokenCache] = React.useState(null);
47
+ const [isRefreshing, setIsRefreshing] = React.useState(false);
48
+ const refreshTimeoutRef = React.useRef(null);
49
+ React.useEffect(() => {
59
50
  return () => {
60
51
  if (refreshTimeoutRef.current) {
61
52
  clearTimeout(refreshTimeoutRef.current);
62
53
  }
63
54
  };
64
55
  }, []);
65
- const fetchToken = React2.useCallback(async () => {
56
+ const fetchToken = React.useCallback(async () => {
66
57
  const baseUrl = tokenEndpoint.startsWith("http") ? tokenEndpoint : typeof window !== "undefined" ? `${window.location.origin}${tokenEndpoint}` : `${apiBaseUrl}${tokenEndpoint}`;
67
58
  const url = new URL(baseUrl);
68
59
  if (projectId) {
@@ -82,7 +73,7 @@ function ArchivaProviderClient({
82
73
  }
83
74
  return data.token;
84
75
  }, [tokenEndpoint, projectId, apiBaseUrl]);
85
- const getToken = React2.useCallback(async () => {
76
+ const getToken = React.useCallback(async () => {
86
77
  const now = Math.floor(Date.now() / 1e3);
87
78
  if (tokenCache && tokenCache.expiresAt > now + 30) {
88
79
  return tokenCache.token;
@@ -112,7 +103,7 @@ function ArchivaProviderClient({
112
103
  setIsRefreshing(false);
113
104
  }
114
105
  }, [tokenCache, isRefreshing, fetchToken]);
115
- const forceRefreshToken = React2.useCallback(async () => {
106
+ const forceRefreshToken = React.useCallback(async () => {
116
107
  setTokenCache(null);
117
108
  if (refreshTimeoutRef.current) {
118
109
  clearTimeout(refreshTimeoutRef.current);
@@ -140,7 +131,7 @@ function ArchivaProviderClient({
140
131
  setIsRefreshing(false);
141
132
  }
142
133
  }, [fetchToken]);
143
- const value = React2.useMemo(
134
+ const value = React.useMemo(
144
135
  () => ({
145
136
  apiBaseUrl,
146
137
  getToken,
@@ -151,6 +142,13 @@ function ArchivaProviderClient({
151
142
  );
152
143
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchivaContext.Provider, { value, children });
153
144
  }
145
+ function useArchivaContext() {
146
+ const context = React.useContext(ArchivaContext);
147
+ if (context === void 0) {
148
+ throw new Error("useArchivaContext must be used within an ArchivaProvider");
149
+ }
150
+ return context;
151
+ }
154
152
  function getTokenExpiry(token) {
155
153
  try {
156
154
  const parts = token.split(".");
@@ -165,9 +163,40 @@ function getTokenExpiry(token) {
165
163
  return null;
166
164
  }
167
165
  }
166
+ var React, import_jsx_runtime, ArchivaContext;
167
+ var init_ArchivaProviderClient = __esm({
168
+ "src/react/internal/ArchivaProviderClient.tsx"() {
169
+ "use strict";
170
+ "use client";
171
+ React = __toESM(require("react"));
172
+ import_jsx_runtime = require("react/jsx-runtime");
173
+ ArchivaContext = React.createContext(void 0);
174
+ }
175
+ });
176
+
177
+ // src/react/index.ts
178
+ var react_exports = {};
179
+ __export(react_exports, {
180
+ ArchivaProvider: () => ArchivaProvider
181
+ });
182
+ module.exports = __toCommonJS(react_exports);
168
183
 
169
184
  // src/react/ArchivaProvider.tsx
185
+ var import_server_only = require("server-only");
186
+
187
+ // src/react/internal/ArchivaProviderWrapper.tsx
188
+ var import_react = require("react");
170
189
  var import_jsx_runtime2 = require("react/jsx-runtime");
190
+ var ArchivaProviderClientPromise = Promise.resolve().then(() => (init_ArchivaProviderClient(), ArchivaProviderClient_exports)).then(
191
+ (mod) => mod.ArchivaProviderClient
192
+ );
193
+ function ArchivaProviderWrapper(props) {
194
+ const ArchivaProviderClient2 = (0, import_react.use)(ArchivaProviderClientPromise);
195
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ArchivaProviderClient2, { ...props });
196
+ }
197
+
198
+ // src/react/ArchivaProvider.tsx
199
+ var import_jsx_runtime3 = require("react/jsx-runtime");
171
200
  function ArchivaProvider({
172
201
  children,
173
202
  apiBaseUrl = "https://api.archiva.app",
@@ -179,8 +208,8 @@ function ArchivaProvider({
179
208
  "ARCHIVA_SECRET_KEY environment variable is required. Set it in your .env.local file."
180
209
  );
181
210
  }
182
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
183
- ArchivaProviderClient,
211
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
212
+ ArchivaProviderWrapper,
184
213
  {
185
214
  apiBaseUrl,
186
215
  tokenEndpoint,
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  ArchivaProvider
3
- } from "../chunk-OSBJW2ZH.mjs";
4
- import "../chunk-XZUDW4PU.mjs";
3
+ } from "../chunk-IUNSB4PF.mjs";
5
4
  export {
6
5
  ArchivaProvider
7
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archiva/archiva-nextjs",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Archiva Next.js SDK - Server Actions and Timeline Component",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",